ci: gate docs job on PRs by label/path, gate test job by label too #173

Merged
rootiest merged 1 commits from ci/label-and-path-gated-docs-and-tests into main 2026-09-23 20:27:23 +00:00
Owner

Summary

  • scripts/** was entirely missing from the CI path filter — that directory never triggered CI regardless of what changed there. Added it.
  • Split the old build-docs job into a docs job with two step-gated sections instead of two separate jobs (avoids passing generated files between jobs via artifacts):
    • Doc tests/build (generate concat markdown, verify-manual.py, compile man page) — runs whenever relevant, PRs included.
    • Publish (site build, Cloudflare deploy, commit-back) — step-gated to push/dispatch only, unchanged from before.
  • docs now also runs on a PR labeled Kind/Documentation or Area/Docs, or whose diff touches docs/manual/**, docs/build-manual.py, docs/manualtools.py, docs/verify-manual.py, or docs/site/**.
  • test gains the same shape: also runs on a PR labeled Kind/Testing, Area/Tests, Area/CI, or Area/Scripts, independent of what the PR actually touches.
  • pull_request no longer has a top-level paths: filter (push keeps its own). A label-only PR with an otherwise-irrelevant diff still needs to trigger the workflow at all for the job-level label check to run; the relevance check (diff against base, or an early exit for push/dispatch) now happens per-job in a shell step instead. Added labeled/unlabeled to the pull_request trigger types for the same reason — a label added after the PR is already open, with no new commit, still needs to re-fire this.

Why

Doc-only and test-only PRs got no doc/test feedback until merge — build-docs never ran on a PR at all. Labels now let either job run precisely when relevant, without waiting for a matching path.

Material tradeoff

docs no longer needs: test (the old job did, gating publish on it). main's branch protection already requires test to pass before a PR can merge, so by the time a push-to-main reaches this job, test has necessarily already passed as a condition of getting here — re-checking it in-workflow would be redundant. The one gap this leaves is a direct admin push bypassing the PR flow entirely, which is the same trust already extended by leaving block_admin_merge_override off on the branch protection rule — not a new hole.

Manual Verification Checklist

  • This PR (labeled Area/CI) actually runs the test job's fish suite, not just a skip — check the Install fish/Run fish config tests steps ran
  • A PR touching only README.md with no relevant label — confirm test and docs both skip their real steps but still report success
  • A PR labeled Kind/Documentation with no docs/ changes — confirm docs's build/verify steps run anyway
  • A push to main — confirm docs's publish steps still run as before
  • workflow_dispatch with job: docs — confirm it runs build+publish, job: test runs only the test job
## Summary - `scripts/**` was entirely missing from the CI path filter — that directory never triggered CI regardless of what changed there. Added it. - Split the old `build-docs` job into a `docs` job with two step-gated sections instead of two separate jobs (avoids passing generated files between jobs via artifacts): - **Doc tests/build** (generate concat markdown, `verify-manual.py`, compile man page) — runs whenever relevant, PRs included. - **Publish** (site build, Cloudflare deploy, commit-back) — step-gated to push/dispatch only, unchanged from before. - `docs` now also runs on a PR labeled `Kind/Documentation` or `Area/Docs`, or whose diff touches `docs/manual/**`, `docs/build-manual.py`, `docs/manualtools.py`, `docs/verify-manual.py`, or `docs/site/**`. - `test` gains the same shape: also runs on a PR labeled `Kind/Testing`, `Area/Tests`, `Area/CI`, or `Area/Scripts`, independent of what the PR actually touches. - `pull_request` no longer has a top-level `paths:` filter (`push` keeps its own). A label-only PR with an otherwise-irrelevant diff still needs to trigger the workflow at all for the job-level label check to run; the relevance check (diff against base, or an early exit for push/dispatch) now happens per-job in a shell step instead. Added `labeled`/`unlabeled` to the `pull_request` trigger types for the same reason — a label added after the PR is already open, with no new commit, still needs to re-fire this. ## Why Doc-only and test-only PRs got no doc/test feedback until merge — `build-docs` never ran on a PR at all. Labels now let either job run precisely when relevant, without waiting for a matching path. ## Material tradeoff `docs` no longer `needs: test` (the old job did, gating publish on it). `main`'s branch protection already requires `test` to pass before a PR can merge, so by the time a push-to-main reaches this job, `test` has necessarily already passed as a condition of getting here — re-checking it in-workflow would be redundant. The one gap this leaves is a direct admin push bypassing the PR flow entirely, which is the same trust already extended by leaving `block_admin_merge_override` off on the branch protection rule — not a new hole. ## Manual Verification Checklist - [x] This PR (labeled `Area/CI`) actually runs the `test` job's fish suite, not just a skip — check the `Install fish`/`Run fish config tests` steps ran - [x] A PR touching only `README.md` with no relevant label — confirm `test` and `docs` both skip their real steps but still report success - [x] A PR labeled `Kind/Documentation` with no `docs/` changes — confirm `docs`'s build/verify steps run anyway - [x] A push to `main` — confirm `docs`'s publish steps still run as before - [x] `workflow_dispatch` with `job: docs` — confirm it runs build+publish, `job: test` runs only the test job
rootiest added the Kind/EnhancementArea/CI labels 2026-09-23 20:18:59 +00:00
rootiest added 1 commit 2026-09-23 20:19:05 +00:00
ci: gate docs job on PRs by label/path, gate test job by label too
CI / test (pull_request) Successful in 2m34s
CI / github-mirror (pull_request) Skipped
CI / docs (pull_request) Successful in 24s
4797af85f3
Adds scripts/** to the push path filter -- it was missing entirely, so
that directory never triggered CI regardless of what changed there.

pull_request no longer has a paths: filter (moved that check inside each
job, in shell, since a label-only PR with no relevant diff still needs
to trigger the workflow for the job-level label check to ever run).
Added labeled/unlabeled to pull_request types for the same reason.

Splits the old build-docs job into a docs job with two sections: doc
tests/build (generate concat, verify-manual.py, compile man page) run
whenever relevant on any event; publish (site build, Cloudflare deploy,
commit-back) is step-gated to push/dispatch only, as before. The docs
job now also runs on a PR when it's labeled Kind/Documentation or
Area/Docs, or its diff touches docs/manual/**, docs/build-manual.py,
docs/manualtools.py, docs/verify-manual.py, or docs/site/**.

test gains the same shape: also runs on a PR labeled Kind/Testing,
Area/Tests, Area/CI, or Area/Scripts, independent of what it touches.

docs no longer needs: test. main's branch protection already requires
test to pass before a PR merges, so by the time a push-to-main reaches
this job, test has necessarily already passed; re-checking it here
would be redundant. Leaves the same gap as
block_admin_merge_override=false on that rule: a direct admin push
bypasses it, an accepted trust boundary, not a new one.
rootiest merged commit ea1575f902 into main 2026-09-23 20:27:23 +00:00
rootiest deleted branch ci/label-and-path-gated-docs-and-tests 2026-09-23 20:27:25 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: rootiest/fish-config#173