-
Notifications
You must be signed in to change notification settings - Fork 5
229 lines (197 loc) · 8.51 KB
/
Copy pathcode-quality-check.yml
File metadata and controls
229 lines (197 loc) · 8.51 KB
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
name: Python
on:
pull_request:
permissions:
contents: read
pull-requests: read
jobs:
code-quality-check:
name: Check Code Quality
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.13'
- name: Install dependencies
run: |
pip install black==26.5.1 flake8==7.3.0
- name: Run black and generate diff
id: black_check
run: |
echo "Running black in check mode with diff output..."
black_exit=0
black --check --diff --line-length 99 . > formatting.diff 2>&1 || black_exit=$?
if [ "$black_exit" -ne 0 ]; then
echo "Formatting issues detected:"
cat formatting.diff
echo "black_failed=true" >> $GITHUB_OUTPUT
else
echo "No formatting issues found."
fi
- name: Upload formatting.diff
if: steps.black_check.outputs.black_failed == 'true'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-formatting-diff
path: formatting.diff
- name: Run Flake8 on changed Python files
env:
GH_TOKEN: ${{ github.token }}
run: |
python3 <<'EOF'
import json
import os
import pathlib
import subprocess
import urllib.request
with open(os.environ["GITHUB_EVENT_PATH"], encoding="utf-8") as event_file:
event = json.load(event_file)
repo = os.environ["GITHUB_REPOSITORY"]
pr_number = event["pull_request"]["number"]
token = os.environ["GH_TOKEN"]
changed_files = []
page = 1
run_url = (
f"https://github.com/{os.environ['GITHUB_REPOSITORY']}"
f"/actions/runs/{os.environ['GITHUB_RUN_ID']}"
)
while True:
request = urllib.request.Request(
f"https://api.github.com/repos/{repo}/pulls/{pr_number}/files"
f"?per_page=100&page={page}",
headers={
"Accept": "application/vnd.github+json",
"Authorization": f"Bearer {token}",
},
)
with urllib.request.urlopen(request) as response:
batch = json.load(response)
if not batch:
break
changed_files.extend(
item["filename"]
for item in batch
if item.get("status") != "removed" and item["filename"].endswith(".py")
)
page += 1
if not changed_files:
print("No Python files changed.")
pathlib.Path("flake8_output.txt").write_text("", encoding="utf-8")
with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as env_file:
env_file.write("SKIP=true\n")
env_file.write("FLAKE8_ISSUE_PRESENT=false\n")
env_file.write(f"RUN_URL={run_url}\n")
with open(os.environ["GITHUB_STEP_SUMMARY"], "a", encoding="utf-8") as summary:
summary.write("### Python Code Quality Check\n\n")
summary.write("Flake8 skipped: no Python files changed.\n")
raise SystemExit(0)
print("Running flake8 on:")
for filename in changed_files:
print(f" {filename}")
result = subprocess.run(
["flake8", "--", *changed_files],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
check=False,
)
pathlib.Path("flake8_output.txt").write_text(result.stdout, encoding="utf-8")
print(result.stdout, end="")
issue_present = result.returncode != 0
with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as env_file:
env_file.write("SKIP=false\n")
env_file.write(f"FLAKE8_ISSUE_PRESENT={'true' if issue_present else 'false'}\n")
env_file.write(f"RUN_URL={run_url}\n")
with open(os.environ["GITHUB_STEP_SUMMARY"], "a", encoding="utf-8") as summary:
summary.write("### Python Code Quality Check\n\n")
if issue_present:
summary.write("**Flake8 detected issues. Fix them before merging.**\n\n")
summary.write(f"[Download full report from workflow artifacts]({run_url}).\n")
summary.write("\n_Only Python files changed in this PR were checked._\n")
else:
summary.write("No issues found in changed Python files.\n")
summary.write("\n_This summary is updated with every commit._\n")
EOF
- name: Upload full report
if: env.FLAKE8_ISSUE_PRESENT == 'true'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-code-quality-report
path: flake8_output.txt
- name: Generate PR comment summary
if: always()
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
BLACK_FAILED: ${{ steps.black_check.outputs.black_failed == 'true' }}
FLAKE8_FAILED: ${{ env.FLAKE8_ISSUE_PRESENT == 'true' }}
SKIP: ${{ env.SKIP }}
run: |
python3 <<'EOF'
import json
import os
import pathlib
skip = os.environ.get("SKIP", "")
flake8_failed = os.environ.get("FLAKE8_FAILED") == "true"
flake8_output = pathlib.Path("flake8_output.txt")
flake8_issue_count = 0
if flake8_output.exists():
flake8_issue_count = len(
[
line
for line in flake8_output.read_text(
encoding="utf-8"
).splitlines()
if line.strip()
]
)
summary = {
"schema_version": 1,
"pr_number": int(os.environ["PR_NUMBER"]),
"head_sha": os.environ["HEAD_SHA"],
"workflow_run_id": os.environ["GITHUB_RUN_ID"],
"summary_complete": skip in {"true", "false"},
"black_failed": os.environ.get("BLACK_FAILED") == "true",
"flake8_failed": flake8_failed,
"python_files_checked": skip == "false",
"flake8_issue_count": flake8_issue_count,
}
pathlib.Path("pr-comment-summary.json").write_text(
json.dumps(summary, indent=2, sort_keys=True) + "\n",
encoding="utf-8",
)
EOF
- name: Upload PR comment summary
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-pr-comment
path: pr-comment-summary.json
retention-days: 7
- name: Fail if both black and flake8 failed
if: steps.black_check.outputs.black_failed == 'true' && env.FLAKE8_ISSUE_PRESENT == 'true'
run: |
echo "Python formatting check failed. See formatting.diff artifact for details."
echo "To fix the error(s) run the command below from the root of the repo and commit the changes:"
echo "./.github/scripts/fix-python-formatting.sh"
echo "We also detected Linting Issues in Python files. Please fix them before merging."
echo "Download the full report from here: $RUN_URL"
exit 1
- name: Fail if only black failed
if: steps.black_check.outputs.black_failed == 'true' && env.FLAKE8_ISSUE_PRESENT != 'true'
run: |
echo "Python formatting check failed. See formatting.diff artifact for details."
echo "To fix the error(s) run the command below from the root of the repo and commit the changes:"
echo "./.github/scripts/fix-python-formatting.sh"
exit 1
- name: Fail if only flake8 failed
if: steps.black_check.outputs.black_failed != 'true' && env.FLAKE8_ISSUE_PRESENT == 'true'
run: |
echo "Issues detected in Python files. Please fix them before merging."
echo "Download the full report from here: $RUN_URL"
exit 1