Skip to content

Buildah/podman support#543

Open
Baenimyr wants to merge 21 commits intocarvel-dev:developfrom
Baenimyr:buildah
Open

Buildah/podman support#543
Baenimyr wants to merge 21 commits intocarvel-dev:developfrom
Baenimyr:buildah

Conversation

@Baenimyr
Copy link
Copy Markdown

@Baenimyr Baenimyr commented Apr 29, 2025

Add support for buildah to create and publish images.

The buildah build command with the --manifest option is used to build an image.
The buildah manifest push command sends the images to a remote registry and retrieve the digest (use a random tag like docker).

Options example in sources:

buildah:
  pull: true
  target: "app"
  platforms:
    - linux/amd64
    - linux/arm64
  buildArgs:
    VERSION: latest
  rawOptions:
    - --layers
    - --jobs=0
    - --quiet

The user can use rawOptions to add arguments like --layers, --jobs=0 or --cache-from. None of them is activated by default.

  • build
  • push to destinations
  • get digest and let kbld create more tags
  • create tests

@Baenimyr Baenimyr marked this pull request as draft April 29, 2025 19:17
@Baenimyr Baenimyr temporarily deployed to DockerHub E2E May 1, 2025 14:28 — with GitHub Actions Inactive
@Baenimyr Baenimyr changed the title WIP: Buildah/podman support Buildah/podman support Jan 21, 2026
@Baenimyr Baenimyr marked this pull request as ready for review January 21, 2026 19:25
@joaopapereira joaopapereira requested a review from Copilot March 18, 2026 21:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 via buildah build --manifest and pushes via buildah manifest push.
  • Wires Buildah into the image build factory and build dispatch logic (Factory / BuiltImage).
  • Updates tagging behavior to only apply ImageDestinations.tags when 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.

Comment on lines +1 to +2
package buildah

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be:

// Copyright 2026 The Carvel Authors.
// SPDX-License-Identifier: Apache-2.0

Comment on lines +89 to +93
cmd := exec.Command("buildah", cmdArgs...)
cmd.Dir = directory
cmd.Stdout = prefixedLogger
cmd.Stderr = os.Stderr

Comment thread pkg/kbld/builder/buildah/buildah.go
Comment thread pkg/kbld/builder/buildah/buildah.go Outdated
Comment on lines +28 to +29
// Provide explicit directory check error message because otherwise docker CLI
// outputs confusing msg 'error: fork/exec /usr/local/bin/docker: not a directory'
Comment on lines +1 to +3
package e2e

import (
Comment on lines +101 to +109
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
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why using a random tag when one is provided by the user or "latest" is an easy choice. Random tags needs to be cleaned.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 latest tag?
  • 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)

Comment on lines +127 to +142
// !!! 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
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Buildah will write only the digest and nothing else (no space, no newline). This is a buildah specification.

Comment thread pkg/kbld/image/tagged.go
Comment on lines +31 to 33
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
Comment on lines +35 to +37
for arg, value := range opts.BuildArgs {
args = append(args, "--build-arg="+arg+"="+value)
}
Benjamin Le Rohellec added 16 commits April 8, 2026 18:28
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>
Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
@joaopapereira
Copy link
Copy Markdown
Member

@Baenimyr do you want to continue to work from this PR or want to swap to the one that I create #585 Do not mind either way

Fix the linter checks.

Signed-off-by: Benjamin Le Rohellec <benjamin@le-rohellec.fr>
Benjamin Le Rohellec added 3 commits April 9, 2026 22:32
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants