From 44d6ba9c8df6a4d26b8729c7b148665cf3c3b4de Mon Sep 17 00:00:00 2001 From: repo-worker Date: Thu, 9 Jul 2026 19:47:31 +0300 Subject: [PATCH] Fix image_name inference bug + add tag normalization setting (oleks/ci-scripts#21, #22) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit render_thin_quartet.py's kind=matrix rendering derived image_name from the manifest's repo field, which silently diverges from the actually-published image for xonsh-image (repo "xonsh-image" vs. live image "oleks/xonsh", confirmed via the package registry). image_name is now a required, explicit manifest field with no inference; xonsh-image and csi-s3 manifests updated with their verified values. entrypoint.sh's buildx-build/buildx-manifest flows always used the raw CI_COMMIT_TAG, with no way to reproduce ci/local.sh's leading-"v" / trailing-"-N" tag stripping. Added resolve_version() with two additive, default-preserving settings: `version` (explicit override, wins over CI_COMMIT_TAG when set — a no-op today since nothing sets it) and `tag_strip_v` (opt-in normalization). Default behavior is unchanged: raw CI_COMMIT_TAG, matching this plugin's own v1.0.x self-build tags and every other current consumer. xonsh-image's manifest now opts into tag_strip_v to prove the fix (verified: resolve_version("v0.22.7") -> "0.22.7", rendered tag "0.22.7-amd64" matches the live-consumed scheme) but is NOT wired into its actual .woodpecker/ dir yet — migration is a separate step once both fixes are released. oleks/ci-scripts#20 --- entrypoint.sh | 40 ++++++++++++++++++++++++++++++-- generator/render_thin_quartet.py | 35 +++++++++++++++++++++++++--- manifests/csi-s3.yaml | 9 +++++++ manifests/xonsh-image.yaml | 11 +++++++++ 4 files changed, 90 insertions(+), 5 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 7292f70..c22ed69 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -29,6 +29,13 @@ # manifest step) using the SAME plugin image. Split into `buildx-build` / # `buildx-manifest` instead; wiki updated to match. # +# Version resolution for buildx-build/buildx-manifest (oleks/ci-scripts#21, +# see resolve_version() below): defaults to the raw CI_COMMIT_TAG (or an +# explicit `version:` setting, or "latest") — unchanged from before. A repo +# whose own build script normalizes tags (strips a leading "v" and a +# trailing "-") can opt in with `tag_strip_v: "true"` to +# reproduce that exactly; default is off. +# # See wiki Spec/Modern-CI-Target and Spec/Fleet Publish Plugin System. set -euo pipefail @@ -67,6 +74,33 @@ render_tag() { echo "$scheme" } +resolve_version() { + # resolve_version — the string substituted for {version} in tag_scheme, + # used by both buildx_build_flow and buildx_manifest_flow so the two + # stay in lockstep (oleks/ci-scripts#21). + # + # Precedence: an explicit `version:` setting (PLUGIN_VERSION) wins over + # the tag the pipeline triggered on (CI_COMMIT_TAG), else "latest". + # Nothing currently sets PLUGIN_VERSION (audited across every repo using + # this plugin), so this is a no-op precedence change for every existing + # consumer today. + # + # `tag_strip_v: "true"` (PLUGIN_TAG_STRIP_V) additionally strips a + # leading "v" and a trailing "-" suffix, e.g. "v0.22.7-4" + # -> "0.22.7" — the normalization xonsh-image's (and csi-s3's) ci/local.sh + # already does before tagging. Default is "false": preserves the raw + # tag verbatim, which is what ci-scripts' own self-build (ci/local.sh, + # this plugin's own v1.0.x tags) and every other current consumer of + # this plugin already expect. Opt in per-repo via `tag_strip_v: "true"` + # in `settings:` — do not flip the default. + local version="${PLUGIN_VERSION:-${CI_COMMIT_TAG:-latest}}" + if [ "${PLUGIN_TAG_STRIP_V:-false}" = "true" ]; then + version="${version#v}" + version="${version%-[0-9]*}" + fi + printf '%s' "$version" +} + # --- attic watch-store lifecycle: explicit non-masking shutdown, never `|| true` --- ATTIC_PID="" @@ -130,7 +164,8 @@ buildx_build_flow() { if [ -n "${PLUGIN_TAG_SCHEME:-}" ]; then tag_scheme="${PLUGIN_TAG_SCHEME}" fi - local version="${CI_COMMIT_TAG:-${PLUGIN_VERSION:-latest}}" + local version + version=$(resolve_version) local tag tag=$(render_tag "$tag_scheme" "$version" "$arch") local context="${PLUGIN_CONTEXT:-.}" @@ -151,7 +186,8 @@ buildx_manifest_flow() { if [ -n "${PLUGIN_TAG_SCHEME:-}" ]; then tag_scheme="${PLUGIN_TAG_SCHEME}" fi - local version="${CI_COMMIT_TAG:-${PLUGIN_VERSION:-latest}}" + local version + version=$(resolve_version) local dest_tags="${PLUGIN_DEST_TAGS:-${version},latest}" IFS=',' read -ra platforms <<<"$PLUGIN_PLATFORMS" diff --git a/generator/render_thin_quartet.py b/generator/render_thin_quartet.py index 819c313..6135449 100644 --- a/generator/render_thin_quartet.py +++ b/generator/render_thin_quartet.py @@ -31,6 +31,13 @@ than the fleet family's migration (which just moves inline shell into `run:`) — needs explicit confirmation that ci/local.sh's Dockerfile build is the ONLY thing it does before this ships (see report). +`kind: matrix` manifests must set `image_name:` explicitly, verified against +the live Gitea package registry (oleks/ci-scripts#22). It is NEVER inferred +from the manifest's `repo:`/dir field — `xonsh-image`'s repo field and its +actually-published image (`oleks/xonsh`, confirmed live) genuinely differ; +inferring one from the other silently pushes a migrated pipeline to a +different, wrong (and possibly empty) image path. + For the-eye/emdash (single) and flake-hub/woodpecker-peek (split), the existing pipelines already invoke a repo-owned script (`ci/local.sh`, `nix run .#publish-*`) as their entire build logic — same shape as the fleet @@ -92,6 +99,13 @@ def render_build(manifest: dict, arch: str, image_name: str) -> str: + lines + "\n" ) + # oleks/ci-scripts#21: opt-in only — reproduces a repo's own ci/local.sh + # tag normalization (strip leading "v" + trailing "-N"). Default off + # (entrypoint.sh's resolve_version() default matches today's raw-tag + # behavior), set per-manifest via `tag_strip_v: true`. + tag_strip_v_line = ( + ' tag_strip_v: "true"\n' if manifest.get("tag_strip_v") else "" + ) return f"""{GENERATED_HEADER}labels: arch: {arch} @@ -110,11 +124,14 @@ steps: flow: buildx-build image_name: "{image_name}" tag_scheme: "{{version}}-{{arch}}" -{backend_options_block}""" +{tag_strip_v_line}{backend_options_block}""" def render_manifest(manifest: dict, arches: list, image_name: str) -> str: platforms = ",".join(arches) + tag_strip_v_line = ( + ' tag_strip_v: "true"\n' if manifest.get("tag_strip_v") else "" + ) return f"""{GENERATED_HEADER}when: - event: tag ref: "refs/tags/v*" @@ -140,7 +157,7 @@ steps: image_name: "{image_name}" platforms: "{platforms}" tag_scheme: "{{version}}-{{arch}}" -""" +{tag_strip_v_line}""" def _comment_block(text: str, indent: str) -> str: @@ -289,7 +306,19 @@ def main(): out_dir = args.out / repo if kind == "matrix": - image_name = f"git.oleks.space/oleks/{repo}" + # oleks/ci-scripts#22: image_name must be explicit in the + # manifest, never inferred from the repo/dir name — the two + # silently diverge for xonsh-image (repo field "xonsh-image", + # actually-published image "oleks/xonsh") and inference would + # have pushed a migrated pipeline to an empty, wrong image path. + image_name = manifest.get("image_name") + if not image_name: + raise SystemExit( + f"manifest for {repo!r} (kind=matrix) is missing required " + "'image_name' field (oleks/ci-scripts#22: must be explicit, " + "verified against the live package registry — do not infer " + "it from the repo/dir name)" + ) arches = manifest["arches"] out_dir.mkdir(parents=True, exist_ok=True) for arch in arches: diff --git a/manifests/csi-s3.yaml b/manifests/csi-s3.yaml index 0ec90a2..7986fc5 100644 --- a/manifests/csi-s3.yaml +++ b/manifests/csi-s3.yaml @@ -3,6 +3,15 @@ kind: matrix explicit_clone: true image: git.oleks.space/oleks/nix-ci:latest script: ci/local.sh +# oleks/ci-scripts#22: matches ci/local.sh's IMAGE_REPO default +# ("csi-s3-driver"), NOT the `repo:` field above. Unlike xonsh-image there is +# no live package under this name yet to cross-check (csi-s3's --publish path +# has never run in CI: no pipeline history, no registry package) — this is +# the intended target per the script, not a confirmed-live value. csi-s3 +# remains EXCLUDED from the #17 migration regardless (oleks/ci-scripts#20: +# too bespoke — build-args, dual per-arch tags, skip-if-published, dropped +# clone/timeout overrides); this field is added for manifest correctness only. +image_name: git.oleks.space/oleks/csi-s3-driver var_name: TARGET_ARCH arches: [amd64, arm64] commented_arches: diff --git a/manifests/xonsh-image.yaml b/manifests/xonsh-image.yaml index a86f4d9..8c75753 100644 --- a/manifests/xonsh-image.yaml +++ b/manifests/xonsh-image.yaml @@ -4,3 +4,14 @@ image: git.oleks.space/oleks/nix-ci script: ci/local.sh arches: [amd64, arm64] buildkit_prefix: buildkit +# oleks/ci-scripts#22: the PUBLISHED image is "oleks/xonsh", not +# "oleks/xonsh-image" — ci/local.sh's IMAGE_REPO default is "xonsh", and the +# live Gitea package registry confirms it (tags 0.22.7, 0.22.7-amd64, +# 0.22.7-arm64, latest all under package "xonsh"). Do not derive this from +# the `repo:` field above. +image_name: git.oleks.space/oleks/xonsh +# oleks/ci-scripts#21: ci/local.sh strips a leading "v" (and a trailing +# "-N" build suffix) from CI_COMMIT_TAG before tagging — live published tags +# are "0.22.7"/"0.22.7-", not "v0.22.7-". Reproduces that exactly +# via entrypoint.sh's opt-in resolve_version() normalization. +tag_strip_v: true