Skip to content

Commit f7f7352

Browse files
authored
Add base-ref-aware stale lock guard for workflow markdown edits (#44912)
1 parent f5f2211 commit f7f7352

3 files changed

Lines changed: 86 additions & 11 deletions

File tree

Makefile

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,19 @@ lint-lock: build
782782
# does a full recompile) by catching the obvious staleness case early.
783783
.PHONY: check-stale-lock-files
784784
check-stale-lock-files:
785-
@bash scripts/check-stale-lock-files.sh
785+
@base_ref="$${CHECK_STALE_LOCK_BASE_REF:-}"; \
786+
if [ -z "$$base_ref" ] && [ -n "$${GITHUB_BASE_REF:-}" ]; then \
787+
if git rev-parse --verify "origin/$${GITHUB_BASE_REF}^{commit}" >/dev/null 2>&1; then \
788+
base_ref="origin/$${GITHUB_BASE_REF}"; \
789+
elif git rev-parse --verify "$${GITHUB_BASE_REF}^{commit}" >/dev/null 2>&1; then \
790+
base_ref="$${GITHUB_BASE_REF}"; \
791+
fi; \
792+
fi; \
793+
if [ -n "$$base_ref" ]; then \
794+
bash scripts/check-stale-lock-files.sh --base-ref "$$base_ref"; \
795+
else \
796+
bash scripts/check-stale-lock-files.sh; \
797+
fi
786798

787799
# Check for drift between workflow markdown sources and generated lock files.
788800
# Compiles all .github/workflows/*.md files and fails if any .lock.yml would
@@ -946,7 +958,7 @@ lint-action-sh:
946958

947959
# Validate all project files
948960
.PHONY: lint
949-
lint: fmt-check fmt-check-json lint-cjs golint validate-model-alias-chains lint-action-sh
961+
lint: check-stale-lock-files fmt-check fmt-check-json lint-cjs golint validate-model-alias-chains lint-action-sh
950962
@echo "✓ All validations passed"
951963

952964
# Install the binary locally

scripts/check-stale-lock-files.sh

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,28 @@ set +o histexpand
33

44
# check-stale-lock-files.sh - Lightweight guard for stale .lock.yml files
55
#
6-
# Detects workflow .md files that have been modified (in the git working tree or
7-
# staging area) without their compiled .lock.yml being regenerated.
6+
# Detects workflow .md files that changed without their compiled .lock.yml being
7+
# regenerated.
88
#
99
# Unlike check-workflow-drift.sh, this script does not require the gh-aw binary:
1010
# it uses git to identify modified .md files and checks whether each has a
1111
# corresponding .lock.yml that was also modified. Use check-workflow-drift.sh
1212
# for a thorough recompile-based verification; use this script as a fast early
1313
# gate that catches the obvious case where a .md was edited and not recompiled.
1414
#
15-
# When there are no modified .md files in the working tree or staging area the
16-
# script exits 0 immediately, so it is a no-op on a clean checkout.
15+
# By default, the script inspects staged/unstaged changes in the current working
16+
# tree. With --base-ref, it instead compares HEAD to a base ref, which is useful
17+
# for CI runs on a clean checkout.
1718
#
1819
# Usage:
19-
# check-stale-lock-files.sh [--dir <workflows-dir>]
20+
# check-stale-lock-files.sh [--dir <workflows-dir>] [--base-ref <git-ref>]
2021
#
2122
# Options:
2223
# --dir <dir> Workflows directory to scan (default: .github/workflows).
2324
# The script only examines .md files under this directory.
25+
# --base-ref <git-ref>
26+
# Git base ref used to detect changed files via
27+
# `git diff <base-ref>...HEAD`. Intended for CI.
2428
#
2529
# Exit codes:
2630
# 0 - No modified .md files detected, or every modified .md has a
@@ -44,16 +48,21 @@ else
4448
fi
4549

4650
WORKFLOWS_DIR=".github/workflows"
51+
BASE_REF=""
4752

4853
while [[ $# -gt 0 ]]; do
4954
case "$1" in
5055
--dir)
5156
WORKFLOWS_DIR="${2:?--dir requires an argument}"
5257
shift 2
5358
;;
59+
--base-ref)
60+
BASE_REF="${2:?--base-ref requires an argument}"
61+
shift 2
62+
;;
5463
*)
5564
echo -e "${RED}ERROR${NC}: unknown argument: $1" >&2
56-
echo "Usage: check-stale-lock-files.sh [--dir <workflows-dir>]" >&2
65+
echo "Usage: check-stale-lock-files.sh [--dir <workflows-dir>] [--base-ref <git-ref>]" >&2
5766
exit 1
5867
;;
5968
esac
@@ -64,9 +73,21 @@ if [ ! -d "$WORKFLOWS_DIR" ]; then
6473
exit 1
6574
fi
6675

