Skip to content

Commit 0aceb63

Browse files
committed
ci: replace per-commit conventional commits check with pr title check
1 parent 228af17 commit 0aceb63

5 files changed

Lines changed: 50 additions & 62 deletions

File tree

.claude/skills/pr-workflow/SKILL.md

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -49,28 +49,29 @@ behaviour change that affects packet contents or timing —
4949
reviewers shouldn't have to reverse-engineer why a constant moved
5050
or a probe interval changed.
5151

52-
## 3. Commit message conventions
53-
54-
Commit messages are linted by `commitlint` with
55-
`@commitlint/config-conventional`, _and_ by `commitizen` in
56-
pre-commit (`stages: [commit-msg]`). Both must pass.
57-
58-
- **Conventional Commits prefix is required.** Pick from:
59-
`feat`, `fix`, `perf`, `refactor`, `docs`, `test`, `build`,
60-
`ci`, `chore`, `style`, `revert`. The `feat`/`fix`/`perf`
61-
prefixes show up in the release-notes; `chore*` and `ci*` are
62-
excluded by semantic-release (`exclude_commit_patterns` in
63-
`pyproject.toml`), so use those for housekeeping.
52+
## 3. PR title conventions
53+
54+
PRs are squash-merged, so the PR title becomes the commit on
55+
`master`. Only the PR title is linted (by the `pr-title` CI job
56+
running `amannn/action-semantic-pull-request`); per-commit
57+
messages on the PR branch are not checked.
58+
59+
- **Conventional Commits prefix is required on the PR title.**
60+
Pick from: `feat`, `fix`, `perf`, `refactor`, `docs`, `test`,
61+
`build`, `ci`, `chore`, `style`, `revert`. The
62+
`feat`/`fix`/`perf` prefixes show up in the release-notes;
63+
`chore*` and `ci*` are excluded by semantic-release
64+
(`exclude_commit_patterns` in `pyproject.toml`), so use those
65+
for housekeeping.
6466
- **Imperative-mood subject.** "fix: handle empty answer", not
6567
"fix: handled empty answer".
66-
- **No header length cap.** The commitlint config sets
67-
`header-max-length: [0, "always", Infinity]`, so a slightly
68-
longer subject is fine if it earns the space; don't pad.
68+
- **Lowercase first character after the prefix** (enforced by
69+
`subjectPattern: ^(?![A-Z]).+$`).
6970
- **No `Co-Authored-By` trailers from automated agents.**
70-
- **One logical change per commit.** Let pre-commit run (ruff
71+
- **One logical change per PR.** Let pre-commit run (ruff
7172
lint + format, mypy, flake8, codespell, cython-lint,
7273
pyupgrade). If a hook auto-fixes something, re-stage and
73-
re-commit; the commit-msg hook re-runs on the new commit.
74+
re-commit.
7475

7576
## 4. Cython / `.pxd` discipline
7677

@@ -101,22 +102,23 @@ Always pass the body via `--body-file`, never `--body "..."` with
101102
shell-escaping — Markdown backticks, asterisks, and angle
102103
brackets must pass through verbatim.
103104

104-
The PR title should match the commit subject (same Conventional
105-
Commits prefix). If the PR ends up squash-merged, the title
106-
becomes the merged commit message, so it has to satisfy
107-
commitlint on its own.
105+
The PR title is what gets enforced — it becomes the squash-merge
106+
commit subject on `master`, so it has to parse as a Conventional
107+
Commit on its own. Per-commit messages on the branch are not
108+
linted.
108109

109110
## 6. After the PR is open
110111

111112
CI runs three jobs:
112113

113114
- `lint``pre-commit/action`. If pre-commit passed locally
114115
this passes too.
115-
- `commitlint``wagoid/commitlint-github-action`. Validates
116-
every commit on the PR; if you amended after pushing, force-
117-
push the branch so the rewritten commits get linted.
118-
- `test` — the full pytest matrix across CPython 3.9–3.14,
119-
3.14t (free-threaded), and PyPy 3.9 / 3.10, on Linux + macOS +
116+
- `pr-title``amannn/action-semantic-pull-request`. Validates
117+
the PR title against Conventional Commits. If it fails, fix
118+
the title in the GitHub UI or with `gh pr edit --title "..."`;
119+
the workflow re-runs on the edit, no push needed.
120+
- `test` — the full pytest matrix across CPython 3.10–3.14,
121+
3.14t (free-threaded), and PyPy 3.10, on Linux + macOS +
120122
Windows. The free-threaded entry is the canary for unguarded
121123
shared-state bugs; failures there are often genuine even when
122124
the GIL-enabled rows pass.

.github/workflows/ci.yml

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,10 @@ jobs:
2424
python-version: "3.12"
2525
- uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
2626

27-
# Make sure commit messages follow the conventional commits convention:
27+
# Make sure the PR title follows the conventional commits convention:
2828
# https://www.conventionalcommits.org
29-
commitlint:
30-
name: Lint Commit Messages
31-
runs-on: ubuntu-latest
32-
steps:
33-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
34-
with:
35-
fetch-depth: 0
36-
- uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6
37-
38-
# PRs are squash-merged, so the PR title becomes the commit subject on
39-
# master. Validate it against Conventional Commits so the squashed commit
40-
# stays release-tool-friendly even when individual commits don't.
29+
# PRs are squash-merged, so the PR title becomes the commit on master and
30+
# drives python-semantic-release's version bump.
4131
pr-title:
4232
name: Lint PR Title
4333
runs-on: ubuntu-latest
@@ -48,6 +38,12 @@ jobs:
4838
- uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
4939
env:
5040
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41+
with:
42+
subjectPattern: ^(?![A-Z]).+$
43+
subjectPatternError: |
44+
The subject "{subject}" found in the pull request title "{title}"
45+
didn't match the configured pattern. Please ensure that the subject
46+
starts with a lowercase character.
5147
5248
test:
5349
strategy:
@@ -155,7 +151,6 @@ jobs:
155151
needs:
156152
- test
157153
- lint
158-
- commitlint
159154
if: ${{ github.repository_owner }} == "python-zeroconf"
160155

161156
runs-on: ubuntu-latest

.pre-commit-config.yaml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ ci:
88
autoupdate_commit_msg: "chore(pre-commit.ci): pre-commit autoupdate"
99

1010
repos:
11-
- repo: https://github.com/commitizen-tools/commitizen
12-
rev: v4.16.2
13-
hooks:
14-
- id: commitizen
15-
stages: [commit-msg]
1611
- repo: https://github.com/pre-commit/pre-commit-hooks
1712
rev: v6.0.0
1813
hooks:

CLAUDE.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,17 @@ path. The authoritative list of cythonized modules lives in
8585

8686
## Commit / PR conventions
8787

88-
- **Conventional Commits are enforced.** CI runs commitlint with
89-
`@commitlint/config-conventional`, and pre-commit runs
90-
commitizen on the commit message. The header has no length cap
91-
(`header-max-length = [0, "always", Infinity]`), but the
92-
_type_ prefix is required: `feat:`, `fix:`, `chore:`, `ci:`,
93-
`docs:`, `refactor:`, `test:`, `perf:`, `build:`, etc.
94-
`semantic-release` excludes `chore*` and `ci*` from the
88+
- **Conventional Commits PR title, lowercase subject.** PRs are
89+
squash-merged, so the **PR title** becomes the commit on
90+
`master` and is the only string that has to parse as a
91+
Conventional Commit. The repo enforces this via the `pr-title`
92+
CI job in `ci.yml` using `amannn/action-semantic-pull-request`.
93+
Accepted types: `feat`, `fix`, `chore`, `ci`, `docs`,
94+
`refactor`, `test`, `perf`, `build`, etc. The subject (text
95+
after `type(scope):`) must start lowercase (enforced by
96+
`subjectPattern: ^(?![A-Z]).+$`). Per-commit messages on the
97+
PR branch are **not** linted; they get collapsed at squash-
98+
merge. `semantic-release` excludes `chore*` and `ci*` from the
9599
changelog, so use those prefixes for housekeeping and reserve
96100
`feat`/`fix`/`perf` for user-visible changes.
97101
- **No `Co-Authored-By` trailers from automated agents.** Project
@@ -267,8 +271,8 @@ or commit that names the bug class and the affected code path.
267271
the resulting wheel will crash at import time.
268272
- **Don't add `Co-Authored-By` trailers from automated agents
269273
to commits** in this repo.
270-
- **Don't introduce a commit message that violates Conventional
271-
Commits.** The commitlint job will fail the PR.
274+
- **Don't introduce a PR title that violates Conventional
275+
Commits.** The `pr-title` job will fail the PR.
272276
- **Don't tighten timings or constants in `const.py` without an
273277
RFC citation in the commit message.** mDNS interop with
274278
Avahi / Bonjour / Windows hinges on those numbers.

commitlint.config.mjs

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)