From 65bcf2900c6854d928b8aa275e038886a6d55f98 Mon Sep 17 00:00:00 2001 From: nkraetzschmar <9020053+nkraetzschmar@users.noreply.github.com> Date: Wed, 28 Oct 2026 23:15:44 +0100 Subject: [PATCH] refactor: make all nameings align with ADR 0035 Signed-off-by: nkraetzschmar <9020053+nkraetzschmar@users.noreply.github.com> --- .github/actions/setup/action.yml | 2 +- build | 13 ------- builder/Makefile | 58 +++++++++++++++-------------- builder/image.sbom | 3 ++ builder/make_get_image_dependencies | 4 +- builder/make_list_build_artifacts | 12 +++--- builder/parse_features | 50 ++++++++++++++----------- docs/reference/builder.md | 5 --- docs/reference/features.md | 21 +++++++++-- 9 files changed, 90 insertions(+), 78 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 6a5265a..1d28212 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -13,7 +13,7 @@ runs: sudo apt-get update if [ "${{ inputs.arch }}" = "amd64" ]; then sudo docker system prune -a -f - sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends qemu-user-static + sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends qemu-user-binfmt elif [ "${{ inputs.arch }}" = "arm64" ]; then sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends podman uidmap slirp4netns dbus-user-session id="$(id -u)" diff --git a/build b/build index c723ad3..134d3ba 100755 --- a/build +++ b/build @@ -21,7 +21,6 @@ container_run_opts=( container_cmd=() use_kms=0 -resolve_cname=0 allow_frankenstein=0 apparmor_profile= @@ -56,10 +55,6 @@ while [ $# -gt 0 ]; do printf '%s\n' "$container_image" >&3 exit 0 ;; - --resolve-cname) - resolve_cname=1 - shift - ;; --target) target_dir="$2" shift 2 @@ -96,14 +91,6 @@ timestamp="$(./get_timestamp)" default_version="$(./get_version)" -if [ "$resolve_cname" = 1 ]; then - arch="$("$container_engine" run --rm "${container_run_opts[@]}" "${container_mount_opts[@]}" "$container_image" dpkg --print-architecture)" - cname="$("$container_engine" run --rm "${container_run_opts[@]}" "${container_mount_opts[@]}" "$container_image" /builder/parse_features --feature-dir /builder/features --default-arch "$arch" --default-version "$default_version" --cname "$1")" - short_commit="$(head -c 8 <<< "$commit")" - echo "$cname-$short_commit" >&3 - exit 0 -fi - make_opts=( REPO="$repo" COMMIT="$commit" diff --git a/builder/Makefile b/builder/Makefile index de695b2..1fd8eef 100644 --- a/builder/Makefile +++ b/builder/Makefile @@ -12,8 +12,8 @@ MAKEFLAGS += --no-builtin-rules lastword = $(word $(words $1),$1) prelastword = $(word $(words $1),_ $1) -cname_version = $(call lastword,$(subst -, ,$1)) -cname_arch = $(call prelastword,$(subst -, ,$1)) +extract_version = $(call lastword,$(subst -, ,$1)) +extract_arch = $(call prelastword,$(subst -, ,$1)) define require_var = ifndef $1 @@ -43,32 +43,34 @@ clean: .build/%.sentinel: true -.build/bootstrap-%-$(SHORT_COMMIT).tar: $$(shell ./make_repo_sentinel $$(REPO) $$(call cname_version,$$*)) +.build/bootstrap-%-$(SHORT_COMMIT).tar: $$(shell ./make_repo_sentinel $$(REPO) $$(call extract_version,$$*)) target '$@' info 'bootstrapping $*-$(SHORT_COMMIT)' - arch='$(call cname_arch,$*)' - version='$(call cname_version,$*)' + arch='$(call extract_arch,$*)' + version='$(call extract_version,$*)' ./bootstrap "$$arch" "$$version" '$(REPO)' keyring.gpg '$@' -.build/%-$(SHORT_COMMIT).tar: .build/bootstrap-$$(call cname_arch,$$*)-$$(call cname_version,$$*)-$(SHORT_COMMIT).tar $(shell ./make_directory_sentinel features) $(shell ./make_directory_sentinel cert) +.build/%-$(SHORT_COMMIT).tar: .build/bootstrap-$$(call extract_arch,$$*)-$$(call extract_version,$$*)-$(SHORT_COMMIT).tar $(shell ./make_directory_sentinel features) $(shell ./make_directory_sentinel cert) target '$@' '$<' info 'configuring rootfs $*-$(SHORT_COMMIT)' - features="$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --cname '$*' features)" - features_platforms="$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --cname '$*' platforms)" - features_elements="$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --cname '$*' elements)" - features_flags="$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --cname '$*' flags)" - cname_base="$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --cname '$*' cname_base)" - BUILDER_CNAME='$*' - BUILDER_CNAME_BASE="$$cname_base" - BUILDER_VERSION='$(call cname_version,$*)' - BUILDER_ARCH='$(call cname_arch,$*)' + features="$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --target '$*' features)" + features_platforms="$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --target '$*' platforms)" + features_elements="$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --target '$*' elements)" + features_flags="$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --target '$*' flags)" + cname="$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --target '$*' cname)" + BUILDER_CNAME="$$cname" + BUILDER_FLAVOR="$$cname-$(call extract_arch,$*)" + BUILDER_VERSIONED_FLAVOR='$*' + BUILDER_ARTIFACT_BASE='$*-$(SHORT_COMMIT)' + BUILDER_VERSION='$(call extract_version,$*)' + BUILDER_ARCH='$(call extract_arch,$*)' BUILDER_TIMESTAMP='$(TIMESTAMP)' BUILDER_COMMIT='$(COMMIT)' BUILDER_FEATURES="$$features" BUILDER_FEATURES_PLATFORMS="$$features_platforms" BUILDER_FEATURES_ELEMENTS="$$features_elements" BUILDER_FEATURES_FLAGS="$$features_flags" - export BUILDER_CNAME BUILDER_CNAME_BASE BUILDER_VERSION BUILDER_ARCH BUILDER_TIMESTAMP BUILDER_COMMIT BUILDER_FEATURES BUILDER_FEATURES_PLATFORMS BUILDER_FEATURES_ELEMENTS BUILDER_FEATURES_FLAGS + export BUILDER_CNAME BUILDER_FLAVOR BUILDER_VERSIONED_FLAVOR BUILDER_ARTIFACT_BASE BUILDER_VERSION BUILDER_ARCH BUILDER_TIMESTAMP BUILDER_COMMIT BUILDER_FEATURES BUILDER_FEATURES_PLATFORMS BUILDER_FEATURES_ELEMENTS BUILDER_FEATURES_FLAGS ./configure '$(word 1,$^)' '$@' define artifact_template = @@ -77,22 +79,24 @@ define artifact_template = input='$$(word 2,$$^)' target '$$@' "$$$$input" info 'building $1 image $$*' - features="$$$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --cname '$$*' features)" - features_platforms="$$$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --cname '$$*' platforms)" - features_elements="$$$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --cname '$$*' elements)" - features_flags="$$$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --cname '$$*' flags)" - cname_base="$$$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --cname '$$*' cname_base)" - BUILDER_CNAME='$$*' - BUILDER_CNAME_BASE="$$$$cname_base" - BUILDER_VERSION='$$(call cname_version,$$*)' - BUILDER_ARCH='$$(call cname_arch,$$*)' + features="$$$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --target '$$*' features)" + features_platforms="$$$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --target '$$*' platforms)" + features_elements="$$$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --target '$$*' elements)" + features_flags="$$$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --target '$$*' flags)" + cname="$$$$(./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --target '$$*' cname)" + BUILDER_CNAME="$$$$cname" + BUILDER_FLAVOR="$$$$cname-$$(call extract_arch,$$*)" + BUILDER_VERSIONED_FLAVOR='$$*' + BUILDER_ARTIFACT_BASE='$$*-$(SHORT_COMMIT)' + BUILDER_VERSION='$$(call extract_version,$$*)' + BUILDER_ARCH='$$(call extract_arch,$$*)' BUILDER_TIMESTAMP='$$(TIMESTAMP)' BUILDER_COMMIT='$$(COMMIT)' BUILDER_FEATURES="$$$$features" BUILDER_FEATURES_PLATFORMS="$$$$features_platforms" BUILDER_FEATURES_ELEMENTS="$$$$features_elements" BUILDER_FEATURES_FLAGS="$$$$features_flags" - export BUILDER_CNAME BUILDER_CNAME_BASE BUILDER_VERSION BUILDER_ARCH BUILDER_TIMESTAMP BUILDER_COMMIT BUILDER_FEATURES BUILDER_FEATURES_PLATFORMS BUILDER_FEATURES_ELEMENTS BUILDER_FEATURES_FLAGS + export BUILDER_CNAME BUILDER_FLAVOR BUILDER_VERSIONED_FLAVOR BUILDER_ARTIFACT_BASE BUILDER_VERSION BUILDER_ARCH BUILDER_TIMESTAMP BUILDER_COMMIT BUILDER_FEATURES BUILDER_FEATURES_PLATFORMS BUILDER_FEATURES_ELEMENTS BUILDER_FEATURES_FLAGS "./$$$$script" "$$$$input" '$$@' endef @@ -106,7 +110,7 @@ $(foreach artifact_rule,$(shell ./make_get_artifact_rules),$(eval $(call artifac echo "$$(basename "$$f").log" | tee -a '$@' done -%: .build/$$(shell ./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --default-arch '$$(DEFAULT_ARCH)' --default-version '$$(DEFAULT_VERSION)' --cname '$$*')-$(SHORT_COMMIT).artifacts +%: .build/$$(shell ./parse_features $(PARSE_FEATURES_ARGS) --feature-dir features --default-arch '$$(DEFAULT_ARCH)' --default-version '$$(DEFAULT_VERSION)' --target '$$*')-$(SHORT_COMMIT).artifacts ln -f -s -r '$<' '.build/$*' # prevents match anything rule from applying to Makefile and image/convert scripts diff --git a/builder/image.sbom b/builder/image.sbom index e30a44e..5184390 100755 --- a/builder/image.sbom +++ b/builder/image.sbom @@ -13,6 +13,7 @@ SYFT_CACHE_DIR="$chroot_dir"/syft-cache syft --quiet "$1" --config syft.yaml --o --arg cname "$BUILDER_CNAME" \ --arg arch "$BUILDER_ARCH" \ --arg version "$BUILDER_VERSION" \ + --arg commit "$BUILDER_COMMIT" \ --arg features "$BUILDER_FEATURES" \ --arg builder_timestamp "$BUILDER_TIMESTAMP" \ --arg cpe "" \ @@ -25,6 +26,8 @@ SYFT_CACHE_DIR="$chroot_dir"/syft-cache syft --quiet "$1" --config syft.yaml --o "properties": [ {"name": "cname", "value": $cname}, {"name": "arch", "value": $arch}, + {"name": "version", "value": $version}, + {"name": "commit", "value": $commit}, {"name": "features", "value": $features}, {"name": "build timestamp", "value": $builder_timestamp} ] diff --git a/builder/make_get_image_dependencies b/builder/make_get_image_dependencies index cbb06c0..acc7f8a 100755 --- a/builder/make_get_image_dependencies +++ b/builder/make_get_image_dependencies @@ -8,7 +8,7 @@ exec 1>&2 # get longest chain of extensions, but not extensions starting with a number to prevent parsing minor version as extension extension="$(grep -E -o '(\.[a-z][a-zA-Z0-9\-_]*)*$' <<< "$1")" artifact_base="${1%"-$COMMIT$extension"}" -cname="$(basename "$artifact_base")" +versioned_flavor="$(basename "$artifact_base")" [ "$extension" != ".raw" ] || extension= @@ -26,7 +26,7 @@ if [ -f "convert$extension" ]; then input="$artifact_base-$COMMIT.raw" fi -IFS=',' read -r -a features < <(./parse_features --allow-frankenstein --feature-dir features --cname "$cname" features) +IFS=',' read -r -a features < <(./parse_features --allow-frankenstein --feature-dir features --target "$versioned_flavor" features) for feature in "${features[@]}"; do if [ -s "features/$feature/image$extension" ]; then diff --git a/builder/make_list_build_artifacts b/builder/make_list_build_artifacts index 12f0d1e..8c5cf98 100755 --- a/builder/make_list_build_artifacts +++ b/builder/make_list_build_artifacts @@ -3,23 +3,23 @@ set -euo pipefail shopt -s nullglob -cname="$1" +versioned_flavor="$1" -IFS=',' read -r -a features < <(./parse_features --allow-frankenstein --feature-dir features --cname "$cname" features) +IFS=',' read -r -a features < <(./parse_features --allow-frankenstein --feature-dir features --target "$versioned_flavor" features) -artifacts=(".build/$cname-$COMMIT.tar" ".build/$cname-$COMMIT.release" ".build/$cname-$COMMIT.manifest" ".build/$cname-$COMMIT.sbom" ".build/$cname-$COMMIT.requirements") +artifacts=(".build/$versioned_flavor-$COMMIT.tar" ".build/$versioned_flavor-$COMMIT.release" ".build/$versioned_flavor-$COMMIT.manifest" ".build/$versioned_flavor-$COMMIT.sbom" ".build/$versioned_flavor-$COMMIT.requirements") for feature in "${features[@]}"; do for i in "features/$feature/"{image,convert}.*; do # get target artifact file extension, usually this is the image/convert script extension # except if the script extension is of the form filename.extA~extB in which case the artifact extension is .extA only extension="$(grep -E -o '(\.[a-z][a-zA-Z0-9\-_~]*)*$' <<< "$i")" - artifacts+=(".build/$cname-$COMMIT${extension%~*}") + artifacts+=(".build/$versioned_flavor-$COMMIT${extension%~*}") done done -if [ "${#artifacts[@]}" = 5 ] && [ -n "$(./parse_features --allow-frankenstein --feature-dir "features" --cname "$cname" platforms)" ]; then - artifacts+=(".build/$cname-$COMMIT.raw") +if [ "${#artifacts[@]}" = 5 ] && [ -n "$(./parse_features --allow-frankenstein --feature-dir "features" --target "$versioned_flavor" platforms)" ]; then + artifacts+=(".build/$versioned_flavor-$COMMIT.raw") fi echo "${artifacts[@]}" diff --git a/builder/parse_features b/builder/parse_features index 146f6cd..fa0fb53 100755 --- a/builder/parse_features +++ b/builder/parse_features @@ -15,7 +15,7 @@ def main(): parser.add_argument("--feature-dir", default="features") parser.add_argument("--features", type=lambda arg: set([f for f in arg.split(",") if f])) parser.add_argument("--ignore", type=lambda arg: set([f for f in arg.split(",") if f]), default=set()) - parser.add_argument("--cname") + parser.add_argument("--target") parser.add_argument("--arch") parser.add_argument("--version") parser.add_argument("--default-arch") @@ -24,7 +24,8 @@ def main(): args_type_allowed = [ "cname", - "cname_base", + "flavor", + "versioned_flavor", "features", "platforms", "flags", @@ -34,22 +35,26 @@ def main(): "graph" ] - parser.add_argument("type", nargs="?", choices=args_type_allowed, default="cname") + parser.add_argument("type", nargs="?", choices=args_type_allowed, default="versioned_flavor") args = parser.parse_args() - assert bool(args.features) ^ bool(args.cname), "please provide either `--features` or `--cname` argument" + assert bool(args.features) ^ bool(args.target), "please provide either `--features` or `--target` argument" arch = None version = None - if args.cname: - search = re.search("^([a-z][a-zA-Z0-9_-]*?)(-(amd64|arm64)(-([a-z0-9.]+))?)?$", args.cname) - assert search, f"not a valid cname {args.cname}" + if args.target: + # the target is the raw string a dev passes to the builder, at any level + # of specificity (cname, flavor, or versioned flavor) and not necessarily + # in canonical order; the canonical cname/flavor/versioned flavor are + # derived from it below + search = re.search("^([a-z][a-zA-Z0-9_-]*?)(-(amd64|arm64)(-([a-z0-9.]+))?)?$", args.target) + assert search, f"not a valid target {args.target}" matches = search.groups() - input_cname_base = matches[0] + input_cname = matches[0] arch = matches[2] version = matches[4] - input_features = reverse_cname_base(input_cname_base) + input_features = reverse_cname(input_cname) else: input_features = args.features @@ -59,10 +64,10 @@ def main(): if args.version: version = args.version - if not arch and (args.type == "cname" or args.type == "arch"): + if not arch and (args.type == "flavor" or args.type == "versioned_flavor" or args.type == "arch"): assert args.default_arch, "architecture not specified and no default architecture set" arch = args.default_arch - if not version and (args.type == "cname" or args.type == "version"): + if not version and (args.type == "versioned_flavor" or args.type == "version"): assert args.default_version, "version not specified and no default version set" version = args.default_version @@ -98,13 +103,16 @@ def main(): sorted_features = sort_nodes(graph) minimal_feature_set = get_minimal_feature_set(graph) sorted_minimal_features = sort_set(minimal_feature_set, sorted_features) - cname_base = get_cname_base(sorted_minimal_features) - cname = f"{cname_base}-{arch}-{version}" + cname = get_cname(sorted_minimal_features) + flavor = f"{cname}-{arch}" + versioned_flavor = f"{cname}-{arch}-{version}" - if args.type == "cname_base": - print(cname_base) - elif args.type == "cname": + if args.type == "cname": print(cname) + elif args.type == "flavor": + print(flavor) + elif args.type == "versioned_flavor": + print(versioned_flavor) elif args.type == "features": print(",".join(features)) elif args.type == "platforms": @@ -114,9 +122,9 @@ def main(): elif args.type == "flags": print(",".join(features_by_type["flag"])) elif args.type == "graph": - print(graph_as_mermaid_markup(cname_base, graph)) + print(graph_as_mermaid_markup(cname, graph)) -def graph_as_mermaid_markup(cname_base, graph): +def graph_as_mermaid_markup(cname, graph): """ Generates a mermaid.js representation of the graph. This is helpful to identify dependencies between features. @@ -124,7 +132,7 @@ def graph_as_mermaid_markup(cname_base, graph): Syntax docs: https://mermaid.js.org/syntax/flowchart.html?id=flowcharts-basic-syntax """ - markup = f"---\ntitle: Dependency Graph for Feature {cname_base}\n---\ngraph TD;\n" + markup = f"---\ntitle: Dependency Graph for Feature {cname}\n---\ngraph TD;\n" for u,v in networkx.edges(graph): markup += f" {u}-->{v};\n" return markup @@ -139,11 +147,11 @@ def popen_read(command): f.close() return output -def reverse_cname_base(cname): +def reverse_cname(cname): cname = cname.replace("_", "-_") return set(cname.split("-")) -def get_cname_base(sorted_features): +def get_cname(sorted_features): return reduce(lambda a, b : a + ("-" if not b.startswith("_") else "") + b, sorted_features) def get_minimal_feature_set(graph): diff --git a/docs/reference/builder.md b/docs/reference/builder.md index 864c0cb..c96a1f3 100644 --- a/docs/reference/builder.md +++ b/docs/reference/builder.md @@ -44,14 +44,9 @@ builder container. This means standard `make` flags such as `-j` are valid here. | `--privileged` | _(none)_ | Off | Runs the builder container with `--privileged` and passes `--second-stage` to the container entrypoint. Required for two-stage builds that need elevated privileges inside the container. | | `--kms` | _(none)_ | Off | Forwards AWS credential environment variables (`AWS_DEFAULT_REGION`, `AWS_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`) into the build. Required when Secure Boot key operations during the build use AWS Key Management Service. | | `--allow-frankenstein` | _(none)_ | Off | Disables the [single-platform enforcement](/reference/adr/0020-enforce-single-platform-by-default-in-builder) by passing `ALLOW_FRANKENSTEIN=1` to the build. Allows composing a flavor from multiple platform features. See [ADR 0020](/reference/adr/0020-enforce-single-platform-by-default-in-builder) for the rationale. | -| `--resolve-cname` | _(none)_ | Off | Resolves the given flavor argument to the artifact base name (`{cname}-{arch}-{version}-{short_commit}`), prints it to stdout, and exits. Requires exactly one flavor argument. Useful for generating reproducible artifact names in scripts. | | `--print-container-image` | _(none)_ | Off | Prints the pinned builder container image reference to stdout and exits immediately. Useful for scripts that need to pull or inspect the builder image independently of running a build. | | `--apparmor-profile` | `` | Auto-detected | Applies the named AppArmor profile to the builder container, replacing the default `apparmor=unconfined`. If not set and Docker is used on a host with `kernel.apparmor_restrict_unprivileged_userns = 1`, the script detects the restriction and offers to create a `builder` profile at `/etc/apparmor.d/builder` automatically. | -:::warning -The `--resolve-cname` flag will be renamed `--resolve-artifact-basename` in [builder#156](https://github.com/gardenlinux/builder/issues/156). -::: - ### `make` flags Any argument not consumed by the option parser above is forwarded to `make` inside the builder diff --git a/docs/reference/features.md b/docs/reference/features.md index 519fca2..6f26045 100644 --- a/docs/reference/features.md +++ b/docs/reference/features.md @@ -28,9 +28,7 @@ After resolving the feature graph, the builder writes the following keys into `/ | `GARDENLINUX_FEATURES_ELEMENTS` | Comma-separated list of all features of type `element` | | `GARDENLINUX_FEATURES_FLAGS` | Comma-separated list of all features of type `flag` | -:::warning -`GARDENLINUX_CNAME` currently contains the versioned flavor (`{cname}-{arch}-{version}`) because `BUILDER_CNAME` in the builder is set to the full make target. Once [builder#156](https://github.com/gardenlinux/builder/issues/156) and [gardenlinux#5004](https://github.com/gardenlinux/gardenlinux/issues/5004) are resolved, `BUILDER_CNAME` will be corrected to carry only the feature encoding (e.g. `aws-gardener_prod`), and `GARDENLINUX_CNAME` will follow. -::: +`GARDENLINUX_CNAME` contains the cname as defined in [ADR 0035](/reference/adr/0035-cname-flavor-artifact-naming) — the feature encoding only, without architecture, version, or commit. It is populated from the builder's `BUILDER_CNAME` variable. `GARDENLINUX_PLATFORM` is always a single token and is the value to use for all platform-routing decisions (publishing, testing, image naming). `GARDENLINUX_FEATURES_PLATFORMS` is informational only and must not be used for routing. @@ -106,6 +104,23 @@ The order of execution is as follows: When building with multiple features, the execution steps of each feature are interleaved. For example, the `exec.config` step will run for all features before any features' `exec.late` step runs. +The builder exports the following variables to feature scripts (naming per [ADR 0035](/reference/adr/0035-cname-flavor-artifact-naming)): + +| Variable | Value | +| ---------------------------- | ---------------------------------------------------------------- | +| `BUILDER_CNAME` | cname — feature encoding only (e.g. `aws-gardener_prod`) | +| `BUILDER_FLAVOR` | flavor — `{cname}-{arch}` | +| `BUILDER_VERSIONED_FLAVOR` | versioned flavor — `{cname}-{arch}-{version}` | +| `BUILDER_ARTIFACT_BASE` | artifact base name — `{cname}-{arch}-{version}-{short_commit}` | +| `BUILDER_ARCH` | target architecture | +| `BUILDER_VERSION` | version | +| `BUILDER_COMMIT` | full source commit hash | +| `BUILDER_TIMESTAMP` | build timestamp (for reproducible builds) | +| `BUILDER_FEATURES` | comma-separated resolved feature set | +| `BUILDER_FEATURES_PLATFORMS` | comma-separated features of type `platform` | +| `BUILDER_FEATURES_ELEMENTS` | comma-separated features of type `element` | +| `BUILDER_FEATURES_FLAGS` | comma-separated features of type `flag` | + ## `fstab`, `fstab.mod` The partition layout of the build image can be defined in an fstab like format.