Conversation
There was a problem hiding this comment.
Pull request overview
Adds Buildah-based image build/publish support to kbld, integrating it as an additional builder option alongside existing Docker/buildx/ko/pack/etc flows.
Changes:
- Introduces a new
buildah:source configuration (SourceBuildahOpts) and a Buildah builder implementation that builds viabuildah build --manifestand pushes viabuildah manifest push. - Wires Buildah into the image build factory and build dispatch logic (
Factory/BuiltImage). - Updates tagging behavior to only apply
ImageDestinations.tagswhen the produced image URL is digest-qualified, and adds an e2e test covering build+push.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
pkg/kbld/builder/buildah/buildah.go |
New Buildah builder implementation for build + manifest push + digest retrieval. |
pkg/kbld/config/config_buildah.go |
New config types + arg rendering for Buildah builds. |
pkg/kbld/config/config.go |
Adds Buildah to config.Source to enable buildah: in Sources. |
pkg/kbld/image/built.go |
Routes builds through Buildah when configured. |
pkg/kbld/image/factory.go |
Instantiates Buildah builder and passes it into BuiltImage. |
pkg/kbld/image/tagged.go |
Applies destination tags only when URL includes a digest (@...). |
test/e2e/build_buildah_test.go |
New e2e test for Buildah build+push and digest-based output. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| package buildah | ||
|
|
There was a problem hiding this comment.
It should be:
// Copyright 2026 The Carvel Authors.
// SPDX-License-Identifier: Apache-2.0
| cmd := exec.Command("buildah", cmdArgs...) | ||
| cmd.Dir = directory | ||
| cmd.Stdout = prefixedLogger | ||
| cmd.Stderr = os.Stderr | ||
|
|
| // Provide explicit directory check error message because otherwise docker CLI | ||
| // outputs confusing msg 'error: fork/exec /usr/local/bin/docker: not a directory' |
| package e2e | ||
|
|
||
| import ( |
| pushLogger := b.logger.NewPrefixedWriter(image + " push | ") | ||
| remoteName := remoteImageName(image, imgDst) | ||
| digest, pushErr := BuildahPush(localName, remoteName, pushLogger) | ||
| if pushErr != nil { | ||
| return "", pushErr | ||
| } | ||
| remoteName = remoteName + "@" + digest | ||
| prefixedLogger.WriteStr("Image build : " + remoteName) | ||
| return remoteName, nil |
There was a problem hiding this comment.
Why using a random tag when one is provided by the user or "latest" is an easy choice. Random tags needs to be cleaned.
There was a problem hiding this comment.
This is the behavior that all the builders have so I think it does make sense to keep consistency in the tool.
There are some things we need to keep in mind;
- what happens when the user do not provide a tag?
- if this image does not pass tests, would you want it to always update the
latesttag? - what happens if the user provide more than 1 tag, which one do we choose? (i do not think it is a major deal because in the end we will have to tag with the other ones, but is just a deviation of what is done with other builders)
| // !!! with --digestfile, buildah will not return an error if an authentication is required. | ||
| log.WriteStr("=> buildah manifest push --all --digestfile=" + digestFile.Name() + " " + src + " docker://" + dest) | ||
| pushCommand := exec.Command("buildah", "manifest", "push", "--all", "--digestfile="+digestFile.Name(), src, "docker://"+dest) | ||
| pushCommand.Stdout = log | ||
| pushCommand.Stderr = log | ||
| pushErr := pushCommand.Run() | ||
| if pushErr != nil { | ||
| return "", fmt.Errorf("error pushing to %q (check if you are authenticated) : %w", dest, pushErr) | ||
| } | ||
|
|
||
| digest := make([]byte, 64+7) | ||
| digestLen, readErr := digestFile.Read(digest) | ||
| if readErr != nil { | ||
| return "", fmt.Errorf("cannot read digest in file %q (check if you are authenticated) : %w", digestFile.Name(), readErr) | ||
| } | ||
| return string(digest[0:digestLen]), nil |
There was a problem hiding this comment.
Buildah will write only the digest and nothing else (no space, no newline). This is a buildah specification.
| if len(i.imgDst.Tags) > 0 && strings.Contains(url, "@") { | ||
| // Configure new tags only if a digest is known | ||
| dstRef, err := regname.NewDigest(url, regname.WeakValidation) |
| expectedOut := env.WithRegistries(`--- | ||
| kind: Object | ||
| spec: | ||
| - image: index.docker.io/*username*/kbld-e2e-tests-build:latest@SHA256-REPLACED1 |
| for arg, value := range opts.BuildArgs { | ||
| args = append(args, "--build-arg="+arg+"="+value) | ||
| } |
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Build for multiple platforms. Use a manifest in all situations because buildah can not create a manifest when a tag already exists. Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Manifests for buildah and podman have no digest. Buildah pushs the manifest to all tags and TaggedImage must ignore the incomplete URL. Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
The manifest digest is written to a temporary file with the option --digestfile. Push only to a random tag and let kbld create the other tags. Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
…nation Use the destination name for local storage if available. The destination name use a special random tag. Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Generation logs are printed in direct using stderr. Flushes mid-sentence are not well rendered through logger. Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Using the same manifest name accumulates images. The local manifest needs a random name. Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Fix the linter checks. Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Add support for buildah to create and publish images.
The
buildah buildcommand with the--manifestoption is used to build an image.The
buildah manifest pushcommand sends the images to a remote registry and retrieve the digest (use a random tag like docker).Options example in sources:
The user can use rawOptions to add arguments like
--layers,--jobs=0or--cache-from. None of them is activated by default.