add support for build-arg files

Signed-off-by: Avi Deitcher <avi@deitcher.net>
This commit is contained in:
Avi Deitcher 2024-02-22 14:16:38 +02:00
parent 72be49c81c
commit 56543ed0a2
14 changed files with 101 additions and 1 deletions

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"bufio"
"errors" "errors"
"fmt" "fmt"
"os" "os"
@ -46,6 +47,7 @@ func addCmdRunPkgBuildPush(cmd *cobra.Command, withPush bool) *cobra.Command {
cacheDir = flagOverEnvVarOverDefaultString{def: defaultLinuxkitCache(), envVar: envVarCacheDir} cacheDir = flagOverEnvVarOverDefaultString{def: defaultLinuxkitCache(), envVar: envVarCacheDir}
sbomScanner string sbomScanner string
dockerfile string dockerfile string
buildArgFiles []string
) )
cmd.RunE = func(cmd *cobra.Command, args []string) error { cmd.RunE = func(cmd *cobra.Command, args []string) error {
@ -95,6 +97,24 @@ func addCmdRunPkgBuildPush(cmd *cobra.Command, withPush bool) *cobra.Command {
} }
opts = append(opts, pkglib.WithDockerfile(dockerfile)) opts = append(opts, pkglib.WithDockerfile(dockerfile))
// read any build arg files
var buildArgs []string
for _, filename := range buildArgFiles {
f, err := os.Open(filename)
if err != nil {
return fmt.Errorf("error opening build args file %s: %w", filename, err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
buildArgs = append(buildArgs, scanner.Text())
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("error reading build args file %s: %w", filename, err)
}
}
opts = append(opts, pkglib.WithBuildArgs(buildArgs))
// skipPlatformsMap contains platforms that should be skipped // skipPlatformsMap contains platforms that should be skipped
skipPlatformsMap := make(map[string]bool) skipPlatformsMap := make(map[string]bool)
if skipPlatforms != "" { if skipPlatforms != "" {
@ -205,6 +225,7 @@ func addCmdRunPkgBuildPush(cmd *cobra.Command, withPush bool) *cobra.Command {
cmd.Flags().BoolVar(&manifest, "manifest", true, "Create and push multi-arch manifest") cmd.Flags().BoolVar(&manifest, "manifest", true, "Create and push multi-arch manifest")
cmd.Flags().StringVar(&sbomScanner, "sbom-scanner", "", "SBOM scanner to use, must match the buildkit spec; set to blank to use the buildkit default; set to 'false' for no scanning") cmd.Flags().StringVar(&sbomScanner, "sbom-scanner", "", "SBOM scanner to use, must match the buildkit spec; set to blank to use the buildkit default; set to 'false' for no scanning")
cmd.Flags().StringVar(&dockerfile, "dockerfile", "", "Dockerfile to use for building the image, must be in this directory or below, overrides what is in build.yml") cmd.Flags().StringVar(&dockerfile, "dockerfile", "", "Dockerfile to use for building the image, must be in this directory or below, overrides what is in build.yml")
cmd.Flags().StringArrayVar(&buildArgFiles, "build-arg-file", nil, "Files containing build arguments, one key=value per line, contents augment and override buildArgs in build.yml. Can be specified multiple times. File is relative to working directory when running `linuxkit pkg build`")
return cmd return cmd
} }

View File

@ -44,6 +44,7 @@ type buildOpts struct {
sbomScan bool sbomScan bool
sbomScannerImage string sbomScannerImage string
dockerfile string dockerfile string
buildArgs []string
} }
// BuildOpt allows callers to specify options to Build // BuildOpt allows callers to specify options to Build
@ -195,6 +196,16 @@ func WithDockerfile(dockerfile string) BuildOpt {
} }
} }
// WithBuildArgs add build args to use when building the package
func WithBuildArgs(args []string) BuildOpt {
return func(bo *buildOpts) error {
// we copy the contents, rather than the reference to the slice, to be safe
bo.buildArgs = make([]string, len(args))
copy(bo.buildArgs, args)
return nil
}
}
// Build builds the package // Build builds the package
func (p Pkg) Build(bos ...BuildOpt) error { func (p Pkg) Build(bos ...BuildOpt) error {
var bo buildOpts var bo buildOpts
@ -380,6 +391,7 @@ func (p Pkg) Build(bos ...BuildOpt) error {
imageBuildOpts.Labels["org.mobyproject.linuxkit.version"] = version.Version imageBuildOpts.Labels["org.mobyproject.linuxkit.version"] = version.Version
imageBuildOpts.Labels["org.mobyproject.linuxkit.revision"] = version.GitCommit imageBuildOpts.Labels["org.mobyproject.linuxkit.revision"] = version.GitCommit
// add build args from the build.yml file
if p.buildArgs != nil { if p.buildArgs != nil {
for _, buildArg := range *p.buildArgs { for _, buildArg := range *p.buildArgs {
parts := strings.SplitN(buildArg, "=", 2) parts := strings.SplitN(buildArg, "=", 2)
@ -389,6 +401,15 @@ func (p Pkg) Build(bos ...BuildOpt) error {
imageBuildOpts.BuildArgs[parts[0]] = &parts[1] imageBuildOpts.BuildArgs[parts[0]] = &parts[1]
} }
} }
// add build args from other files
for _, buildArg := range bo.buildArgs {
parts := strings.SplitN(buildArg, "=", 2)
if len(parts) != 2 {
return fmt.Errorf("invalid build-arg, must be in format 'arg=value': %s", buildArg)
}
imageBuildOpts.BuildArgs[parts[0]] = &parts[1]
}
// add in information about the build process that might be useful // add in information about the build process that might be useful
if _, ok := imageBuildOpts.BuildArgs["SOURCE"]; !ok && p.gitRepo != "" { if _, ok := imageBuildOpts.BuildArgs["SOURCE"]; !ok && p.gitRepo != "" {
imageBuildOpts.BuildArgs["SOURCE"] = &p.gitRepo imageBuildOpts.BuildArgs["SOURCE"] = &p.gitRepo

View File

@ -473,10 +473,11 @@ func (dr *dockerRunnerImpl) build(ctx context.Context, tag, pkg, dockerfile, doc
solveOpts.Session = append(solveOpts.Session, up) solveOpts.Session = append(solveOpts.Session, up)
} else { } else {
solveOpts.LocalDirs = map[string]string{ solveOpts.LocalDirs = map[string]string{
builder.DefaultLocalNameDockerfile: path.Join(pkg, dockerfile), builder.DefaultLocalNameDockerfile: pkg,
builder.DefaultLocalNameContext: pkg, builder.DefaultLocalNameContext: pkg,
} }
} }
frontendAttrs["filename"] = dockerfile
// go through the dockerfile to see if we have any provided images cached // go through the dockerfile to see if we have any provided images cached
if c != nil { if c != nil {

View File

@ -0,0 +1,2 @@
ARG IMAGE
FROM ${IMAGE}

View File

@ -0,0 +1,4 @@
org: linuxkit
image: image-in-build-args
buildArgs:
- IMAGE=alpine:3.19

View File

@ -0,0 +1,13 @@
#!/bin/sh
# SUMMARY: Check that tar output format build is reproducible
# LABELS:
set -e
# Source libraries. Uncomment if needed/defined
#. "${RT_LIB}"
. "${RT_PROJECT_ROOT}/_lib/lib.sh"
linuxkit pkg build --force .
exit 0

View File

@ -0,0 +1,2 @@
ARG IMAGE
FROM ${IMAGE}

View File

@ -0,0 +1 @@
IMAGE=alpine:3.19

View File

@ -0,0 +1,2 @@
org: linuxkit
image: test-image-in-yaml-build-args

View File

@ -0,0 +1,13 @@
#!/bin/sh
# SUMMARY: Check that tar output format build is reproducible
# LABELS:
set -e
# Source libraries. Uncomment if needed/defined
#. "${RT_LIB}"
. "${RT_PROJECT_ROOT}/_lib/lib.sh"
linuxkit pkg build --force --build-arg-file build-args .
exit 0

View File

@ -0,0 +1,2 @@
ARG IMAGE
FROM ${IMAGE}

View File

@ -0,0 +1 @@
IMAGE=alpine:3.19

View File

@ -0,0 +1,4 @@
org: linuxkit
image: test-image-in-yaml-build-args-with-cli-override
buildArgs:
- IMAGE=non-existent:foo

View File

@ -0,0 +1,13 @@
#!/bin/sh
# SUMMARY: Check that tar output format build is reproducible
# LABELS:
set -e
# Source libraries. Uncomment if needed/defined
#. "${RT_LIB}"
. "${RT_PROJECT_ROOT}/_lib/lib.sh"
linuxkit pkg build --force --build-arg-file build-args .
exit 0