Skip to content

Commit c01c25f

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 40fb31e commit c01c25f

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
@@ -36,35 +36,94 @@ def log_env_vars():
3636
print(f"PR_COMMENTS = {PR_COMMENTS}\n")
3737

3838

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

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

69128

70129
def read_result_file() -> str | None:

0 commit comments

Comments
 (0)