Skip to content

Commit 376e231

Browse files
shenxianpengCopilot
andcommitted
fix: check actual PR commits instead of merge commit HEAD
When actions/checkout runs on a pull_request event, it checks out an auto-generated merge commit at refs/pull/{N}/merge as HEAD. The commit message of this merge commit is 'Merge {sha} into {base}', which: - Matches the (Merge).* alternative in the conventional commits regex - Is allowed by allow_merge_commits = true This caused the action to always pass on PRs regardless of the actual commit messages, since only the merge commit HEAD was ever checked. Fix by adding get_pr_commit_messages() which, when GITHUB_BASE_REF is set (indicating a PR context), retrieves the real PR commits via: git log --no-merges origin/{base_ref}..HEAD --format=%B%x00 --reverse Each commit message is then piped individually to commit-check --message via stdin so the actual PR commits are validated. In non-PR contexts (push, manual dispatch, etc.) the existing behaviour is preserved: commit-check determines what to check from git itself. Also fixes stderr being silently discarded (subprocess.PIPE) by using subprocess.STDOUT so errors are captured in result.txt and surfaced in the job summary and PR comments. Fixes #184 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 0fcfa74 commit 376e231

File tree

1 file changed

+82
-23
lines changed

1 file changed

+82
-23
lines changed

main.py

Lines changed: 82 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,35 +35,94 @@ def log_env_vars():
3535
print(f"PR_COMMENTS = {PR_COMMENTS}\n")
3636

3737

38-
def run_commit_check() -> int:
39-
"""Runs the commit-check command and logs the result."""
40-
args = [
41-
"--message",
42-
"--branch",
43-
"--author-name",
44-
"--author-email",
45-
]
46-
args = [
47-
arg
48-
for arg, value in zip(
49-
args,
38+
def get_pr_commit_messages() -> list[str] | None:
39+
"""Get commit messages for all commits in a PR, excluding merge commits.
40+
41+
In a GitHub Actions PR context, HEAD points to an auto-generated merge commit
42+
(refs/pull/{N}/merge), not the actual PR commits. This function retrieves the
43+
real commit messages so they can be validated individually.
44+
45+
Returns None if not in a PR context or if no commits are found.
46+
"""
47+
base_ref = os.getenv("GITHUB_BASE_REF", "")
48+
if not base_ref:
49+
return None
50+
51+
try:
52+
result = subprocess.run(
5053
[
51-
MESSAGE,
52-
BRANCH,
53-
AUTHOR_NAME,
54-
AUTHOR_EMAIL,
54+
"git",
55+
"log",
56+
"--no-merges",
57+
f"origin/{base_ref}..HEAD",
58+
"--format=%B%x00",
59+
"--reverse",
5560
],
61+
stdout=subprocess.PIPE,
62+
stderr=subprocess.PIPE,
63+
text=True,
64+
check=False,
5665
)
57-
if value == "true"
66+
if result.returncode != 0 or not result.stdout.strip():
67+
return None
68+
messages = [m.strip() for m in result.stdout.split("\x00") if m.strip()]
69+
return messages if messages else None
70+
except Exception:
71+
return None
72+
73+
74+
def run_commit_check() -> int:
75+
"""Runs the commit-check command and logs the result."""
76+
other_check_flags = [
77+
("--branch", BRANCH),
78+
("--author-name", AUTHOR_NAME),
79+
("--author-email", AUTHOR_EMAIL),
5880
]
81+
other_args = [arg for arg, value in other_check_flags if value == "true"]
5982

60-
command = ["commit-check"] + args
61-
print(" ".join(command))
83+
ret_code = 0
6284
with open("result.txt", "w") as result_file:
63-
result = subprocess.run(
64-
command, stdout=result_file, stderr=subprocess.PIPE, check=False
65-
)
66-
return result.returncode
85+
if MESSAGE == "true":
86+
commit_messages = get_pr_commit_messages()
87+
if commit_messages:
88+
# PR context: check each commit message individually to avoid
89+
# only checking the auto-generated merge commit at HEAD.
90+
for msg in commit_messages:
91+
command = ["commit-check", "--message"]
92+
print(" ".join(command))
93+
result = subprocess.run(
94+
command,
95+
input=msg,
96+
text=True,
97+
stdout=result_file,
98+
stderr=subprocess.STDOUT,
99+
check=False,
100+
)
101+
ret_code += result.returncode
102+
else:
103+
# Non-PR context: let commit-check determine what to check from git.
104+
command = ["commit-check", "--message"]
105+
print(" ".join(command))
106+
result = subprocess.run(
107+
command,
108+
stdout=result_file,
109+
stderr=subprocess.STDOUT,
110+
check=False,
111+
)
112+
ret_code += result.returncode
113+
114+
if other_args:
115+
command = ["commit-check"] + other_args
116+
print(" ".join(command))
117+
result = subprocess.run(
118+
command,
119+
stdout=result_file,
120+
stderr=subprocess.STDOUT,
121+
check=False,
122+
)
123+
ret_code += result.returncode
124+
125+
return ret_code
67126

68127

69128
def read_result_file() -> str | None:

0 commit comments

Comments
 (0)