From afdcc1412158c86880d0f59914207d01af54936e Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Fri, 2 Oct 2026 02:22:00 +0100 Subject: [PATCH] fix(relock): keep a tag key a workflow still writes (WIP, untested) Re-keying actions/checkout@v7.0.1 to its SHA because ONE workflow pins the SHA inline strands the 17 workflows that still write the tag: prune-stale empties their lists and --verify-local reports not-pinned (metadatastician/_pathroot, 2026-10-02). Skip the re-key when the tag is still written on a live uses: line. UNTESTED: the end-to-end run was cut off by an exhausted REST quota. Needs a known-answer test and a rerun on _pathroot before a PR is opened. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016L7GFo3yGQ2vK9YgKL2wsP --- scripts/relock-sha-keys.sh | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/scripts/relock-sha-keys.sh b/scripts/relock-sha-keys.sh index 8eab212d4..ab36fd528 100755 --- a/scripts/relock-sha-keys.sh +++ b/scripts/relock-sha-keys.sh @@ -34,7 +34,8 @@ LOCK="$WF_DIR/actions.lock" # Lockfile entries key the repo root, while an inline ref may carry a # subpath (github/codeql-action/init@sha), so index by owner/repo only. INLINE="$(mktemp)" -trap 'rm -f "$INLINE" "$MAP" "$TMPLOCK"' EXIT +TAGGED="$(mktemp)" +trap 'rm -f "$INLINE" "$TAGGED" "$MAP" "$TMPLOCK"' EXIT find "$WF_DIR" -maxdepth 1 -type f \( -name '*.yml' -o -name '*.yaml' \) -print0 \ | xargs -0 -r awk ' match($0, /uses:[ \t]*[A-Za-z0-9_.-]+\/[A-Za-z0-9_.\/-]+@[0-9a-f]{40}/) { @@ -46,11 +47,32 @@ find "$WF_DIR" -maxdepth 1 -type f \( -name '*.yml' -o -name '*.yaml' \) -print0 print tolower(seg[1] "/" seg[2]) "\t" sha }' | sort -u > "$INLINE" +# 1b. Collect refs still written in TAG form on a live (uncommented) uses: line, +# as "owner/reporef". A tag-keyed entry whose tag is still in use must +# keep its key: re-keying it to the SHA strands every workflow that writes +# the tag (prune-stale then empties their lists and --verify-local reports +# not-pinned). Measured on metadatastician/_pathroot, 2026-10-02: 17 +# workflows use actions/checkout@v7.0.1 and one pins its SHA inline. +# complete-job-refs and close-lock supply the SHA-form entry for the latter. +find "$WF_DIR" -maxdepth 1 -type f \( -name '*.yml' -o -name '*.yaml' \) -print0 \ + | xargs -0 -r awk ' + /^[ \t]*#/ { next } + match($0, /uses:[ \t]*[A-Za-z0-9_.-]+\/[A-Za-z0-9_.\/-]+@[^ \t#'"'"'"]+/) { + s = substr($0, RSTART, RLENGTH) + sub(/^uses:[ \t]*/, "", s) + n = index(s, "@") + path = substr(s, 1, n - 1); ref = substr(s, n + 1) + if (ref ~ /^[0-9a-f]{40}$/) next + split(path, seg, "/") + print tolower(seg[1] "/" seg[2]) "\t" ref + }' | sort -u > "$TAGGED" + # 2. Walk the lockfile, building tag-key -> sha-key replacements. MAP="$(mktemp)" -awk -v inline="$INLINE" ' +awk -v inline="$INLINE" -v tagged="$TAGGED" ' BEGIN { while ((getline line < inline) > 0) { split(line, f, "\t"); seen[f[1] SUBSEP f[2]] = 1 } + while ((getline line < tagged) > 0) { split(line, f, "\t"); intag[f[1] SUBSEP f[2]] = 1 } } # A dependency entry: '\''action@ref'\'': match($0, /^ '\''[^'\''@]+@[^'\'']+'\'':$/) { @@ -60,6 +82,8 @@ awk -v inline="$INLINE" ' action = substr(key, 1, n - 1); ref = substr(key, n + 1) # already SHA-keyed: nothing to do if (ref ~ /^[0-9a-f]{40}$/) { cur = ""; next } + # still written as this tag somewhere: keep the tag key (see 1b) + if ((tolower(action) SUBSEP ref) in intag) { cur = ""; next } cur = key; curaction = action; next } # its body carries commit: '\''sha1-'\''