fix(744): qualify the two 'ci-image-pin is blocking' conclusions, rewrap
Build ErsatzTV Image / CI toolchain image resolves (pull_request) Successful in 8s
PR Gates / Docs update reminder (pull_request) Successful in 11s
PR Gates / decisions lifecycle (pull_request) Successful in 15s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 22s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 15s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 13s
Review verdict / Set review-verdict status (pull_request_target) Successful in 16s
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Successful in 5m25s
review-verdict/h10 Review-verdict: MERGEABLE @ 43b1e45 (base: main)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Canceled after 2m44s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Canceled after 0s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Canceled after 0s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Canceled after 0s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Canceled after 0s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Canceled after 0s

Round-4 self-review. `ci-image-pin` is NOT a branch-protection required context —
pr-checks.yml says so in as many words (branch protection requires only
`Build & test (.NET)`, `EF migration integrity` and `review-verdict/h10`). The
block is real but comes from the merge-consent hook reading the COMBINED commit
status. 'Blocking' is pre-existing shorthand for this job and is left alone where
it is only a label; the two sites that hang a CONCLUSION on it ('so a PR changing
docker/ci without moving the pin is red, and the only way to move the pin was...')
are this branch's, and are qualified. Fixing the workflow copy last round and not
its twin in the record is the fix-one-site-miss-its-twin shape.

refs #744

Decisions-Edit: yes
This commit is contained in:
2026-08-27 21:56:29 +02:00
parent aa406acd26
commit 43b1e45b55
2 changed files with 8 additions and 4 deletions
+4 -2
View File
@@ -1697,7 +1697,8 @@ ersatztv#299 seeded-media/scanner E2E follow-ups will need.
**Bumping the toolchain is a deliberate two-step.** The jobs pin an immutable `:<sha>`, never
`:latest`, so a bad toolchain push cannot break every job at once. Both steps land in the **same
PR** — `ci-image-pin` is blocking, so a PR that changes `docker/ci/**` without moving the pin is red:
PR** — a PR that changes `docker/ci/**` without moving the pin turns `ci-image-pin` red, and the
merge-consent hook reads the combined status, so it will not auto-grant:
1. **Publish.** Push the branch with the `docker/ci/Dockerfile` change as HEAD, then dispatch
`ci-image.yml` on that branch; it publishes `ersatztv-ci:<sha>`. (`:latest` moves only from
@@ -1823,7 +1824,8 @@ tradeoff, not a necessity** — keeping the file in `expected` still works, sinc
can publish the ci-image.yml commit itself and the pin then matches. What it costs is the reason it
went: that route charges a full ~2 GB publish and a five-pin bump for *every* edit to the file, a
comment included, and a rebase charges it again. That price reverted the first attempt (#697) and is
why this change was landed alone — also a priced decision, not a rule. The chosen side pays the opposite risk instead, below.
why this change was landed alone — also a priced decision, not a rule. The chosen side pays the
opposite risk instead, below.
The consequence to live with: if you change **how** the image is built (build-args, Dockerfile path,
platforms) without touching `docker/ci/**`, CI keeps running an image built by the previous recipe
and nothing goes red. **Make the change alongside a `docker/ci/**` edit** — a comment bump in the
@@ -25,8 +25,10 @@ mechanics: '`docs/ci-cd.md` -> "CI toolchain image" -> "Publishing from a branch
the deliberate publish path.
- **The capability removed was real, so it is replaced rather than argued away.** An earlier attempt
(#697) justified the filter with "publishing from a feature branch was not load-bearing", which is
false: `ci-image-pin` is blocking, so a PR changing `docker/ci/**` without moving the pin is red, and
the only way to move the pin was to publish from the branch first. The replacement is the same
false: a PR changing `docker/ci/**` without moving the pin turns `ci-image-pin` red, and the
merge-consent hook reads the COMBINED commit status, so it will not auto-grant — the job is not
itself a branch-protection required context, but the effect is the same. The only way to move the
pin was to publish from the branch first. The replacement is the same
two-step with a dispatch in place of the push — push the `docker/ci` commit as HEAD, dispatch
`ci-image.yml` on that branch (it tags `git rev-parse --short HEAD`, so the two must coincide), then
commit the pin bump on top. A rebase rewrites the sha, so all three are redone; that was already true.