From ac3f4243662913f7482fe40731845bd0be8a0d6e Mon Sep 17 00:00:00 2001 From: Benjamin Leggett Date: Wed, 4 Mar 2026 18:56:15 -0500 Subject: [PATCH 1/2] Do not allow publishing kernel builds that break the semver<->tag contract. --- hack/build/generate-matrix.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/hack/build/generate-matrix.py b/hack/build/generate-matrix.py index edefe0e..254cdfe 100644 --- a/hack/build/generate-matrix.py +++ b/hack/build/generate-matrix.py @@ -29,10 +29,7 @@ def construct_all_matrix(): def construct_manual_matrix(exact_versions): - reflective = {} - for version in exact_versions: - reflective[version] = version - return matrix.generate_matrix(reflective) + return matrix.generate_matrix(matrix.build_release_tags(exact_versions)) DEFAULT_BUILD_SPEC = "new" From f5706dbeb17f38d903984572e56acf6f8a96e1da Mon Sep 17 00:00:00 2001 From: Benjamin Leggett Date: Wed, 4 Mar 2026 19:02:37 -0500 Subject: [PATCH 2/2] Append branch name to OCI tag names, if built off of non-`main` branch --- hack/build/generate-docker-script.py | 26 ++++++++++++++++++++------ hack/build/generate-matrix.py | 8 +++++++- hack/build/util.py | 9 +++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/hack/build/generate-docker-script.py b/hack/build/generate-docker-script.py index 0fd0f94..352dc59 100644 --- a/hack/build/generate-docker-script.py +++ b/hack/build/generate-docker-script.py @@ -7,7 +7,7 @@ from packaging.version import parse, Version from matrix import CONFIG -from util import format_image_name, maybe, smart_script_split, parse_text_bool +from util import format_image_name, maybe, smart_script_split, parse_text_bool, get_branch_tag_suffix def is_publish_enabled() -> bool: @@ -53,16 +53,25 @@ def docker_build( mark_format: Optional[str], firmware_url: str, firmware_sig_url: str, + tag_suffix: Optional[str] = None, ) -> list[str]: lines = [] version = dockerify_version(version) + + # tag_version is the version string used for OCI tags; version is the + # actual kernel version passed as a build arg and recorded in annotations. + # They differ when building from a non-main branch to avoid tag collisions. + # Tags in the list are already branch-suffixed (applied during matrix generation). + tag_version = "%s-%s" % (version, tag_suffix) if tag_suffix else version + oci_tags = list(tags) + root = format_image_name( image_name_format=CONFIG["imageNameFormat"], flavor=flavor, version_info=version_info, name=name, - tag=version, + tag=tag_version, ) image_build_command = [ @@ -77,7 +86,7 @@ def docker_build( "--target", quoted(target), "--iidfile", - quoted("image-id-%s-%s-%s" % (version, flavor, target)), + quoted("image-id-%s-%s-%s" % (tag_version, flavor, target)), ] for build_platform in docker_platforms(architectures): @@ -117,8 +126,8 @@ def docker_build( all_tags = [root] additional_tags = [] - for tag in tags: - if tag == version: + for tag in oci_tags: + if tag == tag_version: continue additional_tags.append( format_image_name( @@ -149,7 +158,7 @@ def docker_build( "sign", "--yes", quoted( - '%s@$(cat "image-id-%s-%s-%s")' % (tag, version, flavor, target) + '%s@$(cat "image-id-%s-%s-%s")' % (tag, tag_version, flavor, target) ), ] lines += [""] @@ -176,6 +185,7 @@ def generate_builds( kernel_architectures: list[str], firmware_url: str, firmware_sig_url: str, + tag_suffix: Optional[str] = None, ) -> list[str]: lines = [] kernel_version_info = parse(kernel_version) @@ -204,6 +214,7 @@ def generate_builds( architectures=kernel_architectures, firmware_url=firmware_url, firmware_sig_url=firmware_sig_url, + tag_suffix=tag_suffix, ) lines += image_lines return lines @@ -225,11 +236,13 @@ def generate_build_from_env() -> list[str]: kernel_architectures=root_kernel_architectures, firmware_url=root_firmware_url, firmware_sig_url=root_firmware_sig_url, + tag_suffix=get_branch_tag_suffix(), ) def generate_builds_from_matrix(matrix) -> list[str]: lines = [] + tag_suffix = get_branch_tag_suffix() builds = matrix["builds"] # type: list[dict[str, any]] for build in builds: build_version = build["version"] @@ -247,6 +260,7 @@ def generate_builds_from_matrix(matrix) -> list[str]: kernel_architectures=build_architectures, firmware_url=firmware_url, firmware_sig_url=firmware_sig_url, + tag_suffix=tag_suffix, ) return lines diff --git a/hack/build/generate-matrix.py b/hack/build/generate-matrix.py index 254cdfe..dca830f 100644 --- a/hack/build/generate-matrix.py +++ b/hack/build/generate-matrix.py @@ -2,7 +2,7 @@ import sys import matrix -from util import parse_text_constraint, maybe +from util import parse_text_constraint, maybe, get_branch_tag_suffix from packaging.version import Version, parse @@ -107,6 +107,12 @@ def construct_manual_matrix(exact_versions): matrix.validate_produce_conflicts(final_matrix) matrix.fill_runners(final_matrix) +branch_suffix = get_branch_tag_suffix() +if branch_suffix: + for build in final_matrix: + build["tags"] = ["%s-%s" % (t, branch_suffix) for t in build["tags"]] + build["produces"] = ["%s-%s" % (p, branch_suffix) for p in build["produces"]] + print("generated %s builds" % len(final_matrix)) matrix.summarize_matrix(final_matrix) diff --git a/hack/build/util.py b/hack/build/util.py index 17d2dcc..d710f9c 100644 --- a/hack/build/util.py +++ b/hack/build/util.py @@ -1,9 +1,18 @@ +import os +import re from typing import Optional from packaging.version import Version import subprocess +def get_branch_tag_suffix() -> Optional[str]: + ref_name = os.getenv("GITHUB_REF_NAME", "") + if not ref_name or ref_name == "main": + return None + return re.sub(r'[^a-zA-Z0-9._-]', '_', ref_name) + + def format_image_name( image_name_format: str, flavor: str, version_info: Version, name: str, tag: str ) -> str: