Allow intentional protected-workflow changes via PR label#14
Open
kazukinakai wants to merge 1 commit into
Open
Allow intentional protected-workflow changes via PR label#14kazukinakai wants to merge 1 commit into
kazukinakai wants to merge 1 commit into
Conversation
A workflow declaring repo-quality-gate/db-tests as of the base revision is permanently unimprovable through the normal PR lane: detect_native_gates.sh hard-fails any PR that touches it, with no escape hatch. This bit a real case in agiletec/agiletec: db-tests.yml skips its pgTAP job on every main push because its own change-detection diffs github.event.before under fetch-depth: 1, which never sees the merge's files. Fixing that requires editing the protected workflow, which the guard forbids. Add a deliberate, auditable escape hatch: the PR label allow-protected-workflow-change lets a protected-workflow diff through and prints a notice naming each changed path, instead of failing. Absent the label, behavior is unchanged. The label is threaded in from the pull_request event context (github.event.pull_request.labels.*.name) via the PR_LABELS env var, never from repository file content, so a head cannot self-authorize by editing tracked files. merge_group events carry no labels, so PR_LABELS is empty there and strict behavior still applies.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivating case
`detect_native_gates.sh` hard-fails any PR that modifies a workflow the base
revision already declares as a required gate (`repo-quality-gate`, or
`db-tests` when the repo has `supabase/config.toml`). There is no label,
allowlist, or bypass, so such a workflow is permanently unimprovable through
the normal PR lane.
Real case in `agiletec-inc/agiletec`: `.github/workflows/db-tests.yml` skips
its pgTAP job on every `main` push, because its own change-detection diffs
`github.event.before` under `fetch-depth: 1`, so the diff never sees the
merge's files. Fixing that requires editing the protected workflow file —
which this guard forbids — so a gate that is provably not running cannot be
repaired.
What changes
detected, check a new `PR_LABELS` env var (space-separated label names) for
`allow-protected-workflow-change`. If present, print
`Protected workflow changed under allow-protected-workflow-change: `
and continue instead of failing. Absent the label, behavior is byte-for-byte
identical to today (same failure message, same exit code).
`detect_native_gates.sh` invocation (step id `native`) from
`github.event.pull_request.labels.*.name`.
modified without the label still fails with the existing message, (b) same
change with the label succeeds and prints the notice, (c) an unrelated
workflow change is unaffected either way, (d) the label has no effect when
there's no protected-workflow change, (e) empty/absent `PR_LABELS` (the
`merge_group` shape, which carries no labels) keeps strict behavior
unchanged.
Why the label can't be forged
The label comes from the `pull_request` event context
(`github.event.pull_request.labels.*.name`), which is metadata GitHub attaches
to the event and is not derived from any file in the head commit. A head
branch cannot grant itself the label by editing tracked repository content —
only a human (or automation with label-write permission) applying the label
via the GitHub UI/API can. `merge_group` events carry no labels at all, so
`PR_LABELS` is empty there and the strict rejection path is unchanged.
What is explicitly NOT weakened
identical to before this change.
by `evaluate_required_checks.mjs`) is untouched.
actual required check runs — the changed workflow still has to execute and
report the same protected context name for the check to pass.
label to a PR is itself a reviewable, audited GitHub action separate from
pushing commits.
Test output
```
$ python3 -m unittest discover -s tests
...............................................
Ran 47 tests in 2.648s
OK
```
Also ran `bash -n .github/scripts/detect_native_gates.sh` (clean) and
`actionlint .github/workflows/quality-gate.yml` (clean).
Not done
Auto-merge intentionally not enabled — this is a governance change for
the owner to review.