From 60c21cdc95e2ea587b53c229cd0076537716c581 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Wed, 25 Feb 2026 20:44:13 +0200 Subject: [PATCH 1/5] feat: add GH_TOKEN and GITHUB_TOKEN environment variables in action.yml --- action.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/action.yml b/action.yml index 68df492..901a169 100644 --- a/action.yml +++ b/action.yml @@ -69,3 +69,5 @@ runs: DRY_RUN: ${{ inputs.dry-run }} JOB_SUMMARY: ${{ inputs.job-summary }} PR_COMMENTS: ${{ inputs.pr-comments }} + GH_TOKEN: ${{ github.token }} + GITHUB_TOKEN: ${{ github.token }} From 74063e936694cab6221052d26760e7957837fe5a Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Wed, 25 Feb 2026 20:49:17 +0200 Subject: [PATCH 2/5] fix: remove GITHUB_TOKEN requirement for pr-comments feature in README --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 826bc2e..6da81e2 100644 --- a/README.md +++ b/README.md @@ -52,8 +52,6 @@ jobs: with: fetch-depth: 0 # Required for merge-base checks - uses: commit-check/commit-check-action@v2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed for PR comments with: message: true branch: true @@ -123,7 +121,7 @@ jobs: - Default: `false` > [!IMPORTANT] -> `pr-comments` is an experimental feature. By default, it's disabled. To use it, you need to set `GITHUB_TOKEN` in the GitHub Action. +> `pr-comments` is an experimental feature. By default, it's disabled. > > This feature currently doesn’t work with forked repositories. For more details, refer to issue [#77](https://github.com/commit-check/commit-check-action/issues/77). From abe6b8de1e8ee6f6a1d72c1cfc86fa222d346f44 Mon Sep 17 00:00:00 2001 From: Xianpeng Shen Date: Wed, 25 Feb 2026 21:04:13 +0200 Subject: [PATCH 3/5] fix: Remove GITHUB_TOKEN from commit-check workflow Removed GITHUB_TOKEN environment variable for self test. --- .github/workflows/commit-check.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/commit-check.yml b/.github/workflows/commit-check.yml index d9faf0e..b68a5dc 100644 --- a/.github/workflows/commit-check.yml +++ b/.github/workflows/commit-check.yml @@ -16,8 +16,6 @@ jobs: with: fetch-depth: 0 # Required for merge-base checks - uses: ./ # self test - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed for PR comments with: message: true branch: true From 0fcfa74b3bf09e320f5cafb42dd600ef8130c6d7 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Wed, 25 Feb 2026 21:05:57 +0200 Subject: [PATCH 4/5] fix: remove GH_TOKEN from action.yml environment variables --- action.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/action.yml b/action.yml index 901a169..98552ef 100644 --- a/action.yml +++ b/action.yml @@ -69,5 +69,4 @@ runs: DRY_RUN: ${{ inputs.dry-run }} JOB_SUMMARY: ${{ inputs.job-summary }} PR_COMMENTS: ${{ inputs.pr-comments }} - GH_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }} From 376e231a87fe8fe74359015b32a1250d001a0e63 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sat, 14 Mar 2026 01:18:19 +0200 Subject: [PATCH 5/5] 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> --- main.py | 105 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 23 deletions(-) diff --git a/main.py b/main.py index 2ec7ea5..00876a1 100755 --- a/main.py +++ b/main.py @@ -35,35 +35,94 @@ def log_env_vars(): print(f"PR_COMMENTS = {PR_COMMENTS}\n") -def run_commit_check() -> int: - """Runs the commit-check command and logs the result.""" - args = [ - "--message", - "--branch", - "--author-name", - "--author-email", - ] - args = [ - arg - for arg, value in zip( - args, +def get_pr_commit_messages() -> list[str] | None: + """Get commit messages for all commits in a PR, excluding merge commits. + + In a GitHub Actions PR context, HEAD points to an auto-generated merge commit + (refs/pull/{N}/merge), not the actual PR commits. This function retrieves the + real commit messages so they can be validated individually. + + Returns None if not in a PR context or if no commits are found. + """ + base_ref = os.getenv("GITHUB_BASE_REF", "") + if not base_ref: + return None + + try: + result = subprocess.run( [ - MESSAGE, - BRANCH, - AUTHOR_NAME, - AUTHOR_EMAIL, + "git", + "log", + "--no-merges", + f"origin/{base_ref}..HEAD", + "--format=%B%x00", + "--reverse", ], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + check=False, ) - if value == "true" + if result.returncode != 0 or not result.stdout.strip(): + return None + messages = [m.strip() for m in result.stdout.split("\x00") if m.strip()] + return messages if messages else None + except Exception: + return None + + +def run_commit_check() -> int: + """Runs the commit-check command and logs the result.""" + other_check_flags = [ + ("--branch", BRANCH), + ("--author-name", AUTHOR_NAME), + ("--author-email", AUTHOR_EMAIL), ] + other_args = [arg for arg, value in other_check_flags if value == "true"] - command = ["commit-check"] + args - print(" ".join(command)) + ret_code = 0 with open("result.txt", "w") as result_file: - result = subprocess.run( - command, stdout=result_file, stderr=subprocess.PIPE, check=False - ) - return result.returncode + if MESSAGE == "true": + commit_messages = get_pr_commit_messages() + if commit_messages: + # PR context: check each commit message individually to avoid + # only checking the auto-generated merge commit at HEAD. + for msg in commit_messages: + command = ["commit-check", "--message"] + print(" ".join(command)) + result = subprocess.run( + command, + input=msg, + text=True, + stdout=result_file, + stderr=subprocess.STDOUT, + check=False, + ) + ret_code += result.returncode + else: + # Non-PR context: let commit-check determine what to check from git. + command = ["commit-check", "--message"] + print(" ".join(command)) + result = subprocess.run( + command, + stdout=result_file, + stderr=subprocess.STDOUT, + check=False, + ) + ret_code += result.returncode + + if other_args: + command = ["commit-check"] + other_args + print(" ".join(command)) + result = subprocess.run( + command, + stdout=result_file, + stderr=subprocess.STDOUT, + check=False, + ) + ret_code += result.returncode + + return ret_code def read_result_file() -> str | None: