fix test #128
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Mandatory PR Code Quality Checks | ||
# Force trigger for ALL PR events + retain push (for post-merge validation) | ||
on: | ||
push: | ||
branches: [ main, master ] # Only for merged PR validation | ||
pull_request: | ||
branches: [ main, master ] | ||
types: [ opened, synchronize, reopened, edited ] # Trigger on ANY PR change | ||
env: | ||
PYTHON_VERSION: '3.13.7' | ||
jobs: | ||
# 1. Mandatory PR Step: Ruff Auto-Format (pushes back to PR source branch) | ||
pr-ruff-auto-format: | ||
name: "📝 PR: Ruff Auto-Format" | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write # Critical for pushing format fixes to PR | ||
pull-requests: write # Required to update PR status | ||
outputs: | ||
changes_made: ${{ steps.format-check.outputs.changes_made }} | ||
steps: | ||
- name: Checkout PR SOURCE BRANCH (MANDATORY FOR PR) | ||
uses: actions/checkout@v4 | ||
with: | ||
token: ${{ secrets.PR_ACCESS_PAT || secrets.GITHUB_TOKEN }} # Use PAT for forked PRs | ||
fetch-depth: 0 | ||
ref: ${{ github.head_ref }} # MUST target PR source (not main) | ||
path: . | ||
- name: Set up Python | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: ${{ env.PYTHON_VERSION }} | ||
cache: 'pip' | ||
- name: Install ruff | ||
run: pip install ruff | ||
env: | ||
PIP_DISABLE_PIP_VERSION_CHECK: 1 | ||
- name: Run format & detect changes | ||
id: format-check | ||
run: | | ||
ruff format . | ||
if git diff --quiet --exit-code; then | ||
echo "changes_made=false" >> $GITHUB_OUTPUT | ||
else | ||
echo "changes_made=true" >> $GITHUB_OUTPUT | ||
git diff --name-only >> pr_format_changes.txt # Log changes for PR review | ||
fi | ||
- name: Push fixes to PR source branch | ||
if: steps.format-check.outputs.changes_made == 'true' | ||
run: | | ||
git config --local user.name "GitHub Actions (PR Bot)" | ||
git config --local user.email "[email protected]" | ||
git add . | ||
git commit -m "[PR AUTO-FIX] Code formatting via ruff" | ||
git push # Updates PR automatically—no manual push needed | ||
- name: Comment format changes on PR (MANDATORY VISIBILITY) | ||
if: steps.format-check.outputs.changes_made == 'true' && github.event_name == 'pull_request' | ||
uses: actions/github-script@v7 | ||
with: | ||
script: | | ||
const changes = require('fs').readFileSync('pr_format_changes.txt', 'utf8'); | ||
github.rest.issues.createComment({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
issue_number: context.issue.number, | ||
body: `🔄 Auto-formatting changes applied to these files:\n\`\`\`\n${changes}\n\`\`\`` | ||
}); | ||
# 2. Mandatory PR Step: Setup tools (ONLY runs for PRs) | ||
pr-setup-tools: | ||
name: "⚙️ PR: Setup Check Tools" | ||
needs: pr-ruff-auto-format | ||
if: github.event_name == 'pull_request' # MANDATORY: Only execute for PRs | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout PR source branch | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.head_ref }} | ||
path: . | ||
- name: Set up Python | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: ${{ env.PYTHON_VERSION }} | ||
cache: 'pip' | ||
- name: Install PR check tools | ||
run: pip install codespell bandit mypy ruff pytest | ||
env: | ||
PIP_DISABLE_PIP_VERSION_CHECK: 1 | ||
# 3. Mandatory PR Checks (all sync to PR "Checks" tab) | ||
pr-spell-check: | ||
name: "🔍 PR: Spell Check (Non-Blocking)" | ||
needs: pr-setup-tools | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout PR source branch | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.head_ref }} | ||
path: . | ||
- name: Run codespell | ||
run: codespell --skip="*.json,*.lock,*.csv" --ignore-words-list="xxx,yyy,zzz" --quiet-level=2 || true | ||
pr-security-check: | ||
name: "🔒 PR: Security Check (Non-Blocking)" | ||
needs: pr-setup-tools | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout PR source branch | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.head_ref }} | ||
path: . | ||
- name: Run bandit | ||
run: bandit -r . -f human -o pr_bandit_results.txt -f json -o pr_bandit_results.json || true | ||
pr-security-check: | ||
name: "🔒 PR: Security Check (Non-Blocking)" | ||
needs: pr-setup-tools | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout PR source branch | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.head_ref }} | ||
path: . | ||
- name: Run bandit | ||
run: bandit -r . -f human -o pr_bandit_results.txt -f json -o pr_bandit_results.json || true | ||
pr-type-check: | ||
name: "🎯 PR: Type Check (Non-Blocking)" | ||
needs: pr-setup-tools | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout PR source branch | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.head_ref }} | ||
path: . | ||
- name: Run mypy | ||
run: mypy --ignore-missing-imports --show-error-codes . || true | ||
pr-lint-check: | ||
name: "🧹 PR: Lint Check (BLOCKING)" | ||
needs: pr-setup-tools | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout PR source branch | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.head_ref }} | ||
path: . | ||
- name: Run ruff check | ||
run: ruff check --output-format=concise . # Fails PR if lint errors exist | ||
pr-unit-tests: | ||
name: "🧪 PR: Unit Tests (BLOCKING)" | ||
needs: pr-setup-tools | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout PR source branch | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.head_ref }} | ||
path: . | ||
- name: Run pytest | ||
run: pytest # Fails PR if test failures exist | ||
# 4. Mandatory PR Security: CodeQL (syncs to PR "Security" tab) | ||
pr-codeql: | ||
name: "🛡️ PR: CodeQL Analysis" | ||
needs: pr-setup-tools | ||
runs-on: ubuntu-latest | ||
permissions: | ||
actions: read | ||
contents: read | ||
security-events: write # Mandatory for PR security alerts | ||
steps: | ||
- name: Checkout PR source branch | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.head_ref }} | ||
path: . | ||
- name: Initialize CodeQL | ||
uses: github/codeql-action/init@v2 | ||
with: | ||
languages: python | ||
- name: Autobuild | ||
uses: github/codeql-action/autobuild@v2 | ||
- name: Analyze | ||
uses: github/codeql-action/analyze@v2 | ||
# 5. Mandatory PR Step: Block invalid merges | ||
pr-merge-gate: | ||
name: "🚫 PR: Merge Gate (MANDATORY)" | ||
needs: [pr-spell-check, pr-security-check, pr-type-check, pr-lint-check, pr-unit-tests, pr-codeql] | ||
if: github.event_name == 'pull_request' | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Check PR validity | ||
run: | | ||
# Block merge if ANY blocking check fails | ||
if [[ "${{ contains(needs.pr-lint-check.result, 'failure') || contains(needs.pr-unit-tests.result, 'failure') || contains(needs.pr-codeql.result, 'failure') }}" == "true" ]]; then | ||
echo "❌ PR CANNOT be merged: Blocking checks (lint/tests/CodeQL) failed." | ||
exit 1 | ||
else | ||
echo "✅ PR is merge-ready: All blocking checks passed." | ||
fi |