#`cli.Run`
1 messages Β· Page 1 of 1 (latest)
Hi @hollow briar,
Here is an example: https://github.com/dagger/dagger/blob/main/docs/tests/use-cases/go-docker-swarm/full/particubes.docs.cue#L103-L117
grazi !
would be nice if there was a nice wrapper around all of the cli.#Run docker arguments tho instead of having to build up a string/array for the command... so it worked like the more traditional docker.#Run
i guess if i knew enough Cue i could probably build my own action to wrap it
We could work this out together if you want π
What concept do you feel missing atm ? What would you have love ramping up on ? This could make a nice docs page
well basically, docker.#Run has params for mounts and such, it'd be nice to have something that wrapped cli.#Run that didn't take an arbitrary "docker run" command but actually constructed the docker run string itself based on the higher level params that docker.#Run uses
if that makes any sense lol
in my case, it looks like i have to build an extensive command string with "sh -c" that in turns launches docker run that also runs a complicated "sh -c" string as it's own command thus making the whole thing quite messy ... i mean i guess i could wrap things in bash scripts but i was hoping to avoid that
I think I understand what you mean: having more fields when querying cli.#Run to actually directly create the docker run command. To start with that, the easiest is to play with the playground and try to see how to construct the final string: https://cuelang.org/play/?id=BoVsTJ0jB9m#cue@export@cue
An example, there are other ways to do it
that looks intriguing
Why do you need an inception ?
inception ?
you'll have to excuse me, i only just began my second coffee this morning π
Sorry, a docker run sh -c running a docker run sh -c, that you mentioned above. No worries, I sometimes have my own references, that no one else understand π€£
hehe ... i'm trying to achieve bi-directional volume mounts so that whatever the docker container builds can be accessed outside of dagger
and that's when someone suggested i stop using docker.#Run and use cli.#Run instead
basically i wrote https://gist.github.com/rockyburt/f4c780797d1bd259a7a210a91821e8ca ... and when dagger do finishes running i was hoping to be able to access .build/requirements.txt locally outside of dagger
Yes, so: the cli.#Run interacts with the docker daemon. It's a client for your common docker daemon, as he shall have mentioned, it's not possible to have these kind of mounts in Buildkit atm.
You can directly use cli.#Run as you would with docker. You'll only need one sh -c, as it's going to be directly run against your local docker daemon (if it's the one you mount)
right - so i'm playing with it now, is there any way for me to see the docker output of the cli.#Run command ?
One thing though, with Dagger, you can write to the local fs the output of an action. We do it here: https://github.com/dagger/dagger/blob/a3445960e8522121c9a9f9395093f11614b65a14/docs/tests/use-cases/go-docker-swarm/full/particubes.docs.cue#L22. So it's not a mount, but whether an action finishes, and as everything is an image and per se an fs, you can export it. We do it here, with actions.build.image.rootfs
.build/requirements.txt locally outside of dagger
@hollow briar is this the important part to access outside of Dagger?
yeah i was hoping to avoid having to export in this particular scenario due to the fact that there will be a lot of data built and i'd like to be able to transfer the result of data for testing purposes
not really, the important part will be to access the wheels that generated from requirements.txt
the more i discuss these things here, the more it seems i'm trying to "work against" the nature of dagger.io by having realtime bidirectional mounts and that i should just use import/exports as necessary instead
and i should simply "trust" dagger.io to do the right things speedily π
fyi i'm trying to reproduce my fairly large Makefile+bashscripts system in a dagger fashion
I was wondering what would be the simplest scenario we could all get working together.
I'm thinking if we have a builder docker image (or its Dockerfile), plus whatever is needed to build an actual wheel.
so here's what i'm ultimately trying to accomplish boiled down...
- create a new python-based image with developer deps installed and python poetry
- launch new container using the built image that generates requirements and then downloads/builds all necessary python wheels
- create my real image that is bare bones python and sets up a virtualenv using the wheels artifacts from #2 (so it doesn't have to go out to the network)
i'm basically also trying to prevent my Dockerfile's from having to reach out to the network
my standard way of handling the artifacts was the basically store them locally via standard docker mounts (bi-directional)
i'm basically also trying to prevent my Dockerfile's from having to reach out to the network
For performance? Air gapped?
yes and yes
i don't want a Dockerfile to have to worry that a pypi registry where wheels are stored is offline, having problems, missing the latest version i need
etc
lots of tiny reasons i guess
Is there an easy button for step 1? Existing image or Dockerfile to use...
I saw things like this: https://github.com/michaeloliverx/python-poetry-docker-example
Or use your Dockerfile if you can share it π
well i could do #1 manually and simply reference the docker tag i created myself
Right. So we can play along, I mean.
oh i could show you the Dockerfile's ... they're a WIP of course because i'm trying to adapt them to dagger and such
that's the Dockerfile for step 1
i'm not doing any cleanup afterwards or anything as i'll deal with optimizations after
I'll throw some things in a repo. What will I need to build a minimal wheel π
looks
i forked and added a simple web app... https://github.com/rockyburt/rocky-wheels
i haven't worked much with github pull requests and all that jazz so just let me know what you need π
there would be two dockerfile's ... one to setup the built wheels, and the second to construct the actual application btw (at least for my workflow)
and yes, i know i could use build stages, but the thing is, the first stage (the one that builds the wheels and such) ... would be nice to be reusable
Nice. Yes, you could build with Dockerfiles or use Dagger itself to build the images. So the Dockerfile we have is the build deps, etc, right?
I'm going to push it all up to my repo. Just copied your content over.
I renamed Dockerfile to Dockerfile.build, like in your Dagger gist.
yep yep
i'm using raw Dockerfiles and passing in build arguments to keep things configurable in an effort to allow other members on my team the ability to modify the Dockerfile workflow without having to learn dagger.io
if/when the rest of the team becomes more familiar with dagger.io i may convert the Dockerfile's to Dagger build steps
Cool. So, makeBuilder works π Cache speeds things up on subsequent runs.
dagger do makeBuilder --no-cache
[β] _base 0.1s
[β] actions.makeBuilder 25.8s
dagger do makeBuilder
[β] _base 0.1s
[β] actions.makeBuilder 0.1s
btw i had no idea of naming conventions of actions so feel free to clear things up π
yes... for the actual running of the final app
it'll look similar to this...
ARG PYTHON_EXACT_VERSION
FROM public.ecr.aws/docker/library/python:${PYTHON_EXACT_VERSION}-slim-bullseye
RUN \
python3 -m venv /app
COPY app.py /app/src/app.py
CMD ["/app/bin/python", "/app/src/app.py"]
but in that Dockerfile we'll also need to copy over all of the wheels (built from Dagger buildWheels action which is currently commented) and install into the virtualenv
normally i'd use bi-directional mounts to share those wheel build artifacts to speed up the build process
rather than export/import/copy/whatever
in a larger project, there would be thousands of wheels
So you would create a venv for each one of the thousands of wheels?
Maybe I'm getting ahead of myself....can I build a wheel now with the python code I have?
Guessing I need to at least run the poetry command to get the requirements.txt
oh sorry... venv is basically just a localized Python environment so when you install dependencies (such as wheels) it doesn't infest the root python
so one venv for the entire project
yeah... poetry export --dev --without-hashes --format=requirements.txt generates requirements.txt ... requirements.txt is basically a dependency list of all wheels that are needed
what i don't have in any of the samples i've given you so far is the step that acutally builds the third-party wheels... after generating requirements.txt the step would be pip wheel -w someoutdir -r requirements.txt
i hadn't gotten that far yet because i was making sure all my previous steps were operating at peak efficiency π
so the command for buildWheels action would be something like this... mkdir -p .build .build/wheels && poetry export --dev --without-hashes --format=requirements.txt > .build/requirements.txt && pip wheel -w .build/wheels -r .build/requirements.txt
btw a nice to have would be some sort of #RunSteps construct where you could add individual lines to run but in turn generates the full string with adequate "&&" to run the whole thing
i hate writing a long sh -c "step1 && step2 && step3" ... etc manually
maybe have docker.#Run take an optional shell param which is an array of strings and generates the appropriate sh -c string
just spitballing atm
just pushed again
try this
dagger do buildWheels --log-format plain and you should see the requirements
fyi, not sure who's responsible for docs, but took me a lot of digging to figure out i needed to use --log-format plain to see anything useful π
but yeah that shows the requirements.txt
fyi, could you do me a favour and change the tag name to something less noticably a part of my company's info? (ie that 519507978765 is our company AWS account id... it's not enough to invade our system but still indicates us)
i'm gonna delete my fork π
btw, this is the version of main.cue i just reworked a bit...
package rentalsapi
import (
"dagger.io/dagger"
"dagger.io/dagger/core"
"universe.dagger.io/docker"
//"universe.dagger.io/docker/cli"
)
dagger.#Plan & {
_base: core.#Source & {
path: "."
}
actions: {
makeBuilder: #PythonImageBuild & {
pyVersion: "3.11-rc"
dockerfile: path: "Dockerfile.build"
tag: "app:build-py3.11-rc"
}
buildWheels: docker.#Build & {
steps: [
makeBuilder,
docker.#Run & {
mounts: project: {
dest: "/app/src"
contents: _base.output
}
always: true
workdir: "/app/src"
command: {
name: "sh"
args: ["-c", "mkdir -p .build && poetry export --dev --without-hashes --format=requirements.txt > .build/requirements.txt && pip wheel -w /app/build/wheels -r .build/requirements.txt"]
}
},
]
}
}
}
the previous version you were working was specific to the company project i was working on, but that new version i just pasted is more appropriate to the new app we're building based on app.py
The docker.#Build construct connects the outputs and inputs of steps that yield images without you having to manually wire
step1: ...
step2: docker.#Run & {
input: step1.output
oh, nice
btw, in python i would do this to get the complicated sh command string...
my_shell_cmd = ["mkdir -p .build", "poetry export ..."]
args = ["-c"] + "&&".join(my_shell_cmd)
to keep things a bit cleaner... not sure if there's an equiv in Cue
i haaate long "command1 && command2 && command3" strings lol
yep, looks about right
@hollow briar You seem to be describing a multi-stage build. That's what I do in Python with Poetry.
It's easy to do in Dagger, you don't need to export the wheels to your machine, just pass the dagger.#FS to the run stage.
Same idea as this: https://docs.dagger.io/1205/container-images#multi-stage-build
yeah, i mentioned that earlier in this thread... i have used multistage builds for stuff like this in the past, but i'm trying to separate out that build stage as something that can be reused
As for the long command, you can use a multi-line string and set -euo pipefail.
Yes, that's alright, but I saw stuff about using cli.#Run to have bidirectional mounts.
right
You can write your build into a reusable action (e.g, #BuildWheels).
@hollow briar is in first days of using Dagger/CUE, but yeah, we've broken out some things so far:
https://github.com/jpadams/rocky-wheels
like splitting out build.cue from main.cue.
Got it.
Just a quick sketch:
#BuildWheels: {
input: docker.#Image
source: dagger.#FS
_run: bash.#Run & {
"input": input
mounts: project: {
dest: "/app/src"
contents: source
}
always: true
workdir: "/app/src"
script: contents: """
poetry export --dev --without-hashes --format=requirements.txt > /requirements.txt
pip wheel -w /wheels -r /requirements.txt
"""
export: directories: "/wheels"
}
output: _run.export.directories."/wheels"
}
Then
buildWheels: #BuildWheels & {
input: makeBuilder.output
source: _base.output
}
and buildWheels.output will have your wheels, so you can docker.#Copy into the run image.
interesting
that bash script is running outside of docker correct? i was running it inside docker container because i'm trying to reduce dependencies on the outside environment
ohh, i hadn't realized it worked that way
Yes, everything in dagger runs in a container, unless you use Client API: https://docs.dagger.io/1203/client#running-commands
i've been reading the docs constantly over the past couple of days, it's crazy some of the stuff you miss
yeah i knew everything run inside a container because that was the nature of Dagger, but by default it runs in some sort of private Dagger container, no ?
Someone's working on a "How it all works" doc currently π
lol
You mean because you don't see it in your local docker daemon?
Think about a Dockerfile, that bash.#Run or docker.#Run is the same a RUN instruction.
no, i understand why that doesn't happen (sort of) ... but what i meant was that if you run a bash script and don't specify an image input, what container/image does it run ?
It's the same, they're handled by buildkit.
oh, hm
You need an input image otherwise it will error π
oh, haha
Some actions have a default image, you can do it as well. bash.#Run and docker.#Run don't. They're too generalized. So you need to specify it.
so now i'm starting to wonder why docker.#Run is even relevant
python.#Run has a default.
It's because you want to run those commands... poetry, pip...
yeah i think my head is not wrapping all the way around this lol
bash.#Run is a convenience on top of docker.#Run.
oh right, yeah, that makes sense
python.#Run is also a convenience on top of docker.#Run: https://github.com/dagger/dagger/blob/main/pkg/universe.dagger.io/python/python.cue
So if you want to run some python code, it's easier. Same as bash.
neat
so any time i see myself wanting to run docker.#Run ... chances are there's a higher level abstraction that will make things easier such as bash.#Run or python.#Run or whatever
lol
well, the fact that bash.#Run lets me run a series of commands without concontaneating some large string is enough for me π
there should be a disclaimer in the docker.#Run docs ... "if you are reading this, there's a good chance you might want to check on bash.#Run which specifically lets you run a bash script this way"
Yes, but that works with docker.#Run as well, here's the difference:
// docker.#Run
command: {
name: "bash"
flags: "-c": """
set -euo pipefail
<command1>
<command2>
}
}
// bash.#Run
script: contents: """
<command1>
<command2>
"""
Yes, I'm going to work on documenting the docker package this week.
oh gotcha, i wasn't certain how the flags argument worked for docker.#Run
nice
I'm going to take a note of that, thanks!
np
You can see the default args for bash.#Run here: https://github.com/dagger/dagger/blob/a9f300a70b188f801b4d8057c24fe779cc3694d3/pkg/universe.dagger.io/bash/bash.cue#L48-L57
Basically, the flags map gets flattened between command: name and command: args.
So that produces the following command: bash --norc -e -o pipefail <script> [args]
heh, nice ... i've found in general the cue files themselves are actually documentation enough, until i look up something like dagger.#FS source which just confused me lol
Yes, the pkg/dagger.io folder has the core stuff. Some things there come from Go or are interpreted by it. It's universe.dagger.io that has stuff that could be written by anyone. We just collect a few of them.
i guess that means i'd understand some things easier at a glance if i knew Go then
i keep meaning to learn golang, but who has the time lol
No, not necessarily. It just helps to know where the boundaries are, but if you want to stay clear of that just know that this happens.
probably be good to document what those boundaries are
It's actually simple, let me just give you the run down and see if it makes sense: When using types (https://docs.dagger.io/1234/dagger-types-reference/), they hold internal ids that you can't access in CUE, that have meaning in Go. So these types will be interpreted and filled by Go.
Then there's the core actions, which may have a few outputs. Those are also filled by Go during execution time. You can tell when looking at the CUE code if you see a @dagger(generated) attribute, like the output here: https://github.com/dagger/dagger/blob/v0.2.11/pkg/dagger.io/dagger/core/http.cue
yep i asaw a few @dagger references that threw me for a loop
So it's anything you see with $dagger: ... that is interpreted by Go, or @dagger(generated).
fyi, this line which i see quite often... i still only barely grasp what it's for... client: filesystem: ".": read: contents: dagger.#FS which is why i was looking for docs on dagger.#FS and got stumped lol
right, that makes sense, hence, "one of the boundaries"
Good to know. What's not clear? What it does in general, or more specific?
i know what it ultimately gets used for, but the individual fields... like i see it takes a filesystem param, but where is the filesystem param documented?
We have an issue tracking improving that: https://github.com/dagger/dagger/issues/2470
does the filesystem param only take a string?
i can't help but feel if i knew Go syntax better it would be a little clearer to me
No, it doesn't have to do with Go, it's just how the CUE structure is built. The general doc is in https://docs.dagger.io/1203/client
As for reading the CUE code for that, it's here: https://github.com/dagger/dagger/blob/v0.2.11/pkg/dagger.io/dagger/plan.cue
If you don't know what a template is, it helps to know: https://cuelang.org/docs/tutorials/tour/types/templates/
heh, honestly, i've read all of these docs before (including that source cue file) and at the time it didn't "connect" for me, but given the more basic understanding i've acquired today even in this discussion thread, things seem to be connecting better in my head
It helps us to know what could be improved so that first timers have an easier understanding.
it certainly helps to have a more fundamental understanding of how Cue data structures are defined and used... which is starting to happen for me π
Yes, definitely. When I started using dagger I made sure to learn CUE first. When you try to learn both at the same time I think it's harder to know one from the other.
the single line Cue data structure definitions threw me for quite a loop in the beginning
definitely
is Cue used on any other big projects generally used that i might be aware of ?
i have to admit that this was the first barrier for me to even consider using Dagger, was that i had to learn yet another configuration language lol
Not sure. But some use it extensively. We have team members that used it for thousands of cloud formation configs before joining dagger. I heard of it from kubevela.io, but only learned cue with dagger.
Yeah, I get you. I had the same feeling with KubeVela. But dagger made me take another look and it helps to understand why CUE was created in the first place: https://cuelang.org/docs/about/
updated this:
https://github.com/jpadams/rocky-wheels
Now looking back, on one hand it allows us much flexibility and power. Once you get it, it unlocks a great deal. On the other, it adds to the learning curve for first timers.
yeah, right now my brain is going, "how could i best express the workload that @silent ruin is doing in that github repo in a simple yaml format that gets translated into cue" lol
Next would be converting the Dockerfile into a docker.#Build and maybe either integrating it inside of #BuildWheels or use as default image π
yaml-first, but then doing raw cue to do truly powerful things later on, to lessen the initial learning curve π
For one thing, you can just have your team look at this interface: https://github.com/jpadams/rocky-wheels/blob/main/main.cue
Then they could just change values here if needed
https://github.com/jpadams/rocky-wheels/blob/main/main.cue#L13-L24
makeBuilder: #PythonImageBuild & {
source: _base.output
pyVersion: "3.11-rc"
dockerfile: path: "Dockerfile.build"
tag: "app:build-py3.11-rc"
}
buildWheels: #BuildWheels & {
input: makeBuilder.output
source: _base.output
}
Yes, focus on making reusable actions, and keep the plans lean: https://docs.dagger.io/1221/action
yep, pulling the nitty gritty stuff out and then having main.cue just reference the high level tasks would certain make it easier for other team members to tweak as necessary
it'd be nice to see some common naming patterns for the toplevel cue files too... like to me, main.cue and build.cue doesn't really make sense to me... i'd rename main.cue to plan.cue and build.cue to actions.cue until actions.cue grew to large and then made actions be a dir with sub-cue files
well not necessarily actions.cue ... but whatever toplevel unit name
anyhow, i think now i'm just nit-picking
also, it threw me for a loop when i accidentally discovered that dagger just picked up whatever cue files are in the current directory, no need to have special names or whatever
reminds me of terraform files actually
totally. ideally, we'll make these Actions we've been working on packages that anyone can use by adding them to universe.dagger.io. Then anyone can import them into their Dagger plans π
right
We've been using a lot like docker and bash and we have a space for experimental/user-submitted packages too π
https://github.com/dagger/dagger/tree/main/pkg/universe.dagger.io/x
You don't need to put in universe to reuse. Any git repo you have access to can be used.
You can provide your own for others to use, or privately in your company.
interesting
curious, what is the trailing underscore in export: directories: "/wheels": _ for @silent ruin ?
It means, match whatever's the type for it. Instead of re-declaring it again.. you'd have to look what it is and do export: directories: "/wheels": dagger.#FS instead.
oh ok, that makes sense
It's creating a new struct from a template, you just need to create a new value/struct from the template, and inherit the rest of the structure.
@hollow briar I pushed a new version that doesn't export the wheels as a filesystem, but rather provides the whole image with the wheels on it. Not sure what you need exactly, but it's fun to see it working and starting the Quart app π
10:25AM INF actions.app._run._exec | #11 1.283 * Serving Quart app 'app'
10:25AM INF actions.app._run._exec | #11 1.283 * Environment: production
10:25AM INF actions.app._run._exec | #11 1.283 * Please use an ASGI server (e.g. Hypercorn) directly in production
10:25AM INF actions.app._run._exec | #11 1.283 * Debug mode: False
10:25AM INF actions.app._run._exec | #11 1.283 * Running on http://0.0.0.0:5000 (CTRL + C to quit)
10:25AM INF actions.app._run._exec | #11 1.283 [2022-05-30 17:25:44,435] Running on http://0.0.0.0:5000 (CTRL + C to quit)
oh nice
i think that works fine for the case in point ... for me, the main advantage to having the wheel files themselves as an exported build artifact is so i can use more conventional means to cache them in case i need to start from scratch or clear my dagger cache or whatever and not have to rebuild those wheels again
btw, the last step that does the pip install thing is not using the wheels you already built which kind of defeats the purpose π
yeah, figured that, just changed it π
script: contents: """
/app/bin/python -m pip install --upgrade pip
for wheel in /wheels/*.whl; do /app/bin/pip install $wheel; done
/app/bin/python /app/src/app.py
so you'd take the wheels in a filesystem (directory) and use them, but you'd also dump them to the client machine, for example?
i think the cleanest way would be to do...
pip install -r requirements.txt -f /wheels
where requirements.txt would have come from the step that does the poetry export
yes, precisely
and the main reason for wanting those wheels kept is due to the fact that building them can take forever if they include C extensions, particularly if you're building them on an x86 host using a arm64 emulator
so we really want to avoid running that stage unless pyproject.toml changes (which in turn changes requirements.txt which means newer wheels should be used)
one last thing tho, since you're having everything based on the buildWheels image... that means all of the build dependency junk is left in the image (making it quite large) ... so we basically want to mimick a multi stage build so that those deps are left out
so we want to run a second #PythonImageBuild action that makes a clean image and then get the wheels from the first image built into this new image
got it. I pushed up latest.
becoming clearer and clearer π
lol, you'll be a Python project image builder expert after this π
so basically a lot of the things i'm asking about (like preserving wheels separately) may seem non-sensical from a standard perspective, but there's a method to my madness based on years of building python images π
now i'm trying to take those experiences and implement with Dagger
I have to be afkb for a bit, but I'll check back a bit later.
I work a lot with Dagger users conducting Pilots related to a work (or personal) project, so don't hesitate to ping me (or whoever is around) π
sounds good to me... before you go tho, could you give me a hint on how to start a new image that copies the wheels from the first image? π
seems like i should be doing something special with dagger.#FS but it so far eludes me lol
Yes, indeed. For one thing, we could just pull a new image with the tag you specified and then copy (or ephemerally mount) the FS in and run our commands on it.
right
Just pushed another version. Check it out π
it assumes a local registry on 5042 to push the finished image to
docker run -d -p 5042:5000 --restart=always --name localregistry registry:2
neat π
i made some updates that running (locally on the command line) docker run -it --rm pythonapp:1 runs the app - https://gist.github.com/rockyburt/eb80262d871dbe3440ce780cf1eafe07
# build image and setup in local docker
dagger do saveLocal
# run the app using local docker
docker run -it --rm pythonapp:1
Like the imageID output!
Field Value
imageID "sha256:26916eb26b4609076082374d77b403432c7cfe4747e0b0504902f868b8aa0d39"
docker run -it --rm -p 5050:5000 sha256:26916eb26b4609076082374d77b403432c7cfe4747e0b0504902f868b8aa0d39
curl localhost:5050
hello
yeah... i've forked your repo again and doing some more cleanup based on what i know of python image building π
yeah, i would consider the next step to save those wheels into your local/client filesystem ... and then when building them again next time, check the client/local filesystem first (perhaps #Mount ?)
i updated readme as well π https://github.com/rockyburt/rocky-wheels
just added a runTest action that runs some useless tests for python
client: filesystem: "./.build": write: contents: actions.buildWheels.output
put that at the top and now I've got 60 wheels and a requirements.txt in my local .build π
nice!
Sorry if Iβm late to the party, but i recommend looking at the yarn package for a good example of how to deal with βone-wayβ mounts when you need to get something out of your build process (in the case of yarn: the build). Basically the script copies just the output artifacts
hmmm...would it make sense to use a something in the requirements.txt as a cache key?
hash of the file, for example...
@silent ruin i'm not sure how you'd do it... but as for not rebuilding when necessary ... poetry export --dev --without-hashes --format=requirements.txt > /app/build/requirements.txt should only get run iff poetry.lock changed (and not by checking last modified, should test a checksum) ... and then of course pip wheel -w /app/build/wheels -r /app/build/requirements.txt should only be run if requirements.txt changed by testing checksum
it seems to me that #buildWheels _run action should be broken out into separate steps... one that bootstraps (every line before poetry export) and then a step that runs the poetry export and then a step that runs the pip wheel
i had that on my shortlist but got distracted (breaking out the steps ... not the checksum/hash checking)
i've pushed up some more small tweaks to my fork btw
Awesome. That logic is gold.
Seems super do-able. What doesn't work (I tried it out) was to just write out the wheels to the client and then mount that when building. Acts like a new build every time. Def need to let the system know we're using a cachedir.
there is a good lib to help out
import "crypto/sha256"
right... well i guess i'll begin by attempting to break out _run into multiple steps
seems like checksum testing should have a higher level primitive in dagger.io proper tho π
I'll ask a colleague about caching tomorrow. π
if i'm inside the steps of a docekr.#Build ... is there a way for step2 to reference fields from step1 ?