From d0b4d6ad1b7710904b3e6ebb5498f2a946037972 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 17 May 2024 16:29:02 +0000 Subject: [PATCH 01/13] feat: push final image to cache repo This commit enables pushing the final image to the given cache repo.a As part of #185, the goal is to allow for faster startup when the image has already been built. --- envbuilder.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/envbuilder.go b/envbuilder.go index 7e88cbee..d75f4b72 100644 --- a/envbuilder.go +++ b/envbuilder.go @@ -480,14 +480,18 @@ func Run(ctx context.Context, options Options) error { if val, ok := os.LookupEnv("KANIKO_REGISTRY_MIRROR"); ok { registryMirror = strings.Split(val, ";") } - image, err := executor.DoBuild(&config.KanikoOptions{ + var destinations []string + if options.CacheRepo != "" { + destinations = append(destinations, options.CacheRepo) + } + opts := &config.KanikoOptions{ // Boilerplate! CustomPlatform: platforms.Format(platforms.Normalize(platforms.DefaultSpec())), SnapshotMode: "redo", RunV2: true, RunStdout: stdoutWriter, RunStderr: stderrWriter, - Destinations: []string{"local"}, + Destinations: destinations, CacheRunLayers: true, CacheCopyLayers: true, CompressedCaching: true, @@ -518,11 +522,16 @@ func Run(ctx context.Context, options Options) error { RegistryMirrors: registryMirror, }, SrcContext: buildParams.BuildContext, - }) + } + image, err := executor.DoBuild(opts) if err != nil { return nil, err } + if err := executor.DoPush(image, opts); err != nil { + return nil, err + } endStage("🏗️ Built image!") + return image, err } From 5a50f4a006fb53271ad02bec92ed0f7b4d78f2bb Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Mon, 20 May 2024 11:03:49 +0000 Subject: [PATCH 02/13] explicitly set nopush if no destinations --- envbuilder.go | 1 + 1 file changed, 1 insertion(+) diff --git a/envbuilder.go b/envbuilder.go index d75f4b72..6a550ede 100644 --- a/envbuilder.go +++ b/envbuilder.go @@ -492,6 +492,7 @@ func Run(ctx context.Context, options Options) error { RunStdout: stdoutWriter, RunStderr: stderrWriter, Destinations: destinations, + NoPush: len(destinations) == 0, CacheRunLayers: true, CacheCopyLayers: true, CompressedCaching: true, From 6cb1217382a71c749e9492152e888541fa8baa6b Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Mon, 20 May 2024 11:09:31 +0000 Subject: [PATCH 03/13] wrap --- envbuilder.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/envbuilder.go b/envbuilder.go index 6a550ede..e41a8609 100644 --- a/envbuilder.go +++ b/envbuilder.go @@ -526,10 +526,10 @@ func Run(ctx context.Context, options Options) error { } image, err := executor.DoBuild(opts) if err != nil { - return nil, err + return nil, xerrors.Errorf("do build: %w", err) } if err := executor.DoPush(image, opts); err != nil { - return nil, err + return nil, xerrors.Errorf("do push: %w", err) } endStage("🏗️ Built image!") From 7764535c0676ca68eba12d09cf4d3398349b5af9 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 30 May 2024 14:27:18 +0000 Subject: [PATCH 04/13] feat: implement reproducible build and get cached image --- envbuilder.go | 41 +++++++++++++++++++++++++++++++++-------- go.mod | 2 +- go.sum | 4 ++-- options.go | 21 +++++++++++++++++++++ 4 files changed, 57 insertions(+), 11 deletions(-) diff --git a/envbuilder.go b/envbuilder.go index e41a8609..83bf7808 100644 --- a/envbuilder.go +++ b/envbuilder.go @@ -119,11 +119,11 @@ func Run(ctx context.Context, options Options) error { options.WorkspaceFolder = f } - stageNumber := 1 + stageNumber := 0 startStage := func(format string, args ...any) func(format string, args ...any) { now := time.Now() - stageNum := stageNumber stageNumber++ + stageNum := stageNumber options.Logger(notcodersdk.LogLevelInfo, "#%d: %s", stageNum, fmt.Sprintf(format, args...)) return func(format string, args ...any) { @@ -338,7 +338,7 @@ func Run(ctx context.Context, options Options) error { HijackLogrus(func(entry *logrus.Entry) { for _, line := range strings.Split(entry.Message, "\r") { - options.Logger(notcodersdk.LogLevelInfo, "#2: %s", color.HiBlackString(line)) + options.Logger(notcodersdk.LogLevelInfo, "#%d: %s", stageNumber, color.HiBlackString(line)) } }) @@ -474,7 +474,6 @@ func Run(ctx context.Context, options Options) error { cacheTTL = time.Hour * 24 * time.Duration(options.CacheTTLDays) } - endStage := startStage("🏗️ Building image...") // At this point we have all the context, we can now build! registryMirror := []string{} if val, ok := os.LookupEnv("KANIKO_REGISTRY_MIRROR"); ok { @@ -492,7 +491,7 @@ func Run(ctx context.Context, options Options) error { RunStdout: stdoutWriter, RunStderr: stderrWriter, Destinations: destinations, - NoPush: len(destinations) == 0, + NoPush: !options.PushImage || len(destinations) == 0, CacheRunLayers: true, CacheCopyLayers: true, CompressedCaching: true, @@ -523,15 +522,41 @@ func Run(ctx context.Context, options Options) error { RegistryMirrors: registryMirror, }, SrcContext: buildParams.BuildContext, + + // For cached image utilization, produce reproducible builds. + Reproducible: options.PushImage, + } + + if options.GetCachedImage { + endStage := startStage("🏗️ Building fake image...") + image, err := executor.DoFakeBuild(opts) + if err != nil { + logrus.Infof("unable to build fake image: %s", err) + os.Exit(1) + } + endStage("🏗️ Built fake image!") + digest, err := image.Digest() + if err != nil { + return nil, xerrors.Errorf("image digest: %w", err) + } + + _, _ = fmt.Fprintf(os.Stdout, "%s@%s\n", options.CacheRepo, digest.String()) + os.Exit(0) } + + endStage := startStage("🏗️ Building image...") image, err := executor.DoBuild(opts) if err != nil { return nil, xerrors.Errorf("do build: %w", err) } - if err := executor.DoPush(image, opts); err != nil { - return nil, xerrors.Errorf("do push: %w", err) - } endStage("🏗️ Built image!") + if options.PushImage { + endStage = startStage("🏗️ Pushing image...") + if err := executor.DoPush(image, opts); err != nil { + return nil, xerrors.Errorf("do push: %w", err) + } + endStage("🏗️ Pushed image!") + } return image, err } diff --git a/go.mod b/go.mod index 7ba4a6c5..627a4e47 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.22.3 // There are a few options we need added to Kaniko! // See: https://github.com/GoogleContainerTools/kaniko/compare/main...coder:kaniko:main -replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240524082248-9d0d55902c34 +replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240530135420-68a0b6735395 require ( cdr.dev/slog v1.6.2-0.20240126064726-20367d4aede6 diff --git a/go.sum b/go.sum index 889b15d4..bc6118a2 100644 --- a/go.sum +++ b/go.sum @@ -121,8 +121,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coder/kaniko v0.0.0-20240524082248-9d0d55902c34 h1:Wm7sMNc1aTN5l0NerYHb3LZdQJVQp4QrW4v83N21sfc= -github.com/coder/kaniko v0.0.0-20240524082248-9d0d55902c34/go.mod h1:YMK7BlxerzLlMwihGxNWUaFoN9LXCij4P+w/8/fNlcM= +github.com/coder/kaniko v0.0.0-20240530135420-68a0b6735395 h1:xXYQkWPtu9zyhGKP1wnFjPoH9wTQksyNAFnS4xZWdxA= +github.com/coder/kaniko v0.0.0-20240530135420-68a0b6735395/go.mod h1:YMK7BlxerzLlMwihGxNWUaFoN9LXCij4P+w/8/fNlcM= github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 h1:3A0ES21Ke+FxEM8CXx9n47SZOKOpgSE1bbJzlE4qPVs= github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0/go.mod h1:5UuS2Ts+nTToAMeOjNlnHFkPahrtDkmpydBen/3wgZc= github.com/coder/retry v1.5.1 h1:iWu8YnD8YqHs3XwqrqsjoBTAVqT9ml6z9ViJ2wlMiqc= diff --git a/options.go b/options.go index 18c3c990..f411060b 100644 --- a/options.go +++ b/options.go @@ -138,6 +138,13 @@ type Options struct { // CoderAgentSubsystem is the Coder agent subsystems to report when forwarding // logs. The envbuilder subsystem is always included. CoderAgentSubsystem []string + + // PushImage is a flag to determine if the image should be pushed to the + // container registry. This option implies reproducible builds. + PushImage bool + // GetCachedImage is a flag to determine if the cached image is available, + // and if it is, to return it. + GetCachedImage bool } const envPrefix = "ENVBUILDER_" @@ -395,6 +402,20 @@ func (o *Options) CLI() serpent.OptionSet { Description: "Coder agent subsystems to report when forwarding logs. " + "The envbuilder subsystem is always included.", }, + { + Flag: "push-image", + Env: WithEnvPrefix("PUSH_IMAGE"), + Value: serpent.BoolOf(&o.PushImage), + Description: "Flag to determine if the image should be pushed to " + + "the container registry. This option implies reproducible builds.", + }, + { + Flag: "get-cached-image", + Env: WithEnvPrefix("GET_CACHED_IMAGE"), + Value: serpent.BoolOf(&o.GetCachedImage), + Description: "Flag to determine if the cached image is available, " + + "and if it is, to return it.", + }, } // Add options without the prefix for backward compatibility. These options From d54ca81d99f9d55e31a60455780fc0848ac0fdc7 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 30 May 2024 15:55:47 +0000 Subject: [PATCH 05/13] gen --- README.md | 2 ++ options_test.go | 1 + testdata/options.golden | 8 ++++++++ 3 files changed, 11 insertions(+) diff --git a/README.md b/README.md index 7ae3de4b..cecbcf36 100644 --- a/README.md +++ b/README.md @@ -343,4 +343,6 @@ On MacOS or Windows systems, we recommend either using a VM or the provided `.de | `--coder-agent-url` | `CODER_AGENT_URL` | | URL of the Coder deployment. If CODER_AGENT_TOKEN is also set, logs from envbuilder will be forwarded here and will be visible in the workspace build logs. | | `--coder-agent-token` | `CODER_AGENT_TOKEN` | | Authentication token for a Coder agent. If this is set, then CODER_AGENT_URL must also be set. | | `--coder-agent-subsystem` | `CODER_AGENT_SUBSYSTEM` | | Coder agent subsystems to report when forwarding logs. The envbuilder subsystem is always included. | +| `--push-image` | `ENVBUILDER_PUSH_IMAGE` | | Flag to determine if the image should be pushed to the container registry. This option implies reproducible builds. | +| `--get-cached-image` | `ENVBUILDER_GET_CACHED_IMAGE` | | Flag to determine if the cached image is available, and if it is, to return it. | diff --git a/options_test.go b/options_test.go index 14dfd182..e32af9e6 100644 --- a/options_test.go +++ b/options_test.go @@ -181,6 +181,7 @@ func runCLI() envbuilder.Options { } i := cmd.Invoke().WithOS() + i.Args = []string{"--help"} fakeIO(i) err := i.Run() if err != nil { diff --git a/testdata/options.golden b/testdata/options.golden index 38c1ec4f..43aee149 100644 --- a/testdata/options.golden +++ b/testdata/options.golden @@ -78,6 +78,10 @@ OPTIONS: your system! This is used in cases where bypass is needed to unblock customers. + --get-cached-image bool, $ENVBUILDER_GET_CACHED_IMAGE + Flag to determine if the cached image is available, and if it is, to + return it. + --git-clone-depth int, $ENVBUILDER_GIT_CLONE_DEPTH The depth to use when cloning the Git repository. @@ -129,6 +133,10 @@ OPTIONS: should check for the presence of this script and execute it after successful startup. + --push-image bool, $ENVBUILDER_PUSH_IMAGE + Flag to determine if the image should be pushed to the container + registry. This option implies reproducible builds. + --setup-script string, $ENVBUILDER_SETUP_SCRIPT The script to run before the init script. It runs as the root user regardless of the user specified in the devcontainer.json file. From ea91cd57ed74612edd0d5523fbf418de9b500282 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 30 May 2024 17:32:31 +0000 Subject: [PATCH 06/13] gomod --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 627a4e47..830e1bb6 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.22.3 // There are a few options we need added to Kaniko! // See: https://github.com/GoogleContainerTools/kaniko/compare/main...coder:kaniko:main -replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240530135420-68a0b6735395 +replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240530173157-696ae8dd977a require ( cdr.dev/slog v1.6.2-0.20240126064726-20367d4aede6 diff --git a/go.sum b/go.sum index bc6118a2..367340cf 100644 --- a/go.sum +++ b/go.sum @@ -121,8 +121,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coder/kaniko v0.0.0-20240530135420-68a0b6735395 h1:xXYQkWPtu9zyhGKP1wnFjPoH9wTQksyNAFnS4xZWdxA= -github.com/coder/kaniko v0.0.0-20240530135420-68a0b6735395/go.mod h1:YMK7BlxerzLlMwihGxNWUaFoN9LXCij4P+w/8/fNlcM= +github.com/coder/kaniko v0.0.0-20240530173157-696ae8dd977a h1:6BYdPtclD76/AfADhH19JAFGvorhx7xmXf+Wp6d9TEk= +github.com/coder/kaniko v0.0.0-20240530173157-696ae8dd977a/go.mod h1:YMK7BlxerzLlMwihGxNWUaFoN9LXCij4P+w/8/fNlcM= github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 h1:3A0ES21Ke+FxEM8CXx9n47SZOKOpgSE1bbJzlE4qPVs= github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0/go.mod h1:5UuS2Ts+nTToAMeOjNlnHFkPahrtDkmpydBen/3wgZc= github.com/coder/retry v1.5.1 h1:iWu8YnD8YqHs3XwqrqsjoBTAVqT9ml6z9ViJ2wlMiqc= From 1979ffdeacf931c11edbd4ce7c2fd3a0a2ccee68 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 11 Jun 2024 12:18:14 +0100 Subject: [PATCH 07/13] chore: add unit tests for push image / cache mode --- README.md | 4 +- envbuilder.go | 15 +-- go.mod | 2 +- go.sum | 4 +- integration/integration_test.go | 210 ++++++++++++++++++++++++++++++++ options.go | 8 +- 6 files changed, 227 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index cecbcf36..eaf1b1fa 100644 --- a/README.md +++ b/README.md @@ -343,6 +343,6 @@ On MacOS or Windows systems, we recommend either using a VM or the provided `.de | `--coder-agent-url` | `CODER_AGENT_URL` | | URL of the Coder deployment. If CODER_AGENT_TOKEN is also set, logs from envbuilder will be forwarded here and will be visible in the workspace build logs. | | `--coder-agent-token` | `CODER_AGENT_TOKEN` | | Authentication token for a Coder agent. If this is set, then CODER_AGENT_URL must also be set. | | `--coder-agent-subsystem` | `CODER_AGENT_SUBSYSTEM` | | Coder agent subsystems to report when forwarding logs. The envbuilder subsystem is always included. | -| `--push-image` | `ENVBUILDER_PUSH_IMAGE` | | Flag to determine if the image should be pushed to the container registry. This option implies reproducible builds. | -| `--get-cached-image` | `ENVBUILDER_GET_CACHED_IMAGE` | | Flag to determine if the cached image is available, and if it is, to return it. | +| `--push-image` | `ENVBUILDER_PUSH_IMAGE` | | Push the built image to a remote registry.This option forces a reproducible build. | +| `--get-cached-image` | `ENVBUILDER_GET_CACHED_IMAGE` | | Print the digest of the cached image, if available.Exits with an error if not found. | diff --git a/envbuilder.go b/envbuilder.go index 83bf7808..bb3fd9de 100644 --- a/envbuilder.go +++ b/envbuilder.go @@ -99,6 +99,9 @@ func Run(ctx context.Context, options Options) error { if options.InitCommand == "" { options.InitCommand = "/bin/sh" } + if options.CacheRepo == "" && options.PushImage { + return fmt.Errorf("--cache-repo must be set when using --push-image!") + } // Default to the shell! initArgs := []string{"-c", options.InitScript} if options.InitArgs != "" { @@ -528,18 +531,16 @@ func Run(ctx context.Context, options Options) error { } if options.GetCachedImage { - endStage := startStage("🏗️ Building fake image...") - image, err := executor.DoFakeBuild(opts) + endStage := startStage("🏗️ Checking for cached image...") + image, err := executor.DoCacheProbe(opts) if err != nil { - logrus.Infof("unable to build fake image: %s", err) - os.Exit(1) + return nil, xerrors.Errorf("unable to get cached image: %w", err) } - endStage("🏗️ Built fake image!") digest, err := image.Digest() if err != nil { - return nil, xerrors.Errorf("image digest: %w", err) + return nil, xerrors.Errorf("get cached image digest: %w", err) } - + endStage("🏗️ Found cached image!") _, _ = fmt.Fprintf(os.Stdout, "%s@%s\n", options.CacheRepo, digest.String()) os.Exit(0) } diff --git a/go.mod b/go.mod index 830e1bb6..6ae553d7 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.22.3 // There are a few options we need added to Kaniko! // See: https://github.com/GoogleContainerTools/kaniko/compare/main...coder:kaniko:main -replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240530173157-696ae8dd977a +replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240610145227-0a73fcd89e3f require ( cdr.dev/slog v1.6.2-0.20240126064726-20367d4aede6 diff --git a/go.sum b/go.sum index 367340cf..0252f6ae 100644 --- a/go.sum +++ b/go.sum @@ -121,8 +121,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coder/kaniko v0.0.0-20240530173157-696ae8dd977a h1:6BYdPtclD76/AfADhH19JAFGvorhx7xmXf+Wp6d9TEk= -github.com/coder/kaniko v0.0.0-20240530173157-696ae8dd977a/go.mod h1:YMK7BlxerzLlMwihGxNWUaFoN9LXCij4P+w/8/fNlcM= +github.com/coder/kaniko v0.0.0-20240610145227-0a73fcd89e3f h1:o5p2u5sF1KVMgH+pcoMNfStpfXe76O3Enwg0h1KlzIU= +github.com/coder/kaniko v0.0.0-20240610145227-0a73fcd89e3f/go.mod h1:YMK7BlxerzLlMwihGxNWUaFoN9LXCij4P+w/8/fNlcM= github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 h1:3A0ES21Ke+FxEM8CXx9n47SZOKOpgSE1bbJzlE4qPVs= github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0/go.mod h1:5UuS2Ts+nTToAMeOjNlnHFkPahrtDkmpydBen/3wgZc= github.com/coder/retry v1.5.1 h1:iWu8YnD8YqHs3XwqrqsjoBTAVqT9ml6z9ViJ2wlMiqc= diff --git a/integration/integration_test.go b/integration/integration_test.go index 7628b8bc..e139124d 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -34,6 +34,8 @@ import ( "github.com/go-git/go-billy/v5/memfs" "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/registry" + "github.com/google/go-containerregistry/pkg/v1/remote" "github.com/google/go-containerregistry/pkg/v1/remote/transport" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -984,6 +986,186 @@ COPY %s .`, testImageAlpine, inclFile) } } +func TestPushImage(t *testing.T) { + t.Parallel() + + t.Run("CacheWithoutPush", func(t *testing.T) { + t.Parallel() + + srv := createGitServer(t, gitServerOptions{ + files: map[string]string{ + ".devcontainer/Dockerfile": fmt.Sprintf("FROM %s\nRUN date --utc > /root/date.txt", testImageAlpine), + ".devcontainer/devcontainer.json": `{ + "name": "Test", + "build": { + "dockerfile": "Dockerfile" + }, + }`, + }, + }) + + // Given: an empty registry + testReg := setupInMemoryRegistry(t) + testRepo := testReg + "/test" + ref, err := name.ParseReference(testRepo + ":latest") + require.NoError(t, err) + _, err = remote.Image(ref) + require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push") + + // When: we run envbuilder with GET_CACHED_IMAGE + _, err = runEnvbuilder(t, options{env: []string{ + envbuilderEnv("GIT_URL", srv.URL), + envbuilderEnv("CACHE_REPO", testRepo), + envbuilderEnv("GET_CACHED_IMAGE", "1"), + }}) + require.ErrorContains(t, err, "not supported in fake build") + // Then: it should fail to build the image and nothing should be pushed + _, err = remote.Image(ref) + require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push") + + // When: we run envbuilder with PUSH_IMAGE set + _, err = runEnvbuilder(t, options{env: []string{ + envbuilderEnv("GIT_URL", srv.URL), + envbuilderEnv("CACHE_REPO", testRepo), + }}) + require.NoError(t, err) + + // Then: the image tag should not be present, only the layers + _, err = remote.Image(ref) + require.ErrorContains(t, err, "MANIFEST_UNKNOWN", "expected image to not be present before build + push") + + // Then: re-running envbuilder with GET_CACHED_IMAGE should succeed + _, err = runEnvbuilder(t, options{env: []string{ + envbuilderEnv("GIT_URL", srv.URL), + envbuilderEnv("CACHE_REPO", testRepo), + envbuilderEnv("GET_CACHED_IMAGE", "1"), + }}) + require.NoError(t, err) + }) + + t.Run("CacheAndPush", func(t *testing.T) { + t.Parallel() + + srv := createGitServer(t, gitServerOptions{ + files: map[string]string{ + ".devcontainer/Dockerfile": fmt.Sprintf("FROM %s\nRUN date --utc > /root/date.txt", testImageAlpine), + ".devcontainer/devcontainer.json": `{ + "name": "Test", + "build": { + "dockerfile": "Dockerfile" + }, + }`, + }, + }) + + // Given: an empty registry + testReg := setupInMemoryRegistry(t) + testRepo := testReg + "/test" + ref, err := name.ParseReference(testRepo + ":latest") + require.NoError(t, err) + _, err = remote.Image(ref) + require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push") + + // When: we run envbuilder with GET_CACHED_IMAGE + _, err = runEnvbuilder(t, options{env: []string{ + envbuilderEnv("GIT_URL", srv.URL), + envbuilderEnv("CACHE_REPO", testRepo), + envbuilderEnv("GET_CACHED_IMAGE", "1"), + }}) + require.ErrorContains(t, err, "not supported in fake build") + // Then: it should fail to build the image and nothing should be pushed + _, err = remote.Image(ref) + require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push") + + // When: we run envbuilder with PUSH_IMAGE set + _, err = runEnvbuilder(t, options{env: []string{ + envbuilderEnv("GIT_URL", srv.URL), + envbuilderEnv("CACHE_REPO", testRepo), + envbuilderEnv("PUSH_IMAGE", "1"), + }}) + require.NoError(t, err) + + // Then: the image should be pushed + _, err = remote.Image(ref) + require.NoError(t, err, "expected image to be present after build + push") + + // Then: re-running envbuilder with GET_CACHED_IMAGE should succeed + _, err = runEnvbuilder(t, options{env: []string{ + envbuilderEnv("GIT_URL", srv.URL), + envbuilderEnv("CACHE_REPO", testRepo), + envbuilderEnv("GET_CACHED_IMAGE", "1"), + }}) + require.NoError(t, err) + }) + + t.Run("PushImageRequiresCache", func(t *testing.T) { + t.Parallel() + + srv := createGitServer(t, gitServerOptions{ + files: map[string]string{ + ".devcontainer/Dockerfile": fmt.Sprintf("FROM %s\nRUN date --utc > /root/date.txt", testImageAlpine), + ".devcontainer/devcontainer.json": `{ + "name": "Test", + "build": { + "dockerfile": "Dockerfile" + }, + }`, + }, + }) + + // When: we run envbuilder with PUSH_IMAGE set but no cache repo set + _, err := runEnvbuilder(t, options{env: []string{ + envbuilderEnv("GIT_URL", srv.URL), + envbuilderEnv("PUSH_IMAGE", "1"), + }}) + + // Then: Envbuilder should fail explicitly, as it does not make sense to + // specify PUSH_IMAGE + require.ErrorContains(t, err, "--cache-repo must be set when using --push-image") + }) + + t.Run("PushErr", func(t *testing.T) { + t.Parallel() + + srv := createGitServer(t, gitServerOptions{ + files: map[string]string{ + ".devcontainer/Dockerfile": fmt.Sprintf("FROM %s\nRUN date --utc > /root/date.txt", testImageAlpine), + ".devcontainer/devcontainer.json": `{ + "name": "Test", + "build": { + "dockerfile": "Dockerfile" + }, + }`, + }, + }) + + // Given: registry is not set up (in this case, not a registry) + notRegSrv := httptest.NewServer(http.NotFoundHandler()) + notRegURL := strings.TrimPrefix(notRegSrv.URL, "http://") + "/test" + + // When: we run envbuilder with PUSH_IMAGE set + _, err := runEnvbuilder(t, options{env: []string{ + envbuilderEnv("GIT_URL", srv.URL), + envbuilderEnv("CACHE_REPO", notRegURL), + envbuilderEnv("PUSH_IMAGE", "1"), + }}) + + // Then: envbuilder should fail with a descriptive error + require.ErrorContains(t, err, "failed to push to destination") + }) +} + +func setupInMemoryRegistry(t *testing.T) string { + t.Helper() + tempDir := t.TempDir() + testReg := registry.New(registry.WithBlobHandler(registry.NewDiskBlobHandler(tempDir))) + regSrv := httptest.NewServer(testReg) + t.Cleanup(func() { regSrv.Close() }) + regSrvURL, err := url.Parse(regSrv.URL) + require.NoError(t, err) + return fmt.Sprintf("localhost:%s", regSrvURL.Port()) +} + // TestMain runs before all tests to build the envbuilder image. func TestMain(m *testing.M) { checkTestRegistry() @@ -1187,6 +1369,34 @@ func streamContainerLogs(t *testing.T, cli *client.Client, containerID string) ( return logChan, errChan } +func requireContainerLog(t *testing.T, ctrID, needle string) { + t.Helper() + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + require.NoError(t, err) + t.Cleanup(func() { + cli.Close() + }) + ctx := context.Background() + rawLogs, err := cli.ContainerLogs(ctx, ctrID, container.LogsOptions{ + ShowStdout: true, + ShowStderr: true, + Follow: true, + Timestamps: false, + }) + require.NoError(t, err) + defer rawLogs.Close() + scanner := bufio.NewScanner(rawLogs) + var found bool + for scanner.Scan() { + haystack := scanner.Text() + if strings.Contains(haystack, needle) { + found = true + break + } + } + require.True(t, found, "did not find expected log %q", needle) +} + func envbuilderEnv(env string, value string) string { return fmt.Sprintf("%s=%s", envbuilder.WithEnvPrefix(env), value) } diff --git a/options.go b/options.go index f411060b..a015a71a 100644 --- a/options.go +++ b/options.go @@ -406,15 +406,15 @@ func (o *Options) CLI() serpent.OptionSet { Flag: "push-image", Env: WithEnvPrefix("PUSH_IMAGE"), Value: serpent.BoolOf(&o.PushImage), - Description: "Flag to determine if the image should be pushed to " + - "the container registry. This option implies reproducible builds.", + Description: "Push the built image to a remote registry." + + "This option forces a reproducible build.", }, { Flag: "get-cached-image", Env: WithEnvPrefix("GET_CACHED_IMAGE"), Value: serpent.BoolOf(&o.GetCachedImage), - Description: "Flag to determine if the cached image is available, " + - "and if it is, to return it.", + Description: "Print the digest of the cached image, if available." + + "Exits with an error if not found.", }, } From a962a26301a46ce7535f250e7299c32e78115f6f Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 11 Jun 2024 15:26:38 +0100 Subject: [PATCH 08/13] unused code --- integration/integration_test.go | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/integration/integration_test.go b/integration/integration_test.go index e139124d..21934837 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -1369,34 +1369,6 @@ func streamContainerLogs(t *testing.T, cli *client.Client, containerID string) ( return logChan, errChan } -func requireContainerLog(t *testing.T, ctrID, needle string) { - t.Helper() - cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - require.NoError(t, err) - t.Cleanup(func() { - cli.Close() - }) - ctx := context.Background() - rawLogs, err := cli.ContainerLogs(ctx, ctrID, container.LogsOptions{ - ShowStdout: true, - ShowStderr: true, - Follow: true, - Timestamps: false, - }) - require.NoError(t, err) - defer rawLogs.Close() - scanner := bufio.NewScanner(rawLogs) - var found bool - for scanner.Scan() { - haystack := scanner.Text() - if strings.Contains(haystack, needle) { - found = true - break - } - } - require.True(t, found, "did not find expected log %q", needle) -} - func envbuilderEnv(env string, value string) string { return fmt.Sprintf("%s=%s", envbuilder.WithEnvPrefix(env), value) } From d804fc9a76dd039d93d30f3f784bf8f29d9df1da Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 11 Jun 2024 16:27:26 +0100 Subject: [PATCH 09/13] update options.golden --- testdata/options.golden | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testdata/options.golden b/testdata/options.golden index 43aee149..0fcc4e90 100644 --- a/testdata/options.golden +++ b/testdata/options.golden @@ -79,8 +79,8 @@ OPTIONS: customers. --get-cached-image bool, $ENVBUILDER_GET_CACHED_IMAGE - Flag to determine if the cached image is available, and if it is, to - return it. + Print the digest of the cached image, if available.Exits with an error + if not found. --git-clone-depth int, $ENVBUILDER_GIT_CLONE_DEPTH The depth to use when cloning the Git repository. @@ -134,8 +134,8 @@ OPTIONS: successful startup. --push-image bool, $ENVBUILDER_PUSH_IMAGE - Flag to determine if the image should be pushed to the container - registry. This option implies reproducible builds. + Push the built image to a remote registry.This option forces a + reproducible build. --setup-script string, $ENVBUILDER_SETUP_SCRIPT The script to run before the init script. It runs as the root user From b7502ee12162eecf4536c44246f38fa1323267bb Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 11 Jun 2024 17:31:48 +0100 Subject: [PATCH 10/13] add test for multistage build --- integration/integration_test.go | 66 +++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/integration/integration_test.go b/integration/integration_test.go index 147ba05d..42c518f5 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -1101,6 +1101,72 @@ func TestPushImage(t *testing.T) { require.NoError(t, err) }) + t.Run("CacheAndPushMultistage", func(t *testing.T) { + // Currently fails with: + // /home/coder/src/coder/envbuilder/integration/integration_test.go:1417: "error: unable to get cached image: error fake building stage: failed to optimize instructions: failed to get files used from context: failed to get fileinfo for /.envbuilder/0/root/date.txt: lstat /.envbuilder/0/root/date.txt: no such file or directory" + // /home/coder/src/coder/envbuilder/integration/integration_test.go:1156: + // Error Trace: /home/coder/src/coder/envbuilder/integration/integration_test.go:1156 + // Error: Received unexpected error: + // error: unable to get cached image: error fake building stage: failed to optimize instructions: failed to get files used from context: failed to get fileinfo for /.envbuilder/0/root/date.txt: lstat /.envbuilder/0/root/date.txt: no such file or directory + // Test: TestPushImage/CacheAndPushMultistage + t.Skip("TODO: https://github.com/coder/envbuilder/issues/230") + t.Parallel() + + srv := createGitServer(t, gitServerOptions{ + files: map[string]string{ + "Dockerfile": fmt.Sprintf(`FROM %s AS a +RUN date --utc > /root/date.txt +FROM %s as b +COPY --from=a /root/date.txt /date.txt`, testImageAlpine, testImageAlpine), + }, + }) + + // Given: an empty registry + testReg := setupInMemoryRegistry(t) + testRepo := testReg + "/test" + ref, err := name.ParseReference(testRepo + ":latest") + require.NoError(t, err) + _, err = remote.Image(ref) + require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push") + + // When: we run envbuilder with GET_CACHED_IMAGE + _, err = runEnvbuilder(t, options{env: []string{ + envbuilderEnv("GIT_URL", srv.URL), + envbuilderEnv("CACHE_REPO", testRepo), + envbuilderEnv("GET_CACHED_IMAGE", "1"), + envbuilderEnv("DOCKERFILE_PATH", "Dockerfile"), + }}) + require.ErrorContains(t, err, "not supported in fake build") + // Then: it should fail to build the image and nothing should be pushed + _, err = remote.Image(ref) + require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push") + + // When: we run envbuilder with PUSH_IMAGE set + ctrID, err := runEnvbuilder(t, options{env: []string{ + envbuilderEnv("GIT_URL", srv.URL), + envbuilderEnv("CACHE_REPO", testRepo), + envbuilderEnv("PUSH_IMAGE", "1"), + envbuilderEnv("DOCKERFILE_PATH", "Dockerfile"), + }}) + require.NoError(t, err) + // Then: The file copied from stage a should be present + out := execContainer(t, ctrID, "cat /date.txt") + require.NotEmpty(t, out) + + // Then: the image should be pushed + _, err = remote.Image(ref) + require.NoError(t, err, "expected image to be present after build + push") + + // Then: re-running envbuilder with GET_CACHED_IMAGE should succeed + _, err = runEnvbuilder(t, options{env: []string{ + envbuilderEnv("GIT_URL", srv.URL), + envbuilderEnv("CACHE_REPO", testRepo), + envbuilderEnv("GET_CACHED_IMAGE", "1"), + envbuilderEnv("DOCKERFILE_PATH", "Dockerfile"), + }}) + require.NoError(t, err) + }) + t.Run("PushImageRequiresCache", func(t *testing.T) { t.Parallel() From aacdbfcd52e806f01b048a34551192a0de34ca80 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Wed, 12 Jun 2024 09:38:37 +0100 Subject: [PATCH 11/13] Apply suggestions from code review Co-authored-by: Danny Kopping --- envbuilder.go | 4 ++-- options.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/envbuilder.go b/envbuilder.go index f727de31..307a55dd 100644 --- a/envbuilder.go +++ b/envbuilder.go @@ -99,7 +99,7 @@ func Run(ctx context.Context, options Options) error { options.InitCommand = "/bin/sh" } if options.CacheRepo == "" && options.PushImage { - return fmt.Errorf("--cache-repo must be set when using --push-image!") + return fmt.Errorf("--cache-repo must be set when using --push-image") } // Default to the shell! initArgs := []string{"-c", options.InitScript} @@ -531,7 +531,7 @@ func Run(ctx context.Context, options Options) error { endStage := startStage("🏗️ Checking for cached image...") image, err := executor.DoCacheProbe(opts) if err != nil { - return nil, xerrors.Errorf("unable to get cached image: %w", err) + return nil, xerrors.Errorf("get cached image: %w", err) } digest, err := image.Digest() if err != nil { diff --git a/options.go b/options.go index 86317dfe..8f29f071 100644 --- a/options.go +++ b/options.go @@ -406,7 +406,7 @@ func (o *Options) CLI() serpent.OptionSet { Flag: "push-image", Env: WithEnvPrefix("PUSH_IMAGE"), Value: serpent.BoolOf(&o.PushImage), - Description: "Push the built image to a remote registry." + + Description: "Push the built image to a remote registry. " + "This option forces a reproducible build.", }, { From 149bdb37c9bd8e84d9153773872ef7219a184c37 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Wed, 12 Jun 2024 10:50:26 +0100 Subject: [PATCH 12/13] fix help output --- README.md | 4 ++-- options.go | 2 +- testdata/options.golden | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c89d33b6..909d6afe 100644 --- a/README.md +++ b/README.md @@ -362,6 +362,6 @@ On MacOS or Windows systems, we recommend either using a VM or the provided `.de | `--coder-agent-url` | `CODER_AGENT_URL` | | URL of the Coder deployment. If CODER_AGENT_TOKEN is also set, logs from envbuilder will be forwarded here and will be visible in the workspace build logs. | | `--coder-agent-token` | `CODER_AGENT_TOKEN` | | Authentication token for a Coder agent. If this is set, then CODER_AGENT_URL must also be set. | | `--coder-agent-subsystem` | `CODER_AGENT_SUBSYSTEM` | | Coder agent subsystems to report when forwarding logs. The envbuilder subsystem is always included. | -| `--push-image` | `ENVBUILDER_PUSH_IMAGE` | | Push the built image to a remote registry.This option forces a reproducible build. | -| `--get-cached-image` | `ENVBUILDER_GET_CACHED_IMAGE` | | Print the digest of the cached image, if available.Exits with an error if not found. | +| `--push-image` | `ENVBUILDER_PUSH_IMAGE` | | Push the built image to a remote registry. This option forces a reproducible build. | +| `--get-cached-image` | `ENVBUILDER_GET_CACHED_IMAGE` | | Print the digest of the cached image, if available. Exits with an error if not found. | diff --git a/options.go b/options.go index 8f29f071..2913fdea 100644 --- a/options.go +++ b/options.go @@ -413,7 +413,7 @@ func (o *Options) CLI() serpent.OptionSet { Flag: "get-cached-image", Env: WithEnvPrefix("GET_CACHED_IMAGE"), Value: serpent.BoolOf(&o.GetCachedImage), - Description: "Print the digest of the cached image, if available." + + Description: "Print the digest of the cached image, if available. " + "Exits with an error if not found.", }, } diff --git a/testdata/options.golden b/testdata/options.golden index 44357ee4..73e68540 100644 --- a/testdata/options.golden +++ b/testdata/options.golden @@ -79,8 +79,8 @@ OPTIONS: customers. --get-cached-image bool, $ENVBUILDER_GET_CACHED_IMAGE - Print the digest of the cached image, if available.Exits with an error - if not found. + Print the digest of the cached image, if available. Exits with an + error if not found. --git-clone-depth int, $ENVBUILDER_GIT_CLONE_DEPTH The depth to use when cloning the Git repository. @@ -135,7 +135,7 @@ OPTIONS: successful startup. --push-image bool, $ENVBUILDER_PUSH_IMAGE - Push the built image to a remote registry.This option forces a + Push the built image to a remote registry. This option forces a reproducible build. --setup-script string, $ENVBUILDER_SETUP_SCRIPT From 354d8852328499a88c37e0b957b8d40891a3e715 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Wed, 12 Jun 2024 10:51:08 +0100 Subject: [PATCH 13/13] update kaniko to remove fake verbiage when probing build cache --- go.mod | 4 +--- go.sum | 19 +++++-------------- integration/integration_test.go | 6 +++--- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/go.mod b/go.mod index 69d96fe3..74d3b3d2 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.22.3 // There are a few options we need added to Kaniko! // See: https://github.com/GoogleContainerTools/kaniko/compare/main...coder:kaniko:main -replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240610145227-0a73fcd89e3f +replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240612094751-9d2f7eaa733c require ( cdr.dev/slog v1.6.2-0.20240126064726-20367d4aede6 @@ -105,7 +105,6 @@ require ( github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 // indirect github.com/ePirat/docker-credential-gitlabci v1.0.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -118,7 +117,6 @@ require ( github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/gomodule/redigo v1.8.9 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/mux v1.8.1 // indirect diff --git a/go.sum b/go.sum index 8b8e55a4..7e3a7fc0 100644 --- a/go.sum +++ b/go.sum @@ -98,6 +98,9 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/breml/rootcerts v0.2.10 h1:UGVZ193UTSUASpGtg6pbDwzOd7XQP+at0Ssg1/2E4h8= github.com/breml/rootcerts v0.2.10/go.mod h1:24FDtzYMpqIeYC7QzaE8VPRQaFZU5TIUDlyk8qwjD88= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= +github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0= +github.com/bsm/ginkgo/v2 v2.9.5/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= @@ -123,8 +126,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coder/kaniko v0.0.0-20240610145227-0a73fcd89e3f h1:o5p2u5sF1KVMgH+pcoMNfStpfXe76O3Enwg0h1KlzIU= -github.com/coder/kaniko v0.0.0-20240610145227-0a73fcd89e3f/go.mod h1:YMK7BlxerzLlMwihGxNWUaFoN9LXCij4P+w/8/fNlcM= +github.com/coder/kaniko v0.0.0-20240612094751-9d2f7eaa733c h1:m/cK7QW+IIydq+7zmuGesY1k6CEZlKooSF+KtIcXke8= +github.com/coder/kaniko v0.0.0-20240612094751-9d2f7eaa733c/go.mod h1:YMK7BlxerzLlMwihGxNWUaFoN9LXCij4P+w/8/fNlcM= github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 h1:3A0ES21Ke+FxEM8CXx9n47SZOKOpgSE1bbJzlE4qPVs= github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0/go.mod h1:5UuS2Ts+nTToAMeOjNlnHFkPahrtDkmpydBen/3wgZc= github.com/coder/retry v1.5.1 h1:iWu8YnD8YqHs3XwqrqsjoBTAVqT9ml6z9ViJ2wlMiqc= @@ -165,12 +168,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= -github.com/distribution/distribution/v3 v3.0.0-20230629214736-bac7f02e02a1 h1:yRwt9RluqBtKyDLRY7J0Cf/TVqvG56vKx2Eyndy8qNQ= -github.com/distribution/distribution/v3 v3.0.0-20230629214736-bac7f02e02a1/go.mod h1:+fqBJ4vPYo4Uu1ZE4d+bUtTLRXfdSL3NvCZIZ9GHv58= github.com/distribution/distribution/v3 v3.0.0-alpha.1 h1:jn7I1gvjOvmLztH1+1cLiUFud7aeJCIQcgzugtwjyJo= github.com/distribution/distribution/v3 v3.0.0-alpha.1/go.mod h1:LCp4JZp1ZalYg0W/TN05jarCQu+h4w7xc7ZfQF4Y/cY= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/cli v26.1.0+incompatible h1:+nwRy8Ocd8cYNQ60mozDDICICD8aoFGtlPXifX/UQ3Y= @@ -189,8 +188,6 @@ github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQ github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/ePirat/docker-credential-gitlabci v1.0.0 h1:YRkUSvkON6rT88vtscClAmPEYWhtltGEAuRVYtz1/+Y= github.com/ePirat/docker-credential-gitlabci v1.0.0/go.mod h1:Ptmh+D0lzBQtgb6+QHjXl9HqOn3T1P8fKUHldiSQQGA= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= @@ -260,8 +257,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws= -github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -280,8 +275,6 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= @@ -393,8 +386,6 @@ github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= diff --git a/integration/integration_test.go b/integration/integration_test.go index 42c518f5..85d6a877 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -1021,7 +1021,7 @@ func TestPushImage(t *testing.T) { envbuilderEnv("CACHE_REPO", testRepo), envbuilderEnv("GET_CACHED_IMAGE", "1"), }}) - require.ErrorContains(t, err, "not supported in fake build") + require.ErrorContains(t, err, "error probing build cache: uncached command") // Then: it should fail to build the image and nothing should be pushed _, err = remote.Image(ref) require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push") @@ -1075,7 +1075,7 @@ func TestPushImage(t *testing.T) { envbuilderEnv("CACHE_REPO", testRepo), envbuilderEnv("GET_CACHED_IMAGE", "1"), }}) - require.ErrorContains(t, err, "not supported in fake build") + require.ErrorContains(t, err, "error probing build cache: uncached command") // Then: it should fail to build the image and nothing should be pushed _, err = remote.Image(ref) require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push") @@ -1136,7 +1136,7 @@ COPY --from=a /root/date.txt /date.txt`, testImageAlpine, testImageAlpine), envbuilderEnv("GET_CACHED_IMAGE", "1"), envbuilderEnv("DOCKERFILE_PATH", "Dockerfile"), }}) - require.ErrorContains(t, err, "not supported in fake build") + require.ErrorContains(t, err, "error probing build cache: uncached command") // Then: it should fail to build the image and nothing should be pushed _, err = remote.Image(ref) require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push")