Skip to content

Commit

Permalink
feat: implement reproducible build and get cached image
Browse files Browse the repository at this point in the history
  • Loading branch information
mafredri committed May 30, 2024
1 parent 6cb1217 commit 42b6121
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 11 deletions.
41 changes: 33 additions & 8 deletions envbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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))
}
})

Expand Down Expand Up @@ -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 {
Expand All @@ -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,
Expand Down Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
21 changes: 21 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -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_"
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 42b6121

Please sign in to comment.