From 32b95c02b8d56053cd49f23fbdd65886a84656d4 Mon Sep 17 00:00:00 2001 From: ZDDC Date: Thu, 7 May 2026 12:08:01 -0500 Subject: [PATCH] build(channels): include source SHA in beta on-page label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beta cuts now stamp the on-page label as "v-beta · · g" so a tester can confirm at a glance which source commit they're running against. Previously the SHA was deliberately omitted to avoid an embedded-commit recursion: a build that auto-commits the regenerated embedded artifacts (build:971-995) advances HEAD by one, and a SHA derived from HEAD would shift on every cut, causing the next cut to commit again ad infinitum. Fix: embed the *source* SHA, not HEAD. The new _source_commit_short_sha helper walks backwards from HEAD past any "chore(embedded): cut" or "release: vX.Y.Z lockstep" auto-commits and returns the short SHA of the underlying source state. That SHA is invariant across the auto-commit step, so a re-run on the same source state produces the same label and no spurious commit. Plain dev builds and stable cuts are unchanged. Plain builds already included the SHA via _sha + -dirty marker; stable cuts intentionally carry only the bare semver in the label. Co-Authored-By: Claude Opus 4.7 (1M context) --- shared/build-lib.sh | 53 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/shared/build-lib.sh b/shared/build-lib.sh index 7710e56..8f13165 100755 --- a/shared/build-lib.sh +++ b/shared/build-lib.sh @@ -131,6 +131,37 @@ _validate_semver() { case "$_v3" in '' | *[!0-9]*) _bad ;; esac } +# Walk backwards from HEAD until a non-auto-commit is found, return its +# short SHA. Auto-commits are recognised by their canonical commit- +# message prefixes: +# +# - "chore(embedded): cut v-beta" (beta auto-commit, build:993) +# - "release: v lockstep" (stable auto-commit, build:986) +# +# Used by compute_build_label to embed a stable source-SHA into beta +# labels without triggering the embedded-commit recursion: HEAD shifts +# when embedded bytes change, but the source SHA returned here stays +# the same as long as the underlying source hasn't moved. +# +# Falls back to plain `HEAD` short SHA when the walk doesn't find a +# non-auto-commit in the first 32 commits (defensive cap). +_source_commit_short_sha() { + _i=0 + _ref="HEAD" + while [ "$_i" -lt 32 ]; do + _msg=$(git -C "$root_dir" log -1 --format=%s "$_ref" 2>/dev/null || echo "") + case "$_msg" in + "chore(embedded): cut v"* | "release: v"*" lockstep") + _ref="${_ref}~1" + _i=$((_i + 1)) + continue + ;; + esac + break + done + git -C "$root_dir" rev-parse --short=7 "$_ref" 2>/dev/null || echo "unknown" +} + # Compute build label and channel. Reads positional args: # compute_build_label [--release []] # Sets global variables: @@ -187,17 +218,17 @@ compute_build_label() { alpha | beta) channel="$_arg" _date=$(date -u +"%Y-%m-%d") - # No SHA in the channel-cut label — the build's auto-commit - # block (build:971-995) advances HEAD when committing the - # regenerated embedded artifacts, which would shift the SHA - # and trigger the next run to commit again ad infinitum. - # Cosmetic SHA traceability is now via the chart's - # appVersion (full SHA, written by notify-chart-bump.sh on - # push) and the running binary's `--version` output — - # both of which are accurate where the embedded label - # SHA was not (it always pointed at HEAD-before-commit, - # off by one). - build_label="v${_next_stable}-${channel} · ${_date}" + # Resolve the *source* SHA — the most recent commit that is + # not itself an embedded-files auto-commit. This stays stable + # across the build's auto-commit step (build:971-995) which + # advances HEAD by one when embedded bytes change. Using + # HEAD directly here would create an infinite loop: each cut + # would update the embedded label with the new chore-commit + # SHA, which would in turn require another chore commit. + # The source SHA is invariant across embedded auto-commits + # so the second cut on the same source state is a no-op. + _src_sha=$(_source_commit_short_sha) + build_label="v${_next_stable}-${channel} · ${_date} · g${_src_sha}" _emit_build_label_sidecar "$_tool" return 0 ;;