diff --git a/docs/packages.md b/docs/packages.md index 3b5e96ff8..792dca7c3 100644 --- a/docs/packages.md +++ b/docs/packages.md @@ -50,6 +50,7 @@ A package source consists of a directory containing at least two files: - `image` _(string)_: *(mandatory)* The name of the image to build - `org` _(string)_: The hub/registry organisation to which this package belongs +- `tag` _(string)_: The tag to use for the image, can be fixed string or template (default: `{{.Hash}}`) - `dockerfile` _(string)_: The dockerfile to use to build this package, must be in this directory or below (default: `Dockerfile`) - `arches` _(list of string)_: The architectures which this package should be built for (valid entries are `GOARCH` names) - `extra-sources` _(list of strings)_: Additional sources for the package outside the package directory. The format is `src:dst`, where `src` can be relative to the package directory and `dst` is the destination in the build context. This is useful for sharing files, such as vendored go code, between packages. diff --git a/src/cmd/linuxkit/buildtemplate.go b/src/cmd/linuxkit/buildtemplate.go index d534b4a4d..1e2ab4dbf 100644 --- a/src/cmd/linuxkit/buildtemplate.go +++ b/src/cmd/linuxkit/buildtemplate.go @@ -22,12 +22,13 @@ func createPackageResolver(baseDir string) spec.PackageResolver { pkgValue = pkgTmpl case strings.HasPrefix(pkgTmpl, templateFlag+templatePkg): pkgPath := strings.TrimPrefix(pkgTmpl, templateFlag+templatePkg) + piBase := pkglib.NewPkgInfo() var pkgs []pkglib.Pkg pkgConfig := pkglib.PkglibConfig{ BuildYML: defaultPkgBuildYML, HashCommit: defaultPkgCommit, - Tag: defaultPkgTag, + Tag: piBase.Tag, } pkgs, err = pkglib.NewFromConfig(pkgConfig, path.Join(baseDir, pkgPath)) if err != nil { diff --git a/src/cmd/linuxkit/const.go b/src/cmd/linuxkit/const.go index 93161cf02..4d97129a3 100644 --- a/src/cmd/linuxkit/const.go +++ b/src/cmd/linuxkit/const.go @@ -3,5 +3,4 @@ package main const ( defaultPkgBuildYML = "build.yml" defaultPkgCommit = "HEAD" - defaultPkgTag = "{{.Hash}}" ) diff --git a/src/cmd/linuxkit/pkg.go b/src/cmd/linuxkit/pkg.go index 3920f91b0..33bcaa300 100644 --- a/src/cmd/linuxkit/pkg.go +++ b/src/cmd/linuxkit/pkg.go @@ -37,7 +37,6 @@ func pkgCmd() *cobra.Command { HashPath: hashPath, Dirty: dirty, Dev: devMode, - Tag: tag, } if cmd.Flags().Changed("disable-cache") && cmd.Flags().Changed("enable-cache") { return errors.New("cannot set but disable-cache and enable-cache") @@ -65,6 +64,9 @@ func pkgCmd() *cobra.Command { if cmd.Flags().Changed("org") { pkglibConfig.Org = &argOrg } + if cmd.Flags().Changed("tag") { + pkglibConfig.Tag = tag + } return nil }, @@ -88,7 +90,7 @@ func pkgCmd() *cobra.Command { cmd.PersistentFlags().StringVar(&argOrg, "org", piBase.Org, "Override the hub org") cmd.PersistentFlags().StringVar(&buildYML, "build-yml", defaultPkgBuildYML, "Override the name of the yml file") cmd.PersistentFlags().StringVar(&hash, "hash", "", "Override the image hash (default is to query git for the package's tree-sh)") - cmd.PersistentFlags().StringVar(&tag, "tag", defaultPkgTag, "Override the tag using fixed strings and/or text templates. Acceptable are .Hash for the hash") + cmd.PersistentFlags().StringVar(&tag, "tag", piBase.Tag, "Override the tag using fixed strings and/or text templates. Acceptable are .Hash for the hash") cmd.PersistentFlags().StringVar(&hashCommit, "hash-commit", defaultPkgCommit, "Override the git commit to use for the hash") cmd.PersistentFlags().StringVar(&hashPath, "hash-path", "", "Override the directory to use for the image hash, must be a parent of the package dir (default is to use the package dir)") cmd.PersistentFlags().BoolVar(&dirty, "force-dirty", false, "Force the pkg(s) to be considered dirty") diff --git a/src/cmd/linuxkit/pkglib/pkglib.go b/src/cmd/linuxkit/pkglib/pkglib.go index f16d8dc3a..4e0bf88dd 100644 --- a/src/cmd/linuxkit/pkglib/pkglib.go +++ b/src/cmd/linuxkit/pkglib/pkglib.go @@ -20,6 +20,7 @@ import ( type pkgInfo struct { Image string `yaml:"image"` Org string `yaml:"org"` + Tag string `yaml:"tag,omitempty"` // default to {{.Hash}} Dockerfile string `yaml:"dockerfile"` Arches []string `yaml:"arches"` ExtraSources []string `yaml:"extra-sources"` @@ -60,6 +61,7 @@ func NewPkgInfo() pkgInfo { return pkgInfo{ Org: "linuxkit", Arches: []string{"amd64", "arm64"}, + Tag: "{{.Hash}}", GitRepo: "https://github.com/linuxkit/linuxkit", Network: false, DisableCache: false, @@ -257,9 +259,16 @@ func NewFromConfig(cfg PkglibConfig, args ...string) ([]Pkg, error) { } } } + tagTmpl := pi.Tag + if cfg.Tag != "" { + tagTmpl = cfg.Tag + } + if tagTmpl == "" { + tagTmpl = "{{.Hash}}" + } // calculate the tag to use based on the template and the pkgHash - tmpl, err := template.New("tag").Parse(cfg.Tag) + tmpl, err := template.New("tag").Parse(tagTmpl) if err != nil { return nil, fmt.Errorf("invalid tag template: %v", err) } diff --git a/test/cases/000_build/057_pkg_tag/000_tag_yaml/Dockerfile b/test/cases/000_build/057_pkg_tag/000_tag_yaml/Dockerfile new file mode 100644 index 000000000..abf8b7c7b --- /dev/null +++ b/test/cases/000_build/057_pkg_tag/000_tag_yaml/Dockerfile @@ -0,0 +1 @@ +FROM alpine:3.20 diff --git a/test/cases/000_build/057_pkg_tag/000_tag_yaml/build.yml b/test/cases/000_build/057_pkg_tag/000_tag_yaml/build.yml new file mode 100644 index 000000000..69b6730e4 --- /dev/null +++ b/test/cases/000_build/057_pkg_tag/000_tag_yaml/build.yml @@ -0,0 +1,3 @@ +org: linuxkit +image: image-with-tag +tag: file diff --git a/test/cases/000_build/057_pkg_tag/000_tag_yaml/test.sh b/test/cases/000_build/057_pkg_tag/000_tag_yaml/test.sh new file mode 100644 index 000000000..2f903a838 --- /dev/null +++ b/test/cases/000_build/057_pkg_tag/000_tag_yaml/test.sh @@ -0,0 +1,16 @@ +#!/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 . + +# just run docker image inspect; if it does not exist, it will error out +linuxkit cache ls 2>&1 | grep 'linuxkit/image-with-tag:file' + +exit 0 diff --git a/test/cases/000_build/057_pkg_tag/001_tag_cli/Dockerfile b/test/cases/000_build/057_pkg_tag/001_tag_cli/Dockerfile new file mode 100644 index 000000000..abf8b7c7b --- /dev/null +++ b/test/cases/000_build/057_pkg_tag/001_tag_cli/Dockerfile @@ -0,0 +1 @@ +FROM alpine:3.20 diff --git a/test/cases/000_build/057_pkg_tag/001_tag_cli/build.yml b/test/cases/000_build/057_pkg_tag/001_tag_cli/build.yml new file mode 100644 index 000000000..84d0af403 --- /dev/null +++ b/test/cases/000_build/057_pkg_tag/001_tag_cli/build.yml @@ -0,0 +1,2 @@ +org: linuxkit +image: image-with-tag diff --git a/test/cases/000_build/057_pkg_tag/001_tag_cli/test.sh b/test/cases/000_build/057_pkg_tag/001_tag_cli/test.sh new file mode 100644 index 000000000..fcd0da36a --- /dev/null +++ b/test/cases/000_build/057_pkg_tag/001_tag_cli/test.sh @@ -0,0 +1,16 @@ +#!/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 --tag cli . + +# just run docker image inspect; if it does not exist, it will error out +linuxkit cache ls 2>&1 | grep 'linuxkit/image-with-tag:cli' + +exit 0 diff --git a/test/cases/000_build/057_pkg_tag/002_tag_cli_over_yaml/Dockerfile b/test/cases/000_build/057_pkg_tag/002_tag_cli_over_yaml/Dockerfile new file mode 100644 index 000000000..abf8b7c7b --- /dev/null +++ b/test/cases/000_build/057_pkg_tag/002_tag_cli_over_yaml/Dockerfile @@ -0,0 +1 @@ +FROM alpine:3.20 diff --git a/test/cases/000_build/057_pkg_tag/002_tag_cli_over_yaml/build.yml b/test/cases/000_build/057_pkg_tag/002_tag_cli_over_yaml/build.yml new file mode 100644 index 000000000..2a0793d38 --- /dev/null +++ b/test/cases/000_build/057_pkg_tag/002_tag_cli_over_yaml/build.yml @@ -0,0 +1,3 @@ +org: linuxkit +image: image-with-tag +tag: file-new diff --git a/test/cases/000_build/057_pkg_tag/002_tag_cli_over_yaml/test.sh b/test/cases/000_build/057_pkg_tag/002_tag_cli_over_yaml/test.sh new file mode 100644 index 000000000..3231155ad --- /dev/null +++ b/test/cases/000_build/057_pkg_tag/002_tag_cli_over_yaml/test.sh @@ -0,0 +1,22 @@ +#!/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 --tag cli . + +# just run docker image inspect; if it does not exist, it will error out +linuxkit cache ls 2>&1 | grep 'linuxkit/image-with-tag:cli' + +# specifically, the `file` tag should not exist, so check that it does not exist +if linuxkit cache ls 2>&1 | grep 'linuxkit/image-with-tag:file-new'; then + echo "ERROR: image with tag 'file-new' should not exist" + exit 1 +fi + +exit 0