ci(535): split PR-only git gates into pr-checks.yml so release tags don't red #537

Merged
timothy merged 1 commits from fix/535-pr-only-workflow-split into main 2026-07-21 18:31:42 +02:00
Owner

Fixes #535.

Root cause (run-952 forensics)

All five PR-only jobs are dispatched on a tag push even though if: github.event_name == 'pull_request' should skip them — Gitea dispatches a job as a runner task even when its if skips it, evaluating the skip only after dispatch. On the v26.12.0 tag, api-docs/format (ubuntu-latest, identical if:) resolved to skipped cleanly, while the three small-lane git-diff gates (ci-image-pin, docs-reminder, decisions-guard) wedged in act's setup phase and were killed by a runner restart mid-setup → failure (no logs) → red overall commit status on a release that built, scanned, and deployed fine. #508 (already in the tag) widened the lane but did not prevent it. The kill lands in the dispatch window before any step or if:-skip runs, so tweaking the if:/step logic (the issue's options 2/3) could not fix it.

Fix

Relocate exactly those three pure git-diff gates (no container:, no image pin) verbatim into a dedicated .gitea/workflows/pr-checks.yml that triggers on: pull_request only. Gitea evaluates a workflow's trigger before creating any job, so on a tag/main push this workflow produces zero jobs: no dispatch, no kill, no spurious red — for the whole class, permanently.

Why it's safe

  • ci-image-pin integrity: it carries no pin and still greps docker-build.yml, where all five pin-bearing jobs (test/migrations/functional-e2e/api-docs/format) remain → validation unchanged.
  • Merges unaffected: none of the three are required checks (only Build & test (.NET) + EF migration integrity are), and the merge-consent hook reads the prefix-agnostic combined status, so the context-prefix change (Build ErsatzTV Image / … → PR Gates / …) doesn't matter.
  • Bashisms: pr-checks.yml declares defaults: run: shell: bash (ci-image-pin uses mapfile/set -o pipefail).
  • Faithful relocation: byte-identical job bodies (only intentional diff: a comment in this file → in docker-build.yml).
  • Live proof: this PR itself runs the three gates under the new PR Gates / context.

Docs

docs/ci-cd.md: new PR gates workflow section + cross-references (same PR).

Review

Cold adversarial review over the diff: MERGEABLE, no Blocker/High/Medium/Low findings.

🤖 Generated with Claude Code

