Skip to content

Commit 8a2aca0

Browse files
JasonJarvanSheng Zhaoclaude
authored
ci: skip merge commits in commit-message lint (#90)
## Summary The commit-message lint rejects any `Merge ...` commit in the PR range (`scripts/commit_lint.py`: "merge commits are not allowed in PR ranges"). But this repository is squash-only (rebase/merge disabled), so a merge commit created by syncing `main` into a feature branch is squashed away at merge time and never reaches `main`. The rule therefore guards nothing while failing the CI check for every PR that synced `main` via a merge commit (observed on #82). The fix makes `scripts/check_commit_messages.py` gather only non-merge commits by passing `--no-merges` to its `git log` call, mirroring commitlint's own default of ignoring merge commits. The `Merge ` rule in `commit_lint.py` is left intact as belt-and-suspenders (it is also reused by the PR-title path), so no lint behavior is removed. ## Type - [ ] Fix - [ ] Feature - [ ] Docs - [x] CI / tooling - [ ] Refactor - [ ] Other ## Verification - `uv run pytest tests/test_check_commit_messages.py tests/test_commit_lint.py -q` -> 10 passed - `uv run ruff check scripts/check_commit_messages.py tests/test_check_commit_messages.py` -> All checks passed - Added TDD coverage in `tests/test_check_commit_messages.py`: builds a real temporary repo with a `--no-ff` merge commit and asserts the range passes (red before the fix, green after). - [x] Relevant tests pass locally - [x] Relevant lint / type checks pass locally - [ ] User-facing docs or screenshots are updated when needed ## Risk - [x] Security impact considered - [x] Backward compatibility considered - [x] Rollback path is clear for risky changes Backward compatible: real commit messages are still linted exactly as before; only merge commits are now skipped. Rollback is a one-line revert of the `--no-merges` flag. ## Related Issues N/A Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com> Co-authored-by: Sheng Zhao <sheng.zhao@evermind.ai> Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
1 parent f827c00 commit 8a2aca0

2 files changed

Lines changed: 57 additions & 1 deletion

File tree

scripts/check_commit_messages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def _default_range() -> str | None:
4545

4646
def _commit_messages(revision_range: str) -> list[tuple[str, str]]:
4747
output = subprocess.check_output(
48-
["git", "log", "--format=%H%x00%B%x00", revision_range],
48+
["git", "log", "--no-merges", "--format=%H%x00%B%x00", revision_range],
4949
text=True,
5050
)
5151
chunks = output.rstrip("\0").split("\0")
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from __future__ import annotations
2+
3+
import os
4+
import subprocess
5+
from pathlib import Path
6+
7+
from scripts import check_commit_messages
8+
9+
10+
def _git(cwd: Path, *args: str) -> str:
11+
env = {
12+
"GIT_AUTHOR_NAME": "Test",
13+
"GIT_AUTHOR_EMAIL": "test@example.com",
14+
"GIT_COMMITTER_NAME": "Test",
15+
"GIT_COMMITTER_EMAIL": "test@example.com",
16+
"GIT_CONFIG_GLOBAL": "/dev/null",
17+
"GIT_CONFIG_SYSTEM": "/dev/null",
18+
"PATH": os.environ["PATH"],
19+
}
20+
return subprocess.check_output(["git", *args], cwd=cwd, text=True, env=env).strip()
21+
22+
23+
def _init_repo(root: Path) -> None:
24+
_git(root, "init", "-q", "-b", "main")
25+
(root / "a.txt").write_text("a\n")
26+
_git(root, "add", "a.txt")
27+
_git(root, "commit", "-qm", "feat: seed initial file")
28+
29+
30+
def test_range_with_merge_commit_passes(tmp_path: Path) -> None:
31+
repo = tmp_path / "repo"
32+
repo.mkdir()
33+
_init_repo(repo)
34+
base = _git(repo, "rev-parse", "HEAD")
35+
36+
_git(repo, "checkout", "-q", "-b", "feature")
37+
(repo / "b.txt").write_text("b\n")
38+
_git(repo, "add", "b.txt")
39+
_git(repo, "commit", "-qm", "feat: add feature file")
40+
41+
_git(repo, "checkout", "-q", "main")
42+
(repo / "c.txt").write_text("c\n")
43+
_git(repo, "add", "c.txt")
44+
_git(repo, "commit", "-qm", "feat: add main file")
45+
46+
_git(repo, "checkout", "-q", "feature")
47+
_git(repo, "merge", "--no-ff", "-m", "Merge branch 'main' into feature", "main")
48+
49+
cwd = Path.cwd()
50+
try:
51+
os.chdir(repo)
52+
exit_code = check_commit_messages.main([f"{base}..HEAD"])
53+
finally:
54+
os.chdir(cwd)
55+
56+
assert exit_code == 0

0 commit comments

Comments
 (0)