From d689a935fb47f2e1371cf9f543d583eb71389677 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Fri, 28 Aug 2026 06:31:02 -0700 Subject: [PATCH] Retry the Prose Gate's Diff-Base Resolve on a Fresh Merge Tip (#1050) ## What The prose-gate composite action's `git rev-parse --verify` check on the diff base (`github.event.pull_request.base.sha`) now retries with backoff (0/2/4/8/15/30s, re-fetching the ref before each retry) instead of failing on the first miss. ## Why Fixes #1049. That issue documents `ptr727/Financial-Modeling#194`'s Lint sources job failing four times in a row (two reruns, one fresh push) with: ``` ::error::Diff base 'fcc57bfd9c...' does not resolve in this checkout. ::error::Check the ref name and that the job checks out with fetch-depth 0. ``` against a base SHA that was confirmed, both at failure time and afterward, to be `develop`'s genuine tip, a real ancestor of the PR branch, reachable by `git ls-remote`, and covered by the caller's own `fetch-depth: 0` unshallow fetch. The base was a merge commit created by a squash-merge only hours (in that case) to minutes before the failing runs, which points at GitHub-side replication lag on a freshly created merge commit rather than a logic bug in the checkout or the gate. Retrying the resolve check, rather than failing on the first miss, absorbs that lag without weakening the check itself: an actually-absent or malformed base still fails after exhausting the retries, in well under the job's overall timeout. ## Verification - `shellcheck -x` and manual review of the extracted composite-action script (the embedded script isn't covered by the repo's own `*.sh` gate, so this was a standalone check). - `python3 scripts/repo_gate.py` clean. - `python3 .github/actions/prose-gate/prose_lint.py --diff origin/develop -- .` clean against this change's own diff (dogfooding the gate this PR modifies). - Pre-commit hooks passed on commit. The GitHub-side replication-lag mechanism itself isn't independently reproducible from this session, so this is a mitigation for the symptom the issue describes rather than a proven root-cause fix; the retry is safe either way since it only widens the window before the existing failure mode fires. ## Summary by CodeRabbit * **Bug Fixes** * Improved reliability when determining the comparison baseline. * Added retry and refresh handling to reduce failures caused by temporarily unavailable branch data. --- .github/actions/prose-gate/action.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/actions/prose-gate/action.yml b/.github/actions/prose-gate/action.yml index e8f9fbe6..edca233c 100644 --- a/.github/actions/prose-gate/action.yml +++ b/.github/actions/prose-gate/action.yml @@ -23,7 +23,19 @@ runs: # Check the base resolves before scanning, so an empty or absent ref fails naming itself. # Unresolvable, the run would report the repository's whole backlog against this change. # A shallow checkout is the usual cause, so the caller fetches full history. - if ! git rev-parse --verify --quiet "$BASE^{commit}" >/dev/null; then + # A base that is a freshly created merge commit can still lag GitHub's own replication, so retry with backoff before failing rather than treat that lag as a gate failure. + resolved=false + for delay in 0 2 4 8 15 30; do + if [ "$delay" -gt 0 ]; then + sleep "$delay" + git fetch --quiet origin "$BASE" 2>/dev/null || true + fi + if git rev-parse --verify --quiet "$BASE^{commit}" >/dev/null; then + resolved=true + break + fi + done + if ! "$resolved"; then echo "::error::Diff base '$BASE' does not resolve in this checkout." >&2 echo "::error::Check the ref name and that the job checks out with fetch-depth 0." >&2 exit 1