Fixes #535. ## Root cause (run-952 forensics) All five PR-only jobs are **dispatched** on a tag push even though `if: github.event_name == 'pull_request'` should skip them — Gitea dispatches a job as a runner task *even when its `if` skips it*, evaluating the skip only after dispatch. On the v26.12.0 tag, `api-docs`/`format` (ubuntu-latest, **identical** `if:`) resolved to `skipped` cleanly, while the three `small`-lane git-diff gates (`ci-image-pin`, `docs-reminder`, `decisions-guard`) wedged in act's setup phase and were killed by a runner restart mid-setup → `failure` (no logs) → red overall commit status on a release that built, scanned, and deployed fine. #508 (already in the tag) widened the lane but did not prevent it. The kill lands in the dispatch window **before** any step or `if:`-skip runs, so tweaking the `if:`/step logic (the issue's options 2/3) could not fix it. ## Fix Relocate exactly those three pure git-diff gates (no `container:`, no image pin) **verbatim** into a dedicated `.gitea/workflows/pr-checks.yml` that triggers `on: pull_request` **only**. Gitea evaluates a workflow's trigger *before* creating any job, so on a tag/main push this workflow produces **zero** jobs: no dispatch, no kill, no spurious red — for the whole class, permanently. ## Why it's safe - **`ci-image-pin` integrity**: it carries no pin and still greps `docker-build.yml`, where all five pin-bearing jobs (`test`/`migrations`/`functional-e2e`/`api-docs`/`format`) remain → validation unchanged. - **Merges unaffected**: none of the three are required checks (only `Build & test (.NET)` + `EF migration integrity` are), and the merge-consent hook reads the prefix-agnostic **combined** status, so the context-prefix change (`Build ErsatzTV Image / …` → `PR Gates / …`) doesn't matter. - **Bashisms**: `pr-checks.yml` declares `defaults: run: shell: bash` (`ci-image-pin` uses `mapfile`/`set -o pipefail`). - **Faithful relocation**: byte-identical job bodies (only intentional diff: a comment `in this file` → `in docker-build.yml`). - **Live proof**: this PR itself runs the three gates under the new `PR Gates /` context. ## Docs `docs/ci-cd.md`: new **PR gates workflow** section + cross-references (same PR). ## Review Cold adversarial review over the diff: **MERGEABLE**, no Blocker/High/Medium/Low findings. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
timothy added 1 commit 2026-07-21 18:08:23 +02:00
ci(535): split PR-only git gates into pr-checks.yml so release tags don't red
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 9s
PR Gates / Docs update reminder (pull_request) Successful in 12s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 12s
PR Gates / decisions lifecycle (pull_request) Successful in 17s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m24s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 16m39s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 19m49s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 21m20s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
b4ac46fce1
Three PR-only git-diff gates (ci-image-pin, docs-reminder, decisions-guard)
lived in docker-build.yml, which also triggers on push to main and v* tags.
Gitea dispatches a job as a runner task even when its `if` skips it, so on
every tag/main push these three were dispatched to the `small` lane just to
evaluate the skip. On the v26.12.0 tag those dispatched skip-tasks wedged in
act's setup phase and were killed by a runner restart mid-setup, reporting
`failure` (no logs) and reddening the tag's overall commit status even though
the release built, scanned, and deployed fine. The two identical-`if:` jobs on
ubuntu-latest (api-docs, format) skipped cleanly — the job logic was never the
problem; the kill lands in the dispatch window before any step or skip runs, so
tweaking the `if:`/step logic could not fix it.

Relocate exactly those three (pure checkout + git-diff, no container:, no image
pin) verbatim into a dedicated pr-checks.yml that triggers `on: pull_request`
only. Gitea evaluates a workflow's trigger before creating any job, so on a
tag/main push this workflow produces zero jobs: no dispatch, no kill, no
spurious red — for the whole class, permanently.

- ci-image-pin carries no pin and still greps docker-build.yml, where all five
  pin-bearing jobs (test/migrations/functional-e2e/api-docs/format) remain, so
  its validation is unchanged.
- None of the three are required checks (only Build & test + EF migration
  integrity are), so the status-context prefix change (Build ErsatzTV Image / ...
  -> PR Gates / ...) does not affect merges; the merge-consent hook reads the
  prefix-agnostic combined status.
- pr-checks.yml declares `defaults: run: shell: bash` (ci-image-pin uses
  mapfile / set -o pipefail).

docs/ci-cd.md: new "PR gates workflow" section + cross-references.

fixes #535

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Owner

Review-verdict: MERGEABLE @ b4ac46fce1

Cold adversarial review over the diff returned MERGEABLE with zero Blocker/High/Medium/Low findings (only a pre-existing informational nit on the pin grep, unchanged by this PR). CI green on this head, including the three relocated gates running under the new PR Gates / context (live proof the split works).

Review-verdict: MERGEABLE @ b4ac46fce188496c17fb25f1e00872264dad2c89 Cold adversarial review over the diff returned MERGEABLE with zero Blocker/High/Medium/Low findings (only a pre-existing informational nit on the pin grep, unchanged by this PR). CI green on this head, including the three relocated gates running under the new `PR Gates /` context (live proof the split works).
timothy merged commit c21d227132 into main 2026-07-21 18:31:42 +02:00
timothy deleted branch fix/535-pr-only-workflow-split 2026-07-21 18:31:42 +02:00
Sign in to join this conversation.