Skip to content

Commit 785d02e

Browse files
authored
feat: Support posting pull request comments (#71)
* feat: support add pull request comments * add .pre-commit-config.yaml to format code * fix: requirements.txt and test new input * fix: just checking PR_COMMENTS * feat: add GITHUB_TOKEN * update readme.md * update exiting comments or delete it to add new one * try to fix 'Issue' object has no attribute 'get_issue_comments' * update .commit-check.yml * try to fix posting issue comment * docs: update readme * docs: update links
1 parent f0c5269 commit 785d02e

File tree

7 files changed

+218
-46
lines changed

7 files changed

+218
-46
lines changed

.commit-check.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@ checks:
77
[optional body]\n
88
[optional footer(s)]\n\n
99
More details please refer to https://www.conventionalcommits.org"
10-
suggest: git commit --amend --no-verify
10+
suggest: please check your commit message whether matches above regex
1111

1212
- check: branch
13-
regex: ^(bugfix|feature|release|hotfix|task|dependabot)\/.+|(master)|(main)|(HEAD)|(PR-.+)
14-
error: "Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/"
15-
suggest: git checkout -b type/branch_name
13+
regex: ^(bugfix|feature|release|hotfix|task|chore)\/.+|(master)|(main)|(HEAD)|(PR-.+)
14+
error: "Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/ chore/"
15+
suggest: run command `git checkout -b type/branch_name`
1616

1717
- check: author_name
1818
regex: ^[A-Za-z ,.\'-]+$|.*(\[bot])
1919
error: The committer name seems invalid
20-
suggest: git config user.name "Peter Shen"
20+
suggest: run command `git config user.name "Your Name"`
2121

2222
- check: author_email
2323
regex: ^\S+@\S+\.\S+$
2424
error: The committer email seems invalid
25-
suggest: git config user.email petershen@example.com
25+
suggest: run command `git config user.email yourname@example.com`

.github/workflows/commit-check.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ jobs:
1313
with:
1414
ref: ${{ github.event.pull_request.head.sha }}
1515
- uses: ./ # self test
16+
env:
17+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # used by `pr-comments`
1618
with:
1719
message: true
1820
branch: true
1921
author-name: true
2022
author-email: true
2123
commit-signoff: true
2224
job-summary: true
25+
pr-comments: true

.pre-commit-config.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# https://pre-commit.com/
2+
ci:
3+
autofix_commit_msg: 'ci: auto fixes from pre-commit.com hooks'
4+
autoupdate_commit_msg: 'ci: pre-commit autoupdate'
5+
6+
repos:
7+
- repo: https://github.com/pre-commit/pre-commit-hooks
8+
rev: v5.0.0
9+
hooks:
10+
- id: check-yaml
11+
- id: check-toml
12+
- id: end-of-file-fixer
13+
- id: trailing-whitespace
14+
- id: name-tests-test
15+
- id: requirements-txt-fixer
16+
- repo: https://github.com/psf/black-pre-commit-mirror
17+
rev: 24.10.0
18+
hooks:
19+
- id: black
20+
# FIXME: main.py:109: error: Item "None" of "str | None" has no attribute "split" [union-attr]
21+
# - repo: https://github.com/pre-commit/mirrors-mypy
22+
# rev: v1.12.0
23+
# hooks:
24+
# - id: mypy
25+
- repo: https://github.com/codespell-project/codespell
26+
rev: v2.3.0
27+
hooks:
28+
- id: codespell

README.md

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ jobs:
2525
runs-on: ubuntu-latest
2626
steps:
2727
- uses: actions/checkout@v4
28+
with:
29+
ref: ${{ github.event.pull_request.head.sha }} # Checkout PR HEAD commit
2830
- uses: commit-check/commit-check-action@v1
2931
with:
3032
message: true
@@ -34,6 +36,7 @@ jobs:
3436
commit-signoff: true
3537
dry-run: true
3638
job-summary: true
39+
pr-comments: true
3740
```
3841
3942
## Optional Inputs
@@ -72,22 +75,41 @@ jobs:
7275

7376
### `job-summary`
7477

75-
- **Description**: display job summary to a workflow run
78+
- **Description**: display job summary to the workflow run
7679
- Default: 'true'
7780

81+
### `pr-comments`
82+
83+
- **Description**: post results to the pull request comments
84+
- Default: 'true'
85+
86+
> [!IMPORTANT]
87+
> This is a experimental feature
88+
> use it you need to set `GITHUB_TOKEN` in the GitHub Action.
89+
7890
Note: the default rule of above inputs is following [this configuration](https://github.com/commit-check/commit-check/blob/main/.commit-check.yml), if you want to customize just add your `.commit-check.yml` config file under your repository root directory.
7991

8092
## GitHub Action job summary
8193

82-
By default, commit-check-action results are shown on the job summary page of the workflow.
94+
By default, commit-check-action results are shown on the job summary page of the workflow.
8395

8496
### Success job summary
8597

86-
![Success job summary](https://github.com/commit-check/.github/blob/main/screenshot/success-summary.png)
98+
![Success job summary](https://github.com/commit-check/.github/blob/main/screenshot/success-job-summary.png)
8799

88100
### Failure job summary
89101

90-
![Failure job summary](https://github.com/commit-check/.github/blob/main/screenshot/failure-summary.png)
102+
![Failure job summary](https://github.com/commit-check/.github/blob/main/screenshot/failure-job-summary.png)
103+
104+
## GitHub Pull Request comments
105+
106+
### Success pull request comment
107+
108+
![Success pull request comment](https://github.com/commit-check/.github/blob/main/screenshot/success-pr-comments.png)
109+
110+
### Failure pull request comment
111+
112+
![Failure pull request comment](https://github.com/commit-check/.github/blob/main/screenshot/failure-pr-comments.png)
91113

92114
## Badging your repository
93115

action.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ inputs:
3030
required: false
3131
default: false
3232
job-summary:
33-
description: add a job summary
33+
description: display job summary to the workflow run
34+
required: false
35+
default: true
36+
pr-comments:
37+
description: post results to the pull request comments
3438
required: false
3539
default: true
3640
runs:
@@ -55,3 +59,4 @@ runs:
5559
COMMIT_SIGNOFF: ${{ inputs.commit-signoff }}
5660
DRY_RUN: ${{ inputs.dry-run }}
5761
JOB_SUMMARY: ${{ inputs.job-summary }}
62+
PR_COMMENTS: ${{ inputs.pr-comments }}

main.py

Lines changed: 147 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,171 @@
33
import sys
44
import subprocess
55
import re
6+
from github import Github
7+
8+
9+
# Constants for message titles
10+
SUCCESS_TITLE = "# Commit-Check ✔️"
11+
FAILURE_TITLE = "# Commit-Check ❌"
12+
13+
# Environment variables
14+
MESSAGE = os.getenv("MESSAGE", "false")
15+
BRANCH = os.getenv("BRANCH", "false")
16+
AUTHOR_NAME = os.getenv("AUTHOR_NAME", "false")
17+
AUTHOR_EMAIL = os.getenv("AUTHOR_EMAIL", "false")
18+
COMMIT_SIGNOFF = os.getenv("COMMIT_SIGNOFF", "false")
19+
DRY_RUN = os.getenv("DRY_RUN", "false")
20+
JOB_SUMMARY = os.getenv("JOB_SUMMARY", "false")
21+
PR_COMMENTS = os.getenv("PR_COMMENTS", "false")
22+
GITHUB_STEP_SUMMARY = os.environ["GITHUB_STEP_SUMMARY"]
23+
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
24+
GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY")
25+
GITHUB_REF = os.getenv("GITHUB_REF")
26+
27+
28+
def log_env_vars():
29+
"""Logs the environment variables for debugging purposes."""
30+
print(f"MESSAGE = {MESSAGE}")
31+
print(f"BRANCH = {BRANCH}")
32+
print(f"AUTHOR_NAME = {AUTHOR_NAME}")
33+
print(f"AUTHOR_EMAIL = {AUTHOR_EMAIL}")
34+
print(f"COMMIT_SIGNOFF = {COMMIT_SIGNOFF}")
35+
print(f"DRY_RUN = {DRY_RUN}")
36+
print(f"JOB_SUMMARY = {JOB_SUMMARY}")
37+
print(f"PR_COMMENTS = {PR_COMMENTS}\n")
638

739

840
def run_commit_check() -> int:
9-
args = ["--message", "--branch", "--author-name", "--author-email", "--commit-signoff"]
10-
args = [arg for arg, value in zip(args, [MESSAGE, BRANCH, AUTHOR_NAME, AUTHOR_EMAIL, COMMIT_SIGNOFF]) if value == "true"]
41+
"""Runs the commit-check command and logs the result."""
42+
args = [
43+
"--message",
44+
"--branch",
45+
"--author-name",
46+
"--author-email",
47+
"--commit-signoff",
48+
]
49+
args = [
50+
arg
51+
for arg, value in zip(
52+
args, [MESSAGE, BRANCH, AUTHOR_NAME, AUTHOR_EMAIL, COMMIT_SIGNOFF]
53+
)
54+
if value == "true"
55+
]
1156

1257
command = ["commit-check"] + args
1358
print(" ".join(command))
1459
with open("result.txt", "w") as result_file:
15-
result = subprocess.run(command, stdout=result_file, stderr=subprocess.PIPE, check=False)
60+
result = subprocess.run(
61+
command, stdout=result_file, stderr=subprocess.PIPE, check=False
62+
)
1663
return result.returncode
1764

1865

66+
def read_result_file() -> str | None:
67+
"""Reads the result.txt file and removes ANSI color codes."""
68+
if os.path.getsize("result.txt") > 0:
69+
with open("result.txt", "r") as result_file:
70+
result_text = re.sub(
71+
r"\x1B\[[0-9;]*[a-zA-Z]", "", result_file.read()
72+
) # Remove ANSI colors
73+
return result_text.rstrip()
74+
return None
75+
76+
1977
def add_job_summary() -> int:
78+
"""Adds the commit check result to the GitHub job summary."""
2079
if JOB_SUMMARY == "false":
21-
sys.exit()
80+
return 0
2281

23-
if os.path.getsize("result.txt") > 0:
24-
with open("result.txt", "r") as result_file:
25-
result_text = re.sub(r'\x1B\[[0-9;]*[a-zA-Z]', '', result_file.read()) # Remove ANSI colors
82+
result_text = read_result_file()
2683

27-
with open(GITHUB_STEP_SUMMARY, "a") as summary_file:
28-
summary_file.write("### Commit-Check ❌\n```\n")
29-
summary_file.write(result_text)
30-
summary_file.write("```")
31-
return 1
32-
else:
33-
with open(GITHUB_STEP_SUMMARY, "a") as summary_file:
34-
summary_file.write("### Commit-Check ✔️\n")
84+
summary_content = (
85+
SUCCESS_TITLE
86+
if result_text is None
87+
else f"{FAILURE_TITLE}\n```\n{result_text}\n```"
88+
)
89+
90+
with open(GITHUB_STEP_SUMMARY, "a") as summary_file:
91+
summary_file.write(summary_content)
92+
93+
return 0 if result_text is None else 1
94+
95+
96+
def add_pr_comments() -> int:
97+
"""Posts the commit check result as a comment on the pull request."""
98+
if PR_COMMENTS == "false":
3599
return 0
36100

101+
try:
102+
token = os.getenv("GITHUB_TOKEN")
103+
repo_name = os.getenv("GITHUB_REPOSITORY")
104+
pr_number = os.getenv("GITHUB_REF").split("/")[-2]
37105

38-
MESSAGE = os.getenv("MESSAGE", "false")
39-
BRANCH = os.getenv("BRANCH", "false")
40-
AUTHOR_NAME = os.getenv("AUTHOR_NAME", "false")
41-
AUTHOR_EMAIL = os.getenv("AUTHOR_EMAIL", "false")
42-
COMMIT_SIGNOFF = os.getenv("COMMIT_SIGNOFF", "false")
43-
DRY_RUN = os.getenv("DRY_RUN", "false")
44-
JOB_SUMMARY = os.getenv("JOB_SUMMARY", "false")
45-
GITHUB_STEP_SUMMARY = os.environ["GITHUB_STEP_SUMMARY"]
106+
# Initialize GitHub client
107+
g = Github(token)
108+
repo = g.get_repo(repo_name)
109+
pull_request = repo.get_issue(int(pr_number))
110+
111+
# Prepare comment content
112+
result_text = read_result_file()
113+
pr_comments = (
114+
SUCCESS_TITLE
115+
if result_text is None
116+
else f"{FAILURE_TITLE}\n```\n{result_text}\n```"
117+
)
118+
119+
# Fetch all existing comments on the PR
120+
comments = pull_request.get_comments()
121+
122+
# Track if we found a matching comment
123+
matching_comments = []
124+
last_comment = None
125+
126+
for comment in comments:
127+
if comment.body.startswith(SUCCESS_TITLE) or comment.body.startswith(
128+
FAILURE_TITLE
129+
):
130+
matching_comments.append(comment)
131+
if matching_comments:
132+
last_comment = matching_comments[-1]
133+
134+
if last_comment.body == pr_comments:
135+
print(f"PR comment already up-to-date for PR #{pr_number}.")
136+
return 0
137+
else:
138+
# If the last comment doesn't match, update it
139+
print(f"Updating the last comment on PR #{pr_number}.")
140+
last_comment.edit(pr_comments)
141+
142+
# Delete all older matching comments
143+
for comment in matching_comments[:-1]:
144+
print(f"Deleting an old comment on PR #{pr_number}.")
145+
comment.delete()
146+
else:
147+
# No matching comments, create a new one
148+
print(f"Creating a new comment on PR #{pr_number}.")
149+
pull_request.create_comment(body=pr_comments)
150+
151+
return 0 if result_text is None else 1
152+
except Exception as e:
153+
print(f"Error posting PR comment: {e}", file=sys.stderr)
154+
return 1
155+
156+
157+
def main():
158+
"""Main function to run commit-check, add job summary and post PR comments."""
159+
log_env_vars()
160+
161+
# Combine return codes
162+
ret_code = run_commit_check()
163+
ret_code += add_job_summary()
164+
ret_code += add_pr_comments()
46165

47-
print(f"MESSAGE = {MESSAGE}")
48-
print(f"BRANCH = {BRANCH}")
49-
print(f"AUTHOR_NAME = {AUTHOR_NAME}")
50-
print(f"AUTHOR_EMAIL = {AUTHOR_EMAIL}")
51-
print(f"COMMIT_SIGNOFF = {COMMIT_SIGNOFF}")
52-
print(f"DRY_RUN = {DRY_RUN}")
53-
print(f"JOB_SUMMARY = {JOB_SUMMARY}\n")
166+
if DRY_RUN == "true":
167+
ret_code = 0
54168

55-
ret_code = run_commit_check()
56-
ret_code += add_job_summary() # Combine return codes
169+
sys.exit(ret_code)
57170

58-
if DRY_RUN == "true":
59-
ret_code = 0
60171

61-
sys.exit(ret_code)
172+
if __name__ == "__main__":
173+
main()

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# Install commit-check CLI
22
# For details please see: https://github.com/commit-check/commit-check
33
commit-check==0.8.3
4+
# Interact with the GitHub API.
5+
PyGithub==2.4.0

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy