diff --git a/cmd/dagger/cmd/common/common.go b/cmd/dagger/cmd/common/common.go index 83e17d70..5028a2b1 100644 --- a/cmd/dagger/cmd/common/common.go +++ b/cmd/dagger/cmd/common/common.go @@ -60,10 +60,10 @@ func GetCurrentDeploymentState(ctx context.Context, store *dagger.Store) *dagger } // Re-compute a deployment (equivalent to `dagger up`). -func DeploymentUp(ctx context.Context, state *dagger.DeploymentState) *dagger.Deployment { +func DeploymentUp(ctx context.Context, state *dagger.DeploymentState, noCache bool) *dagger.Deployment { lg := log.Ctx(ctx) - c, err := dagger.NewClient(ctx, "") + c, err := dagger.NewClient(ctx, "", noCache) if err != nil { lg.Fatal().Err(err).Msg("unable to create client") } diff --git a/cmd/dagger/cmd/compute.go b/cmd/dagger/cmd/compute.go index 9f2d32e4..4596315f 100644 --- a/cmd/dagger/cmd/compute.go +++ b/cmd/dagger/cmd/compute.go @@ -149,7 +149,7 @@ var computeCmd = &cobra.Command{ } } - deployment := common.DeploymentUp(ctx, st) + deployment := common.DeploymentUp(ctx, st, viper.GetBool("no-cache")) v := compiler.NewValue() if err := v.FillPath(cue.MakePath(), deployment.Plan()); err != nil { @@ -173,6 +173,7 @@ func init() { computeCmd.Flags().StringSlice("input-git", []string{}, "TARGET=REMOTE#REF") computeCmd.Flags().String("input-json", "", "JSON") computeCmd.Flags().String("input-yaml", "", "YAML") + computeCmd.Flags().Bool("no-cache", false, "disable cache") if err := viper.BindPFlags(computeCmd.Flags()); err != nil { panic(err) diff --git a/cmd/dagger/cmd/down.go b/cmd/dagger/cmd/down.go index 1e3937ac..5766c8b5 100644 --- a/cmd/dagger/cmd/down.go +++ b/cmd/dagger/cmd/down.go @@ -22,7 +22,7 @@ var downCmd = &cobra.Command{ } func init() { - downCmd.Flags().Bool("--no-cache", false, "Disable all run cache") + downCmd.Flags().Bool("no-cache", false, "Disable all run cache") if err := viper.BindPFlags(downCmd.Flags()); err != nil { panic(err) diff --git a/cmd/dagger/cmd/new.go b/cmd/dagger/cmd/new.go index 90d68468..9c3e3966 100644 --- a/cmd/dagger/cmd/new.go +++ b/cmd/dagger/cmd/new.go @@ -63,7 +63,7 @@ var newCmd = &cobra.Command{ Msg("deployment created") if viper.GetBool("up") { - common.DeploymentUp(ctx, st) + common.DeploymentUp(ctx, st, false) } }, } diff --git a/cmd/dagger/cmd/query.go b/cmd/dagger/cmd/query.go index 5680371f..3a1ed73a 100644 --- a/cmd/dagger/cmd/query.go +++ b/cmd/dagger/cmd/query.go @@ -47,7 +47,7 @@ var queryCmd = &cobra.Command{ cuePath = cue.ParsePath(args[0]) } - c, err := dagger.NewClient(ctx, "") + c, err := dagger.NewClient(ctx, "", false) if err != nil { lg.Fatal().Err(err).Msg("unable to create client") } diff --git a/cmd/dagger/cmd/up.go b/cmd/dagger/cmd/up.go index 7d6175e8..b0ecf81f 100644 --- a/cmd/dagger/cmd/up.go +++ b/cmd/dagger/cmd/up.go @@ -29,9 +29,7 @@ var upCmd = &cobra.Command{ } state := common.GetCurrentDeploymentState(ctx, store) - - // TODO: Implement options: --no-cache - result := common.DeploymentUp(ctx, state) + result := common.DeploymentUp(ctx, state, viper.GetBool("no-cache")) state.Computed = result.Computed().JSON().String() if err := store.UpdateDeployment(ctx, state, nil); err != nil { lg.Fatal().Err(err).Msg("failed to update deployment") @@ -40,7 +38,7 @@ var upCmd = &cobra.Command{ } func init() { - newCmd.Flags().Bool("--no-cache", false, "Disable all run cache") + upCmd.Flags().Bool("no-cache", false, "Disable all run cache") if err := viper.BindPFlags(upCmd.Flags()); err != nil { panic(err) diff --git a/dagger/client.go b/dagger/client.go index 0d5cc719..3635301a 100644 --- a/dagger/client.go +++ b/dagger/client.go @@ -29,10 +29,11 @@ import ( // A dagger client type Client struct { - c *bk.Client + c *bk.Client + noCache bool } -func NewClient(ctx context.Context, host string) (*Client, error) { +func NewClient(ctx context.Context, host string, noCache bool) (*Client, error) { if host == "" { host = os.Getenv("BUILDKIT_HOST") } @@ -53,7 +54,8 @@ func NewClient(ctx context.Context, host string) (*Client, error) { return nil, fmt.Errorf("buildkit client: %w", err) } return &Client{ - c: c, + c: c, + noCache: noCache, }, nil } @@ -111,7 +113,7 @@ func (c *Client) buildfn(ctx context.Context, deployment *Deployment, fn ClientD Msg("spawning buildkit job") resp, err := c.c.Build(ctx, opts, "", func(ctx context.Context, gw bkgw.Client) (*bkgw.Result, error) { - s := NewSolver(c.c, gw, ch) + s := NewSolver(c.c, gw, ch, c.noCache) lg.Debug().Msg("loading configuration") if err := deployment.LoadPlan(ctx, s); err != nil { diff --git a/dagger/pipeline.go b/dagger/pipeline.go index 7cddcfd0..271dbb5d 100644 --- a/dagger/pipeline.go +++ b/dagger/pipeline.go @@ -722,6 +722,10 @@ func (p *Pipeline) DockerBuild(ctx context.Context, op *compiler.Value, st llb.S return st, err } + if p.s.noCache { + opts["no-cache"] = "" + } + req := bkgw.SolveRequest{ Frontend: "dockerfile.v0", FrontendOpt: opts, diff --git a/dagger/solver.go b/dagger/solver.go index c20fef27..3a78c0c1 100644 --- a/dagger/solver.go +++ b/dagger/solver.go @@ -23,22 +23,50 @@ type Solver struct { events chan *bk.SolveStatus control *bk.Client gw bkgw.Client + noCache bool } -func NewSolver(control *bk.Client, gw bkgw.Client, events chan *bk.SolveStatus) Solver { +func NewSolver(control *bk.Client, gw bkgw.Client, events chan *bk.SolveStatus, noCache bool) Solver { return Solver{ events: events, control: control, gw: gw, + noCache: noCache, } } +func invalidateCache(def *llb.Definition) error { + for _, dt := range def.Def { + var op bkpb.Op + if err := (&op).Unmarshal(dt); err != nil { + return err + } + dgst := digest.FromBytes(dt) + opMetadata, ok := def.Metadata[dgst] + if !ok { + opMetadata = bkpb.OpMetadata{} + } + c := llb.Constraints{Metadata: opMetadata} + llb.IgnoreCache(&c) + def.Metadata[dgst] = c.Metadata + } + + return nil +} + func (s Solver) Marshal(ctx context.Context, st llb.State) (*bkpb.Definition, error) { // FIXME: do not hardcode the platform def, err := st.Marshal(ctx, llb.LinuxAmd64) if err != nil { return nil, err } + + if s.noCache { + if err := invalidateCache(def); err != nil { + return nil, err + } + } + return def.ToPB(), nil } diff --git a/examples/jamstack/ecr_image.cue b/examples/jamstack/ecr_image.cue index 81d44fe6..20963737 100644 --- a/examples/jamstack/ecr_image.cue +++ b/examples/jamstack/ecr_image.cue @@ -19,15 +19,6 @@ import ( pushTarget: "\(repository):\(tag)" - // Build the image - buildImage: op.#DockerBuild & { - context: source - if dockerfilePath != _|_ { - "dockerfilePath": dockerfilePath - } - buildArg: buildArgs - } - // Use these credentials to push ecrCreds: ecr.#Credentials & { config: awsConfig @@ -35,6 +26,7 @@ import ( } push: #up: [ + // Build the docker image op.#DockerBuild & { context: source if dockerfilePath != _|_ { @@ -42,6 +34,7 @@ import ( } buildArg: buildArgs }, + // Push the image to the registry op.#PushContainer & { ref: pushTarget },