11name : Code Quality & Auto-Format Checks
22
3- # Trigger on push to main/master or PRs targeting these branches
43on :
54 push :
65 branches : [ main, master ]
76 pull_request :
87 branches : [ main, master ]
98
10- # Shared environment variables (avoid duplicate hardcoding)
119env :
1210 PYTHON_VERSION : ' 3.13.7'
1311
1412jobs :
15- # Phase 1: Auto-format with ruff (runs first, controls downstream jobs )
13+ # Phase 1: Ruff Auto-Format (no dependency file references )
1614 ruff-auto-format :
17- name : " 📝 Ruff Auto-Format (With Auto-Commit) "
15+ name : " 📝 Ruff Auto-Format"
1816 runs-on : ubuntu-latest
19- # Grant write permission for auto-commit (critical for push)
2017 permissions :
21- contents : write # Allows workflow to push formatting changes
22- pull-requests : read # Optional: Reads PR info for branch targeting
18+ contents : write # For auto-commit
19+ pull-requests : read
2320 outputs :
24- changes_made : ${{ steps.format-check.outputs.changes_made }} # Track if formatting changes were applied
21+ changes_made : ${{ steps.format-check.outputs.changes_made }}
2522 steps :
26- - name : Set up Python ${{ env.PYTHON_VERSION }}
23+ - name : Checkout repository (critical for file access)
24+ uses : actions/checkout@v4
25+ with :
26+ token : ${{ secrets.GITHUB_TOKEN }}
27+ fetch-depth : 0
28+ ref : ${{ github.head_ref || github.ref }}
29+ path : . # Ensure repo is in default working dir
30+
31+ - name : Set up Python (no cache based on dependency files)
2732 uses : actions/setup-python@v4
2833 with :
2934 python-version : ${{ env.PYTHON_VERSION }}
30- cache : ' pip' # Cache dependencies to speed up installs
35+ # Removed `cache-dependency-path` (no requirements/pyproject to reference)
36+ cache : ' pip' # Still caches pip packages (e.g., ruff) for speed
3137
32- - name : Install ruff (code formatter )
38+ - name : Install ruff (direct install, no dependency files )
3339 run : pip install ruff
3440 env :
35- PIP_DISABLE_PIP_VERSION_CHECK : 1 # Skip pip version check for faster installs
41+ PIP_DISABLE_PIP_VERSION_CHECK : 1
3642
37- - name : Run ruff format & detect changes
43+ - name : Run ruff format & check changes
3844 id : format-check
3945 run : |
40- echo "Running ruff format to fix code styling..."
41- ruff format . # Apply formatting fixes
42-
43- # Check if any files were modified (avoids empty commits)
46+ ruff format .
4447 if git diff --quiet --exit-code; then
4548 echo "changes_made=false" >> $GITHUB_OUTPUT
46- echo "✅ No formatting issues found. No commit needed."
4749 else
4850 echo "changes_made=true" >> $GITHUB_OUTPUT
49- echo "🔄 Formatting changes detected in these files:"
50- git diff --name-only # List modified files for debugging
5151 fi
5252
5353 - name : Auto-commit & push formatting changes
5454 if : steps.format-check.outputs.changes_made == 'true'
5555 run : |
56- # Configure Git committer info (required for commits)
57- git config --local user.name "GitHub Actions (Ruff Format)"
58- git config --local user.email "actions-ruff-format@github.com"
59-
60- # Commit and push changes
61- git add .
62- git commit -m "[auto] style: Fix code formatting with ruff" # Clear commit message
63- git push
64- echo "✅ Formatting changes pushed successfully."
65-
66- # Phase 2: Install check tools (runs only after valid ruff-format triggers)
56+ git config --local user.name "GitHub Actions"
57+ git config --local user.email "actions@github.com"
58+ git add . && git commit -m "[auto] Fix code format with ruff" && git push
59+
60+ # Phase 2: Setup Check Tools (no dependency file checks)
6761 setup-check-tools :
68- name : " ⚙️ Setup Code Check Tools"
69- needs : ruff-auto-format # Depends on ruff-format completion
70- # Trigger conditions:
71- # - Run on direct pushes to main/master
72- # - Run on PRs only if: 1) ruff made changes, OR 2) PR was merged
62+ name : " ⚙️ Setup Check Tools"
63+ needs : ruff-auto-format
7364 if : >
7465 (github.event_name == 'push') ||
75- (github.event_name == ' pull_request' &&
66+ (github.event. pull_request &&
7667 (needs.ruff-auto-format.outputs.changes_made == 'true' ||
7768 github.event.pull_request.merged == true))
7869 runs-on : ubuntu-latest
7970 steps :
80- - name : Checkout repository code
71+ - name : Checkout repository
8172 uses : actions/checkout@v4
73+ with :
74+ path : .
75+ fetch-depth : 1
8276
83- - name : Set up Python ${{ env.PYTHON_VERSION }}
77+ - name : Set up Python (no dependency file cache)
8478 uses : actions/setup-python@v4
8579 with :
8680 python-version : ${{ env.PYTHON_VERSION }}
87- cache : ' pip' # Reuse cache from ruff-format job
81+ cache : ' pip' # Caches tools (codespell/bandit) for downstream jobs
8882
89- - name : Install all code check tools
83+ - name : Install check tools (direct install, no dependency files)
9084 run : |
9185 pip install codespell bandit mypy ruff pytest
9286 env :
9387 PIP_DISABLE_PIP_VERSION_CHECK : 1
9488
95- # Non-blocking check: Spell check (fails won't stop workflow)
89+ # --- Non-blocking Checks (no dependency file references) ---
9690 spell-check :
9791 name : " 🔍 Spell Check (Non-Blocking)"
9892 needs : setup-check-tools
9993 runs-on : ubuntu-latest
10094 steps :
101- - name : Checkout repository code
95+ - name : Checkout repository
10296 uses : actions/checkout@v4
103-
104- - name : Set up Python ${{ env.PYTHON_VERSION }}
97+ with :
98+ path : .
99+ - name : Set up Python
105100 uses : actions/setup-python@v4
106101 with :
107102 python-version : ${{ env.PYTHON_VERSION }}
108103 cache : ' pip'
104+ - name : Run codespell
105+ run : codespell --skip="*.json,*.lock,*.csv" --ignore-words-list="xxx,yyy,zzz" --quiet-level=2 || true
109106
110- - name : Run codespell (ignore common false positives)
111- run : |
112- codespell \
113- --skip="*.json,*.lock,*.csv" \ # Skip non-code files
114- --ignore-words-list="xxx,yyy,zzz" \ # Ignore custom false positives
115- --quiet-level=2 || true # Non-blocking: continue if errors exist
116-
117- # Non-blocking check: Security scan (fails won't stop workflow)
118107 security-scan :
119108 name : " 🔒 Security Scan (Non-Blocking)"
120109 needs : setup-check-tools
121110 runs-on : ubuntu-latest
122111 steps :
123- - name : Checkout repository code
112+ - name : Checkout repository
124113 uses : actions/checkout@v4
125-
126- - name : Set up Python ${{ env.PYTHON_VERSION }}
114+ with :
115+ path : .
116+ - name : Set up Python
127117 uses : actions/setup-python@v4
128118 with :
129119 python-version : ${{ env.PYTHON_VERSION }}
130120 cache : ' pip'
121+ - name : Run bandit
122+ run : bandit -r . -f human -o bandit-results.txt -f json -o bandit-results.json || true
131123
132- - name : Run bandit (security linter for Python)
133- run : |
134- bandit \
135- -r . \ # Scan all Python files recursively
136- -f human -o bandit-results.txt \ # Human-readable report
137- -f json -o bandit-results.json || true # JSON report (for tools) + non-blocking
138-
139- # Non-blocking check: Type check (fails won't stop workflow)
140124 type-check :
141125 name : " 🎯 Type Check (Non-Blocking)"
142126 needs : setup-check-tools
143127 runs-on : ubuntu-latest
144128 steps :
145- - name : Checkout repository code
129+ - name : Checkout repository
146130 uses : actions/checkout@v4
147-
148- - name : Set up Python ${{ env.PYTHON_VERSION }}
131+ with :
132+ path : .
133+ - name : Set up Python
149134 uses : actions/setup-python@v4
150135 with :
151136 python-version : ${{ env.PYTHON_VERSION }}
152137 cache : ' pip'
138+ - name : Run mypy
139+ run : mypy --ignore-missing-imports --show-error-codes . || true
153140
154- - name : Run mypy (static type checker)
155- run : |
156- mypy \
157- --ignore-missing-imports \ # Ignore unresolved imports (e.g., third-party libs)
158- --show-error-codes . || true # Show error codes for debugging + non-blocking
159-
160- # Blocking check: Lint check (fails stop workflow)
141+ # --- Blocking Checks ---
161142 lint-check :
162143 name : " 🧹 Lint Check (Blocking)"
163144 needs : setup-check-tools
164145 runs-on : ubuntu-latest
165146 steps :
166- - name : Checkout repository code
147+ - name : Checkout repository
167148 uses : actions/checkout@v4
168-
169- - name : Set up Python ${{ env.PYTHON_VERSION }}
149+ with :
150+ path : .
151+ - name : Set up Python
170152 uses : actions/setup-python@v4
171153 with :
172154 python-version : ${{ env.PYTHON_VERSION }}
173155 cache : ' pip'
156+ - name : Run ruff check
157+ run : ruff check --output-format=concise .
174158
175- - name : Run ruff check (code linter)
176- run : ruff check --output-format=concise . # Blocking: fails on lint errors
177-
178- # Blocking check: Unit tests (fails stop workflow)
179- unit-tests :
159+ unit-tests :
180160 name : " 🧪 Unit Tests (Blocking)"
181161 needs : setup-check-tools
182162 runs-on : ubuntu-latest
183163 steps :
184- - name : Checkout repository code
164+ - name : Checkout repository
185165 uses : actions/checkout@v4
186-
187- - name : Set up Python ${{ env.PYTHON_VERSION }}
166+ with :
167+ path : .
168+ - name : Set up Python
188169 uses : actions/setup-python@v4
189170 with :
190171 python-version : ${{ env.PYTHON_VERSION }}
191172 cache : ' pip'
173+ - name : Run pytest
174+ run : pytest # Adjust test command if your tests are in a subfolder (e.g., pytest tests/)
192175
193- - name : Run pytest (unit test framework)
194- run : pytest # Blocking: fails on test failures
195-
196- # Security analysis: CodeQL (for vulnerability detection)
176+ # --- CodeQL Analysis ---
197177 codeql-analysis :
198178 name : " 🛡️ CodeQL Security Analysis"
199- needs : setup-check-tools # Controlled by ruff-format pre-condition
179+ needs : setup-check-tools
200180 runs-on : ubuntu-latest
201181 permissions :
202182 actions : read
203183 contents : read
204- security-events : write # Required to upload CodeQL results
184+ security-events : write
205185 steps :
206- - name : Checkout repository code
186+ - name : Checkout repository
207187 uses : actions/checkout@v4
208-
188+ with :
189+ path : .
209190 - name : Initialize CodeQL
210191 uses : github/codeql-action/init@v2
211192 with :
212- languages : python # Analyze Python code
213-
214- - name : Autobuild (auto-configure build for CodeQL)
193+ languages : python
194+ - name : Autobuild
215195 uses : github/codeql-action/autobuild@v2
216-
217- - name : Run CodeQL analysis
196+ - name : Perform CodeQL Analysis
218197 uses : github/codeql-action/analyze@v2
219- with :
220- output : sarif-results/ # Export results for debugging
221198
222- # Final summary: Verify all checks completed
199+ # --- Final Summary ---
223200 all-checks-summary :
224201 name : " ✅ All Checks Summary"
225202 needs : [spell-check, security-scan, type-check, lint-check, unit-tests, codeql-analysis]
226- if : always() # Run even if some checks fail
203+ if : always()
227204 runs-on : ubuntu-latest
228205 steps :
229- - name : Print workflow summary
206+ - name : Print summary
230207 run : |
231- echo "==================== Workflow Summary ===================="
232- echo "Ruff auto-format made changes: ${{ needs.ruff-auto-format.outputs.changes_made }}"
233- echo "---------------------------------------------------------"
234-
235- # Check for blocking failures (lint/tests/CodeQL)
236- if [[ "${{ contains(needs.lint-check.result, 'failure') || contains(needs.unit-tests.result, 'failure') || contains(needs.codeql-analysis.result, 'failure') }}" == "true" ]]; then
237- echo "❌ Critical failure detected (lint/tests/CodeQL). Fix required."
238- exit 1 # Block workflow on critical failures
208+ echo "Ruff auto-format changes: ${{ needs.ruff-auto-format.outputs.changes_made }}"
209+ if [[ "${{ contains(needs.lint-check.result, 'failure') || contains(needs.unit-tests.result, 'failure') }}" == "true" ]]; then
210+ echo "❌ Critical failure (lint/tests) - Fix required"
211+ exit 1
239212 else
240- echo "✅ No critical failures. Non-blocking issues (spelling/type) may exist. "
213+ echo "✅ No critical failures"
241214 fi
242-
0 commit comments