fix(prettier): fail-safe changed-file scoping; never autofix workflow files#118
Conversation
…files A transient GitHub API error (HTML 5xx body -> gh --jq 'invalid character <' parse failure) failed the PR changed-file listing on whois-api-llc/wxa-secrets#27, and the failure branch fell OPEN to full-glob mode: prettier --write ran on the whole tree, reformatted pre-existing drift in .github/workflows/pr-review.yml (a file the PR never touched), and the push died on the workflow-scope check — a red X on every yml-less PR in any repo with workflow-file drift. - lint.yml + prettier-autofix.yml: retry the files API 3x, then SKIP (mode=none) instead of widening scope to the full tree. Blocks kept byte-identical; drift-checked by the new selftest. - prettier-autofix.yml: revert any prettier write under .github/workflows/ before committing — automerge_pat deliberately lacks workflow scope (fleet policy), so such pushes are always rejected. Covers changed_only=false callers and PRs that legitimately touch a misformatted workflow file. - selftest/test_prettier_scope_failsafe.sh: extracts and executes the shipped bash — listing failure -> mode=none (never glob), guard reverts workflow writes and keeps the rest, python-only PR -> skip, positive control -> mode=files. Wired into test_workflow_guards.py. Co-Authored-By: Claude Fable 5 <[email protected]>
|
Coverage Floor — mode:
|
|
Independent verification from the session that babysat wxa-secrets#27 (where this incident fired twice, attempts 1+2 of run 29542573990):
Ready for human review + manual merge (fleet policy for this repo). Until it lands, every yml-less PR fleet-wide stays exposed to the same red-X during API turbulence. |
|
Risk class: This PR touches one of the blocked path categories from Auto-merge is refused by (This is a policy notice, not a code-quality failure. The classify job itself does not fail — required CI checks remain authoritative for "is the code green.") |
|
No issues found. Fail-safe flips listing failure to mode=none (skip+pass, handled in both case blocks), retry loop is -e-safe, and the workflow-file revert guard runs before staging without touching PR-authored commits. Blocks are byte-identical and selftest-covered. |
prettier-autofix can never push workflow-file fixes (AUTOMERGE_PAT lacks workflow scope by design), so pre-existing drift here redlines any PR that touches these files. Fleet-wide one-time clear; the full-tree fall-open that surfaced it is fixed in topcoder1/ci-workflows#118. Co-Authored-By: Claude Fable 5 <[email protected]>
prettier-autofix can never push workflow-file fixes (AUTOMERGE_PAT lacks workflow scope by design), so pre-existing drift here redlines any PR that touches these files. Fleet-wide one-time clear; the full-tree fall-open that surfaced it is fixed in #118. Co-Authored-By: Claude Fable 5 <[email protected]>
prettier-autofix can never push workflow-file fixes (AUTOMERGE_PAT lacks workflow scope by design), so pre-existing drift here redlines any PR that touches these files. Fleet-wide one-time clear; the full-tree fall-open that surfaced it is fixed in topcoder1/ci-workflows#118. Co-Authored-By: Claude Fable 5 <[email protected]>
prettier-autofix can never push workflow-file fixes (AUTOMERGE_PAT lacks workflow scope by design), so pre-existing drift here redlines any PR that touches these files. Fleet-wide one-time clear; the full-tree fall-open that surfaced it is fixed in topcoder1/ci-workflows#118. Co-Authored-By: Claude Fable 5 <[email protected]>
Root cause (wxa-secrets#27, job log)
A transient GitHub API error (HTML 5xx body →
gh --jqdied withinvalid character '<' looking for beginning of value) failed the PR changed-file listing on a Python-only PR. The listing-failure branch fell open to full-glob mode:prettier --writeran on the entire tree, reformatted pre-existing drift in.github/workflows/pr-review.yml(a file the PR never touched), and the push was rejected —refusing to allow a Personal Access Token to create or update workflow ... without 'workflow' scope(AUTOMERGE_PAT correctly lacks that scope). Net effect: every such PR goes red in any repo carrying workflow-file drift.Note the empty-intersection path (
mode=none) was already correct — the fall-open was specifically the listing-failure branch. The job token hadPullRequests: read; the old warning text blaming caller permissions was misleading.Fix
mode=none) with a loud::warning::. A scoping failure is never widened to a full-tree pass. Blocks kept byte-identical; the new selftest drift-checks them..github/workflows/before staging. automerge_pat will never have workflow scope by fleet policy, so such pushes are always rejected. Coverschanged_only: falsecallers and PRs that legitimately touch a misformatted workflow file (explicit glob mode remains caller opt-in).mode=none(never glob, incl. behavioral run of the extracted block with a failingghstub); guard reverts workflow writes and keeps the rest; python-only PR → skip; positive control →mode=files. Wired intotest_workflow_guards.py. RED before this fix (fall-open + missing guard), GREEN after.Verification
uv run pytest -q: 9 passed (includes new selftest)prettier --checkclean on edited files;actionlintcleanFollow-up (separate, human-pushed): one-time format commit on wxa-secrets main to clear the pre-existing
.github/workflows/pr-review.ymldrift.Auto-merge rationale: manual-merge category — PRs to topcoder1/ci-workflows are always manual merge (fleet policy) and this touches
.github/workflows/**(production infrastructure). Opened as draft so automerge stays disarmed.🤖 Generated with Claude Code