Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions .github/workflows/lockfile-drift-detect.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
mv r.tmp repos.txt
fi

scanned=0; withlock=0; drifted=0
scanned=0; withlock=0; drifted=0; errors=0
while read -r r; do
scanned=$((scanned+1))
# Cheap probe first: skip repos with no lockfile (that is failure
Expand All @@ -90,21 +90,35 @@ jobs:
"https://x-access-token:${GH_TOKEN}@github.com/hyperpolymath/$r.git" _w 2>/dev/null; then
continue
fi
if ! bash scripts/check-lockfile-drift.sh _w >> drift-report.tsv 2>/dev/null; then
# Exit-code honesty (issue #708): 1 = drift found, 2 = usage/env
# error. The old `if !` folded both into 'drifted', so a broken
# clone counted as a drifted repo. The slug arg gives column 1 a
# real identity; without it every row said `_w`.
rc=0
bash scripts/check-lockfile-drift.sh _w "$r" >> drift-report.tsv 2>> drift-errors.log || rc=$?
if [ "$rc" -eq 1 ]; then
drifted=$((drifted+1))
elif [ "$rc" -ne 0 ]; then
errors=$((errors+1))
echo "::warning::$r: drift check errored (rc=$rc) — see drift-errors.log"
fi
rm -rf _w
done < repos.txt

rows=$(( $(wc -l < drift-report.tsv) - 1 ))
# Count data rows only: lines bearing a TAB, minus the header.
# (wc -l − 1 counted banner lines as drift entries when banners
# still leaked into stdout — 67 of 418 'entries' in run 2026-09-15
# were `[drift] clean` lines, issue #708.)
rows=$(( $(grep -c $'\t' drift-report.tsv || true) - 1 ))
{
echo "total=$TOTAL"
echo "scanned=$scanned"
echo "withlock=$withlock"
echo "drifted=$drifted"
echo "errors=$errors"
echo "rows=$rows"
} >> "$GITHUB_OUTPUT"
echo "scanned=$scanned withlock=$withlock drifted=$drifted rows=$rows"
echo "scanned=$scanned withlock=$withlock drifted=$drifted errors=$errors rows=$rows"

- name: Upload report
if: always()
Expand All @@ -126,6 +140,7 @@ jobs:
echo "| scanned | ${{ steps.sweep.outputs.scanned }} |"
echo "| carrying a lockfile | ${{ steps.sweep.outputs.withlock }} |"
echo "| **with drift** | **${{ steps.sweep.outputs.drifted }}** |"
echo "| check errors (rc≠0,1) | ${{ steps.sweep.outputs.errors }} |"
echo "| drifted entries | ${{ steps.sweep.outputs.rows }} |"
echo
echo '```'
Expand Down Expand Up @@ -163,6 +178,7 @@ jobs:
echo "| scanned | ${{ steps.sweep.outputs.scanned }} |"
echo "| carrying a lockfile | ${{ steps.sweep.outputs.withlock }} |"
echo "| **with drift** | **${{ steps.sweep.outputs.drifted }}** |"
echo "| check errors (rc≠0,1) | ${{ steps.sweep.outputs.errors }} |"
echo "| drifted entries | ${{ steps.sweep.outputs.rows }} |"
} > issue-body.md
body="$(cat issue-body.md)"
Expand Down
16 changes: 12 additions & 4 deletions scripts/check-lockfile-drift.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,21 @@ set -eo pipefail
# not "this is why CI is down". The strong claim is the converse and it holds:
# every workflow that WAS dead had a drifted entry.
#
# Usage: check-lockfile-drift.sh [REPO_DIR] (default: .)
# Output: TSV — repo <TAB> workflow <TAB> requested <TAB> locked
# Usage: check-lockfile-drift.sh [REPO_DIR] [REPO_SLUG]
# REPO_DIR default: . — the checkout to inspect
# REPO_SLUG default: basename(REPO_DIR) — the identity written to
# column 1. The caller MUST pass this when REPO_DIR is a
# throwaway clone (e.g. `_w`): otherwise every row says
# `_w` and the report is untraceable (issue #708).
# Output: TSV on stdout — repo <TAB> workflow <TAB> requested <TAB> locked
# (all banners/notices go to stderr — stdout is data ONLY, so the
# file can be appended straight into the report)
# Exit: 0 = no drift (or no lockfile — not this script's business)
# 1 = drift found
# 2 = usage / environment error

REPO_DIR="${1:-.}"
REPO_SLUG="${2:-$(basename "$REPO_DIR")}"
LOCK="$REPO_DIR/.github/workflows/actions.lock"
WFDIR="$REPO_DIR/.github/workflows"

Expand Down Expand Up @@ -111,7 +119,7 @@ for wf in "$WFDIR"/*.yml "$WFDIR"/*.yaml; do
[ "$resolved" = "$ref" ] && continue # same commit, different notation
fi

printf '%s\t%s\t%s\t%s\n' "$(basename "$REPO_DIR")" "$base" "$want" "$have"
printf '%s\t%s\t%s\t%s\n' "$REPO_SLUG" "$base" "$want" "$have"
drift=$((drift + 1))
done < /tmp/_drift_want.$$

Expand All @@ -124,5 +132,5 @@ if [ "$drift" -gt 0 ]; then
exit 1
fi

echo "[drift] clean — $checked workflow(s) checked in $REPO_DIR"
echo "[drift] clean — $checked workflow(s) checked in $REPO_DIR" >&2
exit 0
Loading