Merge origin/release/1.0 into SAFETY-25
CI-02 landed on release/1.0 after this branch was opened and both tickets add a block under `## Unreleased`, so CHANGELOG.md collided. Both entries are kept, newest-first: SAFETY-25's, then CI-02's, then SAFETY-20's. Nothing else conflicted.
This commit is contained in:
@@ -69,6 +69,71 @@ against a freshly copied tree with no `__pycache__` present at all, mounted
|
||||
`:ro` — the same structural immunity `MUTATION.md` records for CI. All eight go
|
||||
red on the named check.
|
||||
|
||||
**The gate has never once graded the content a pull request would land, and a
|
||||
run that never started reported as a test failure (CI-02).** Both halves were
|
||||
measured on a deliberately conflicted throwaway pull request rather than read
|
||||
off the workflow, because the Actions log endpoints 404 on this Gitea and a
|
||||
step's own conclusion is the only channel out of a job.
|
||||
|
||||
**Case 1, and the ticket's mechanism was wrong in a way that made it worse.**
|
||||
CI-02 was filed saying a conflicted pull request loses its merge ref, so that
|
||||
`git fetch $GITHUB_REF || git fetch $GITHUB_SHA` falls through and grades the
|
||||
bare branch head. The symptom was real — PR #14 reported `checks / unit ->
|
||||
success` while `mergeable: false` — but the mechanism is not. On this server
|
||||
`GITHUB_REF` **is** `refs/pull/<n>/head`, `GITHUB_SHA` is the same commit, and
|
||||
`git ls-remote origin 'refs/pull/*'` advertises no `/merge` refs at all, for
|
||||
open and closed pull requests alike. The first fetch has always succeeded; **the
|
||||
fallback has never fired once.** So the gate did not lose merged content on
|
||||
conflicted pull requests — it has never had merged content, on any pull request
|
||||
in this repository's history. Green has meant "this branch passed on its own",
|
||||
which on a base that has moved is not what lands, and `block_on_outdated_branch`
|
||||
is off on release/1.0 so the base usually has moved.
|
||||
|
||||
**The checkout now fetches the base tip and the pull request head, merges them,
|
||||
and refuses if the merge does not apply** — as its own named step, so
|
||||
`/actions/runs/<id>/jobs` distinguishes "nothing was tested" from "the tests
|
||||
spoke". Verified by producing it: with the fix on a conflicted pull request the
|
||||
required context went `failure` in 2 s with the two test steps `skipped`. The
|
||||
`--depth 1` is gone (a merge needs a merge base; a full fetch of this repository
|
||||
is 6.8 MB and 1.1 s), and the fallback survives only on the `workflow_dispatch`
|
||||
path, which has no pull request to merge and now says so in its output.
|
||||
|
||||
**Case 2: `concurrency:` is gone, and `cancel-in-progress` was never the knob.**
|
||||
Runs 531 and 533 on PR #14 were cancelled at 0 s each at the exact second the
|
||||
next run was created, having never started; a cancelled run posts `failure` on
|
||||
the required context, described `Canceled after 0s`, and branch protection
|
||||
compares state and not description — so "nothing ran" and "your tests are
|
||||
broken" arrive at the gate as the same red, wanting opposite responses. Three
|
||||
settings were measured with one run holding the single runner slot and two
|
||||
pushes behind it: with **no block at all** both queued runs survived and
|
||||
executed; with the group kept and **`cancel-in-progress: false`** the queued run
|
||||
was still cancelled at 0 s. A shared group cancels a run that has not started
|
||||
regardless of that flag. Having no group is the only configuration measured to
|
||||
leave a queued run alive, and it is what ships. The cost — a developer who
|
||||
pushes four times occupies the shared runner four times — is CI-01's own trade
|
||||
written the other way round: a delayed verdict, never a destroyed one.
|
||||
|
||||
**`test_ci_gate.py` grades the gate by running it, not by reading it.** It
|
||||
extracts the checkout and merge steps out of `checks.yml` and executes the
|
||||
shipped commands against two throwaway local repositories it builds — one whose
|
||||
pull request merges, one whose does not — and pins that the old one-liner exits
|
||||
0 on the unmergeable one while the new steps refuse. It also pins the two tokens
|
||||
that assemble `checks / unit (pull_request)`: renaming `name:` or the `unit:`
|
||||
job key would leave every open and future pull request waiting forever on a
|
||||
context that never arrives, with no error anywhere in that sequence. Seven
|
||||
mutations of `checks.yml` were each confirmed red. `.gitea/ci/Dockerfile` gains
|
||||
`git` for it.
|
||||
|
||||
**What was NOT established, stated so nobody reads more into this.** The
|
||||
original report that "no run was ever created for `0942228d`" was already
|
||||
corrected on the card — run 533 was created and cancelled — and this work
|
||||
confirms that from the runs list and the per-commit status history. A commit
|
||||
that never had a run carries an empty `/statuses/<sha>` list; a queued one
|
||||
carries `pending / Waiting to run` within seconds, and a concurrency-held one
|
||||
`pending / Blocked by required conditions`. Those are distinguishable at the
|
||||
API. `/actions/tasks`, which is what was polled originally, lists only tasks
|
||||
that started, and cannot answer the question at all.
|
||||
|
||||
**A setpoint device smaller than `max_w` silently disarmed the frozen-meter
|
||||
detector, and the status page reported it as armed (SAFETY-20).** SAFETY-18's
|
||||
conjunction needs `abs(commanded_w) >= 0.95 * max_w`, but the emitted command is
|
||||
|
||||
Reference in New Issue
Block a user