-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.py
executable file
·200 lines (163 loc) · 6.05 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/usr/bin/env python3
import os
import sys
import subprocess
import re
from github import Github # type: ignore
# Constants for message titles
SUCCESS_TITLE = "# Commit-Check ✔️"
FAILURE_TITLE = "# Commit-Check ❌"
# Environment variables
MESSAGE = os.getenv("MESSAGE", "false")
BRANCH = os.getenv("BRANCH", "false")
AUTHOR_NAME = os.getenv("AUTHOR_NAME", "false")
AUTHOR_EMAIL = os.getenv("AUTHOR_EMAIL", "false")
COMMIT_SIGNOFF = os.getenv("COMMIT_SIGNOFF", "false")
MERGE_BASE = os.getenv("MERGE_BASE", "false")
DRY_RUN = os.getenv("DRY_RUN", "false")
JOB_SUMMARY = os.getenv("JOB_SUMMARY", "false")
PR_COMMENTS = os.getenv("PR_COMMENTS", "false")
GITHUB_STEP_SUMMARY = os.environ["GITHUB_STEP_SUMMARY"]
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY")
GITHUB_REF = os.getenv("GITHUB_REF")
def log_env_vars():
"""Logs the environment variables for debugging purposes."""
print(f"MESSAGE = {MESSAGE}")
print(f"BRANCH = {BRANCH}")
print(f"AUTHOR_NAME = {AUTHOR_NAME}")
print(f"AUTHOR_EMAIL = {AUTHOR_EMAIL}")
print(f"COMMIT_SIGNOFF = {COMMIT_SIGNOFF}")
print(f"MERGE_BASE = {MERGE_BASE}")
print(f"DRY_RUN = {DRY_RUN}")
print(f"JOB_SUMMARY = {JOB_SUMMARY}")
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",
"--commit-signoff",
"--merge-base",
]
args = [
arg
for arg, value in zip(
args,
[MESSAGE, BRANCH, AUTHOR_NAME, AUTHOR_EMAIL, COMMIT_SIGNOFF, MERGE_BASE],
)
if value == "true"
]
command = ["commit-check"] + args
print(" ".join(command))
with open("result.txt", "w") as result_file:
result = subprocess.run(
command, stdout=result_file, stderr=subprocess.PIPE, check=False
)
return result.returncode
def read_result_file() -> str | None:
"""Reads the result.txt file and removes ANSI color codes."""
if os.path.getsize("result.txt") > 0:
with open("result.txt", "r") as result_file:
result_text = re.sub(
r"\x1B\[[0-9;]*[a-zA-Z]", "", result_file.read()
) # Remove ANSI colors
return result_text.rstrip()
return None
def add_job_summary() -> int:
"""Adds the commit check result to the GitHub job summary."""
if JOB_SUMMARY == "false":
return 0
result_text = read_result_file()
summary_content = (
SUCCESS_TITLE
if result_text is None
else f"{FAILURE_TITLE}\n```\n{result_text}\n```"
)
with open(GITHUB_STEP_SUMMARY, "a") as summary_file:
summary_file.write(summary_content)
return 0 if result_text is None else 1
def add_pr_comments() -> int:
"""Posts the commit check result as a comment on the pull request."""
if PR_COMMENTS == "false":
return 0
try:
token = os.getenv("GITHUB_TOKEN")
repo_name = os.getenv("GITHUB_REPOSITORY")
pr_number = os.getenv("GITHUB_REF")
if pr_number is not None:
pr_number = pr_number.split("/")[-2]
else:
# Handle the case where GITHUB_REF is not set
raise ValueError("GITHUB_REF environment variable is not set")
# Initialize GitHub client
g = Github(token)
repo = g.get_repo(repo_name)
pull_request = repo.get_issue(int(pr_number))
# Prepare comment content
result_text = read_result_file()
pr_comments = (
SUCCESS_TITLE
if result_text is None
else f"{FAILURE_TITLE}\n```\n{result_text}\n```"
)
# Fetch all existing comments on the PR
comments = pull_request.get_comments()
# Track if we found a matching comment
matching_comments = []
last_comment = None
for comment in comments:
if comment.body.startswith(SUCCESS_TITLE) or comment.body.startswith(
FAILURE_TITLE
):
matching_comments.append(comment)
if matching_comments:
last_comment = matching_comments[-1]
if last_comment.body == pr_comments:
print(f"PR comment already up-to-date for PR #{pr_number}.")
return 0
else:
# If the last comment doesn't match, update it
print(f"Updating the last comment on PR #{pr_number}.")
last_comment.edit(pr_comments)
# Delete all older matching comments
for comment in matching_comments[:-1]:
print(f"Deleting an old comment on PR #{pr_number}.")
comment.delete()
else:
# No matching comments, create a new one
print(f"Creating a new comment on PR #{pr_number}.")
pull_request.create_comment(body=pr_comments)
return 0 if result_text is None else 1
except Exception as e:
print(f"Error posting PR comment: {e}", file=sys.stderr)
return 1
def log_error_and_exit(
failure_title: str, result_text: str | None, ret_code: int
) -> None:
"""
Logs an error message to GitHub Actions and exits with the specified return code.
Args:
failure_title (str): The title of the failure message.
result_text (str): The detailed result text to include in the error message.
ret_code (int): The return code to exit with.
"""
if result_text:
error_message = f"{failure_title}\n```\n{result_text}\n```"
print(f"::error::{error_message}")
sys.exit(ret_code)
def main():
"""Main function to run commit-check, add job summary and post PR comments."""
log_env_vars()
# Combine return codes
ret_code = run_commit_check()
ret_code += add_job_summary()
ret_code += add_pr_comments()
if DRY_RUN == "true":
ret_code = 0
result_text = read_result_file()
log_error_and_exit(FAILURE_TITLE, result_text, ret_code)
if __name__ == "__main__":
main()