67-
# Collect all files that git sees as modified (staged or unstaged vs HEAD).
68-
# On a clean checkout with no edits this set is empty, so the check is a no-op.
69-
all_modified=$(git diff --name-only HEAD 2>/dev/null || true)
76+
collect_modified_files() {
77+
# Explicit base ref compare (clean checkout safe, CI-friendly).
78+
if [ -n "$BASE_REF" ]; then
79+
if git rev-parse --verify "${BASE_REF}^{commit}" >/dev/null 2>&1; then
80+
git diff --name-only "${BASE_REF}...HEAD" 2>/dev/null || true
81+
return
82+
fi
83+
echo -e "${YELLOW}WARN${NC}: --base-ref not found (${BASE_REF}); falling back to working-tree check." >&2
84+
fi
85+
86+
# Local contributor path: staged/unstaged vs HEAD.
87+
git diff --name-only HEAD 2>/dev/null || true
88+
}
89+
90+
all_modified=$(collect_modified_files)
7091

7192
# Filter to .md files within the workflows directory.
7293
# Strip a leading "./" from WORKFLOWS_DIR for consistent prefix matching.
@@ -88,6 +109,7 @@ stale_files=()
88109
missing_locks=()
89110

90111
while IFS= read -r md; do
112+
[ -f "$md" ] || continue
91113
[ -n "$md" ] || continue
92114
lock="${md%.md}.lock.yml"
93115

scripts/check-stale-lock-files_test.sh

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,47 @@ else
183183
fail "missing directory error message was unexpected" "$(cat "$T8_OUT")"
184184
fi
185185

186+
# ---------------------------------------------------------------------------
187+
# Test 9: --base-ref detects stale committed markdown changes on clean tree.
188+
# ---------------------------------------------------------------------------
189+
echo "Test 9: --base-ref catches stale committed markdown changes..."
190+
T9="$TMP_ROOT/t9"
191+
mkdir -p "$T9"
192+
create_fixture_repo "$T9" "base-ref-workflow"
193+
T9_BASE_COMMIT=$(git -C "$T9" rev-parse HEAD)
194+
git -C "$T9" checkout -q -b feature
195+
printf '%s\n' "# base-ref-workflow (edited)" > "$T9/.github/workflows/base-ref-workflow.md"
196+
git -C "$T9" add .github/workflows/base-ref-workflow.md
197+
git -C "$T9" commit -q -m "edit workflow markdown only"
198+
T9_OUT="$TMP_ROOT/t9-output.txt"
199+
if (cd "$T9" && bash "$STALE_SCRIPT" --base-ref "$T9_BASE_COMMIT" >"$T9_OUT" 2>&1); then
200+
fail "--base-ref stale check should exit 1" "$(cat "$T9_OUT")"
201+
elif grep -q "base-ref-workflow.md" "$T9_OUT"; then
202+
pass "--base-ref catches stale committed markdown changes"
203+
else
204+
fail "--base-ref stale output did not name the .md file" "$(cat "$T9_OUT")"
205+
fi
206+
207+
# ---------------------------------------------------------------------------
208+
# Test 10: --base-ref passes when markdown + lock were both committed.
209+
# ---------------------------------------------------------------------------
210+
echo "Test 10: --base-ref passes when markdown + lock both changed..."
211+
T10="$TMP_ROOT/t10"
212+
mkdir -p "$T10"
213+
create_fixture_repo "$T10" "base-ref-ok"
214+
T10_BASE_COMMIT=$(git -C "$T10" rev-parse HEAD)
215+
git -C "$T10" checkout -q -b feature
216+
printf '%s\n' "# base-ref-ok (edited)" > "$T10/.github/workflows/base-ref-ok.md"
217+
printf '%s\n' "lock: updated" > "$T10/.github/workflows/base-ref-ok.lock.yml"
218+
git -C "$T10" add .github/workflows/base-ref-ok.md .github/workflows/base-ref-ok.lock.yml
219+
git -C "$T10" commit -q -m "edit workflow markdown and lock"
220+
T10_OUT="$TMP_ROOT/t10-output.txt"
221+
if (cd "$T10" && bash "$STALE_SCRIPT" --base-ref "$T10_BASE_COMMIT" >"$T10_OUT" 2>&1); then
222+
pass "--base-ref passes when markdown + lock both changed"
223+
else
224+
fail "--base-ref should pass when markdown + lock changed" "$(cat "$T10_OUT")"
225+
fi
226+
186227
echo
187228
echo "Tests passed: $TESTS_PASSED"
188229
echo "Tests failed: $TESTS_FAILED"

0 commit comments

Comments
 (0)