diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 706f8ae2..6b77604f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,17 +74,3 @@ jobs: - name: the Stage-B schedules loader's tests run: uv run --frozen pytest working-directory: tools/servicetag-schedules - hygiene: - if: github.event_name == 'pull_request' - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 - with: - ref: ${{ github.event.pull_request.head.sha }} # the pull request's own tip, not the merge ref - fetch-depth: 0 # the whole range, and origin/ - persist-credentials: false # this job needs no git credentials after the checkout - - name: the pull request's own commits follow CLAUDE.md - env: - BASE: origin/${{ github.base_ref }} - HEAD_SHA: ${{ github.event.pull_request.head.sha }} - run: bash tools/check-commit-hygiene.sh "$BASE" "$HEAD_SHA" diff --git a/.github/workflows/hygiene.yml b/.github/workflows/hygiene.yml new file mode 100644 index 00000000..64b8e34e --- /dev/null +++ b/.github/workflows/hygiene.yml @@ -0,0 +1,20 @@ +name: hygiene +# Its own workflow, on pull requests only, so a pull request's head carries exactly one check run +# named "hygiene": the ruleset "master: hygiene required" waits on that name, and a job skipped by +# an `if:` inside the push-triggered ci workflow would also count as passed. +on: + pull_request: +jobs: + hygiene: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + with: + ref: ${{ github.event.pull_request.head.sha }} # the pull request's own tip, not the merge ref + fetch-depth: 0 # the whole range, and origin/ + persist-credentials: false # this job needs no git credentials after the checkout + - name: the pull request's own commits follow CLAUDE.md + env: + BASE: origin/${{ github.base_ref }} + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + run: bash tools/check-commit-hygiene.sh "$BASE" "$HEAD_SHA" diff --git a/CLAUDE.md b/CLAUDE.md index dee37bd6..7518d4a1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,7 +25,8 @@ commit or pull request attribution. Product design lives in `docs/`, not here. - Name the branch for the work, `fix-…` or `issue-123-…`. Never start it with a tool's name. - Merge with a merge commit whose subject carries no tool-named branch. Never squash or rebase away the owner's history. -- CI's `hygiene` job runs `tools/check-commit-hygiene.sh` over the pull request's own commits. Run +- The `hygiene` workflow runs `tools/check-commit-hygiene.sh` over the pull request's own commits and + master requires it green (ruleset "master: hygiene required"; repository admins can bypass). Run it before pushing: `bash tools/check-commit-hygiene.sh origin/master HEAD`. ## The gates CI cannot run diff --git a/docs/release-proofs.md b/docs/release-proofs.md index ccb037bb..52e431e8 100644 --- a/docs/release-proofs.md +++ b/docs/release-proofs.md @@ -81,7 +81,7 @@ prints the three activities sorted and `other 0 []`; a fourth exported component Each prints nothing, or the count stated. The author, attribution and empty-body lines, and the three content greps, are now also enforced on every pull request, over its own commits, by -`tools/check-commit-hygiene.sh` (CI's `hygiene` job); the controller still runs them all here. +`tools/check-commit-hygiene.sh` (the `hygiene` workflow, required on master); the controller still runs them all here. - no e-mail in added lines: `git diff ..HEAD | grep -nE '^\+.*[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}'` (fixture URLs carry none) - no home path: `git diff ..HEAD | grep -nE '^\+.*/hom[e]/[a-z]'`