fix(git-tools): add admin-gated --no-ci-expected merge assertion to ci-queue-wait
A repository with no CI configured has no sanctioned wrapper merge path: the queue guard fails closed on zero status contexts for purpose=merge (exit 3). That fail-closed default stays correct, because at merge time no-status may also mean CI has not reported yet; but it left CI-less repos unmergeable without the break-glass override, which makes the override a gap rather than an exception. --no-ci-expected reclassifies only the zero-context case for merge as queue-clear, and only when the acting token holds repository admin. The elevation check reads the repository object's permissions.admin: the branch-head and combined-status responses the guard already fetches carry no permissions object at all. The assertion prints its own audit line (purpose, branch, asserting identity, reason) and writes a NO_CI_ASSERTED JSONL record to the existing audit sink; an unauditable pass is refused (exit 70). A non-admin caller is refused with exit 77 (ASSERTION_REFUSED, own text, audited), kept distinct from ASSERTED_NOT_READY's exit 3; an unavailable permissions lookup holds as CANNOT_ASSERT exit 75. --require-status contradicts the flag and is a usage error; a pending or failed context still holds or fails exactly as before; push behavior is unchanged. pr-merge.sh gains a pass-through --no-ci-expected that only forwards the flag to the guard invocation. PowerShell twins are unchanged: no existing test exercises their guard path (pr-merge.ps1 only runs with -SkipQueueGuard; ci-queue-wait.ps1 has no test). Closes #1372
This commit is contained in:
@@ -111,7 +111,7 @@ approve path carries the trap.) `pr-review.sh` sends the correct token for the d
|
||||
Whatever you use, re-read `GET /pulls/{n}/reviews` and assert the state before reporting a verdict
|
||||
placed.
|
||||
|
||||
The guard exits nonzero for any provider-asserted non-green, missing, or malformed CI state. If credentials or the provider are unavailable, it emits `CANNOT_ASSERT` and writes a JSONL audit record. Push degrades to exit 0 so recovery work is not bricked; merge holds with retryable exit 75 until the provider recovers, then self-clears without manual reset. Neither outcome is evidence that CI was clear. `pr-merge.sh` automatically inspects the exact PR head repository and full commit SHA rather than its `main` base; this also handles fork PRs without branch-name ambiguity. Pass `--expect-head <approved-full-sha>` to bind a commit-specific review or merge-gate verdict; Gitea uses atomic `head_commit_id` and GitHub uses `--match-head-commit`.
|
||||
The guard exits nonzero for any provider-asserted non-green, missing, or malformed CI state. If credentials or the provider are unavailable, it emits `CANNOT_ASSERT` and writes a JSONL audit record. Push degrades to exit 0 so recovery work is not bricked; merge holds with retryable exit 75 until the provider recovers, then self-clears without manual reset. Neither outcome is evidence that CI was clear. For a repository with no CI configured at all, `pr-merge.sh --no-ci-expected` is the sanctioned merge path: it forwards to `ci-queue-wait.sh --no-ci-expected`, which reclassifies a zero-context merge head as queue-clear only when the acting token holds repository admin, and records the assertion (or its refusal) in the same JSONL audit log. `pr-merge.sh` automatically inspects the exact PR head repository and full commit SHA rather than its `main` base; this also handles fork PRs without branch-name ambiguity. Pass `--expect-head <approved-full-sha>` to bind a commit-specific review or merge-gate verdict; Gitea uses atomic `head_commit_id` and GitHub uses `--match-head-commit`.
|
||||
|
||||
### Code Review (Codex)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user