From de13ee521df7e16b4849eeca761911cc2df95182 Mon Sep 17 00:00:00 2001 From: Avi Deitcher Date: Thu, 8 Jun 2023 18:16:44 +0300 Subject: [PATCH] include source repo, revision and go package version as build-args Signed-off-by: Avi Deitcher --- docs/packages.md | 17 ++++++++++ src/cmd/linuxkit/pkglib/build.go | 27 +++++++++++++-- src/cmd/linuxkit/pkglib/git.go | 33 +++++++++++++++++++ test/cases/000_build/030_build_args/test.sh | 2 +- .../000_build/031_fixed_build_args/Dockerfile | 11 +++++++ .../000_build/031_fixed_build_args/build.yml | 5 +++ .../000_build/031_fixed_build_args/test.sh | 18 ++++++++++ 7 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 test/cases/000_build/031_fixed_build_args/Dockerfile create mode 100644 test/cases/000_build/031_fixed_build_args/build.yml create mode 100755 test/cases/000_build/031_fixed_build_args/test.sh diff --git a/docs/packages.md b/docs/packages.md index a617d602d..500c38931 100644 --- a/docs/packages.md +++ b/docs/packages.md @@ -264,6 +264,23 @@ linuxkit pkg build --platforms=linux/arm64 --builders linux/arm64=my-remote-arm6 linuxkit will try to build for `linux/arm64` using the context `my-remote-arm64`. Since that context does not exist, you will get an error. +##### Preset build arguments + +When building packages, the following build-args automatically are set for you: + +* `SOURCE` - the source repository of the package +* `REVISION` - the git commit that was used for the build +* `GOPKGVERSION` - the go package version or pseudo-version per https://go.dev/ref/mod#glos-pseudo-version + +Note that the above are set **only** if you do not set them in `build.yaml`. Your settings _always_ +override these built-in ones. + +To use them, simply address them in your `Dockerfile`: + +```dockerfile +ARG SOURCE +``` + ### Build packages as a maintainer All official LinuxKit packages are multi-arch manifests and most of diff --git a/src/cmd/linuxkit/pkglib/build.go b/src/cmd/linuxkit/pkglib/build.go index 52b7c0c51..e39f4649a 100644 --- a/src/cmd/linuxkit/pkglib/build.go +++ b/src/cmd/linuxkit/pkglib/build.go @@ -309,12 +309,23 @@ func (p Pkg) Build(bos ...BuildOpt) error { if p.git != nil && p.gitRepo != "" { imageBuildOpts.Labels["org.opencontainers.image.source"] = p.gitRepo } - if p.git != nil && !p.dirty { - commit, err := p.git.commitHash("HEAD") + var ( + gitCommit string + goPkgVersion string + ) + if p.git != nil { + if !p.dirty { + gitCommit, err = p.git.commitHash("HEAD") + if err != nil { + return err + } + imageBuildOpts.Labels["org.opencontainers.image.revision"] = gitCommit + } + // get the go version or pseudo-version + goPkgVersion, err = p.git.goPkgVersion() if err != nil { return err } - imageBuildOpts.Labels["org.opencontainers.image.revision"] = commit } imageBuildOpts.NetworkMode = "default" @@ -342,6 +353,16 @@ func (p Pkg) Build(bos ...BuildOpt) error { imageBuildOpts.BuildArgs[parts[0]] = &parts[1] } } + // add in information about the build process that might be useful + if _, ok := imageBuildOpts.BuildArgs["SOURCE"]; !ok && p.gitRepo != "" { + imageBuildOpts.BuildArgs["SOURCE"] = &p.gitRepo + } + if _, ok := imageBuildOpts.BuildArgs["REVISION"]; !ok && gitCommit != "" { + imageBuildOpts.BuildArgs["REVISION"] = &gitCommit + } + if _, ok := imageBuildOpts.BuildArgs["GOPKGVERSION"]; !ok && goPkgVersion != "" { + imageBuildOpts.BuildArgs["GOPKGVERSION"] = &goPkgVersion + } // build for each arch and save in the linuxkit cache for _, platform := range platformsToBuild { diff --git a/src/cmd/linuxkit/pkglib/git.go b/src/cmd/linuxkit/pkglib/git.go index 0723d95b1..007bd956d 100644 --- a/src/cmd/linuxkit/pkglib/git.go +++ b/src/cmd/linuxkit/pkglib/git.go @@ -211,3 +211,36 @@ func (g git) isDirty(pkg, commit string) (bool, error) { return false, err } } + +// goPkgVersion return a version that is compliant with go package versioning. +// This would either be: +// +// - The tag name if the most recent commit is tagged +// - The structure -- if the most recent commit is not tagged +// +// See https://go.dev/ref/mod for more information +func (g git) goPkgVersion() (string, error) { + lastSemver, _ := g.commandStdout(nil, "--no-pager", "describe", "--match='v[0-9].[0-9].[0-9]*'", "--abbrev=0", "--tags") + if lastSemver == "" { + lastSemver = "v0.0.0" + } + commitList := "HEAD" + if lastSemver != "v0.0.0" { + commitList = fmt.Sprintf("%s..HEAD", lastSemver) + } + count, err := g.commandStdout(nil, "rev-list", commitList, "--count") + if err != nil { + return "", err + } + version := "" + if count == "0" { + version = lastSemver + } else { + dateCommit, err := g.commandStdout(nil, "--no-pager", "show", "--quiet", "--abbrev=12", "--date=format-local:%Y%m%d%H%M%S", "--format=%cd-%h") + if err != nil { + return "", err + } + version = fmt.Sprintf("%s-%s", lastSemver, dateCommit) + } + return version, nil +} diff --git a/test/cases/000_build/030_build_args/test.sh b/test/cases/000_build/030_build_args/test.sh index 1d7bc1b38..958dd616f 100755 --- a/test/cases/000_build/030_build_args/test.sh +++ b/test/cases/000_build/030_build_args/test.sh @@ -10,7 +10,7 @@ set -ex . "${RT_PROJECT_ROOT}/_lib/lib.sh" # Test code goes here -echo Linuxkig is "$(which linuxkit)" +echo Linuxkit is "$(which linuxkit)" RESULT="$(2>&1 linuxkit pkg build --force . | grep PASSED)" echo RESULT="${RESULT}" echo "${RESULT}" | grep "Build-arg test PASSED" diff --git a/test/cases/000_build/031_fixed_build_args/Dockerfile b/test/cases/000_build/031_fixed_build_args/Dockerfile new file mode 100644 index 000000000..255d5b8fa --- /dev/null +++ b/test/cases/000_build/031_fixed_build_args/Dockerfile @@ -0,0 +1,11 @@ +FROM alpine:3.17 + +ARG SOURCE=FAILED +ARG REVISION=FAILED +ARG GOPKGVERSION=FAILED + +RUN echo "printf \"Build-arg test source $SOURCE\\n\"" >> check.sh +RUN echo "printf \"Build-arg test revision $REVISION\\n\"" >> check.sh +RUN echo "printf \"Build-arg test gopkgversion $GOPKGVERSION\\n\"" >> check.sh + +ENTRYPOINT ["/bin/sh", "/check.sh"] diff --git a/test/cases/000_build/031_fixed_build_args/build.yml b/test/cases/000_build/031_fixed_build_args/build.yml new file mode 100644 index 000000000..7ffcd5cbd --- /dev/null +++ b/test/cases/000_build/031_fixed_build_args/build.yml @@ -0,0 +1,5 @@ +image: build-args-test +network: true +arches: + - amd64 + - arm64 diff --git a/test/cases/000_build/031_fixed_build_args/test.sh b/test/cases/000_build/031_fixed_build_args/test.sh new file mode 100755 index 000000000..61c8ea0aa --- /dev/null +++ b/test/cases/000_build/031_fixed_build_args/test.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# SUMMARY: Check that the build-args are correctly passed to Dockerfiles +# LABELS: +# REPEAT: + +set -ex + +# Source libraries. Uncomment if needed/defined +#. "${RT_LIB}" +. "${RT_PROJECT_ROOT}/_lib/lib.sh" + +# Test code goes here +echo Linuxkit is "$(which linuxkit)" +RESULT="$(2>&1 linuxkit pkg build --force . | grep 'Build-arg test' || echo)" +echo RESULT="${RESULT}" +echo "${RESULT}" | grep -v "FAILED" + +exit 0