#WithExec caching
1 messages ยท Page 1 of 1 (latest)
That or the commands are being executed out of order?
Execs are always be cached if they have the exact same inputs as before. If you need it to always run no matter what, you can attach a randomly generated value as an environment variable, like container.WithEnvVariable("BUST", time.Now().String())
came across that solution in another thread, oddly its still being skipped with that :/
will see if I can get a repro
Things seem to work as expected if I explicitly request Stdout from each WithExec.
that's because Stdout gets the output of the withExec where it was invoked. You can try this:
package main
import (
"context"
"fmt"
"time"
"dagger.io/dagger"
)
func main() {
ctx := context.Background()
client, err := dagger.Connect(ctx)
if err != nil {
panic(err)
}
defer client.Close()
c := client.Pipeline("test").
Container().
From("alpine").
WithEnvVariable("BUST", time.Now().String())
printOut(c.WithExec([]string{"echo", "xxx1"}).Stdout(ctx))
printOut(c.WithExec([]string{"echo", "xxx2"}).Stdout(ctx))
printOut(c.WithExec([]string{"echo", "xxx3"}).Stdout(ctx))
if err != nil {
panic(err)
}
}
func printOut(o string, err error) {
if err == nil {
fmt.Println(o)
}
}
Thanks beat me to it @maiden nebula ๐ Im still a bit confused on the behaviour of dagger when compared to more traditional CI engines...
Is it the case that without the calls to .Stdout in each step that the order is undetermined?
no, even if you chain the withExec they'll be executed in order
if you add logging to your client: client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr)) you'll have more visibility about how things are currently being executed.
the only way to get "undefined" execution is if you run multiple WithExecsin different goroutines to make them run in parallel
you could also try the dagger run UI: https://github.com/dagger/dagger/discussions/4942
My original use case was a basic pipeline with terraform, something like this:
src := client.Host().Directory(".")
terraform := client.Container().From(toolbox)
terraform = terraform.WithMountedDirectory("/work", src).WithWorkdir("/work")
terraform = terraform.WithExec([]string{"terraform", "init"})
terraform = terraform.WithExec([]string{"terraform", "apply", "--auto-approve")
But what I was seeing (before explicitly fetching and print Stdout after each WithExec), was that it would skip over the 'init' step entirely and go straight to the apply, which of course failed because init hasn't run...
It seems the Stdout call is forcing dagger to wait for the init to run before proceeding, without that it just fails pretty quickly. This is even with the cache bust workaround...
Sorry to be persistent but I feel I need to understand this to have a future with dagger ๐
sure! that's strange since it shouldn't happen if you used the cache bust command. I'll try to repro this a bit later ๐
you shouldn't have to do Stdout for each step
@idle inlet managed to get a simple example which doesn't show the behavior you mention:
package main
import (
"context"
"os"
"time"
"dagger.io/dagger"
)
func main() {
ctx := context.Background()
client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr))
if err != nil {
panic(err)
}
defer client.Close()
client.Pipeline("test").
Container().
From("hashicorp/terraform").
WithMountedDirectory("/app", client.Host().Workdir()).
WithWorkdir("/app").
WithEnvVariable("BUST", time.Now().String()).
WithExec([]string{"init"}).
WithExec([]string{"apply", "-auto-approve"}).ExitCode(ctx)
}
resource "local_file" "foo" {
content = "foo!"
filename = "${path.module}/foo.bar"
}
if you run go run main.go multiple times, init and apply are both executed
LMK if you have a repro example from your side so we can take a look
Thanks very much for checking - your example also works as expected on my end so Im kind of stumped as to why I was having issues in my other pipeline. At least I know a little more about how its supposed to work, if I see this issue again I'll let you know