Add pylint, pip caching improvements, and static analysis to GitHub workflow #218
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: Python Tests | |
| on: | |
| workflow_dispatch: | |
| push: | |
| branches: [ main ] | |
| pull_request: | |
| branches: [ main ] | |
| permissions: | |
| contents: read | |
| checks: write | |
| pull-requests: write | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: [ '3.12', '3.13' , '3.14' ] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| cache: pip | |
| cache-dependency-path: requirements.txt | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| - name: Run pylint analysis | |
| id: pylint | |
| continue-on-error: true | |
| run: | | |
| bash tests/python/run_pylint.sh | |
| - name: Upload pylint reports | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: pylint-reports-${{ matrix.python-version }} | |
| path: tests/python/pylint/reports/ | |
| - name: Summarize pylint rating | |
| if: always() | |
| id: pylint_summary | |
| run: | | |
| TEXT_REPORT="tests/python/pylint/reports/latest.txt" | |
| if [ -f "$TEXT_REPORT" ]; then | |
| SCORE=$(grep -Eo 'Your code has been rated at [0-9.]+/10' "$TEXT_REPORT" | tail -n 1) | |
| if [ -z "$SCORE" ]; then | |
| SCORE="Pylint score not available" | |
| fi | |
| echo "score=$SCORE" >> "$GITHUB_OUTPUT" | |
| { | |
| echo 'summary<<EOF' | |
| tail -n 20 "$TEXT_REPORT" | |
| echo EOF | |
| } >> "$GITHUB_OUTPUT" | |
| else | |
| echo "score=Pylint report not found" >> "$GITHUB_OUTPUT" | |
| echo "summary=Pylint text report missing" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Publish Pylint Results to PR | |
| if: always() && github.event_name == 'pull_request' | |
| uses: marocchino/sticky-pull-request-comment@v2 | |
| with: | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| header: pylint-${{ matrix.python-version }} | |
| message: | | |
| ## Python ${{ matrix.python-version }} Pylint Results | |
| *Outcome:* `${{ steps.pylint.outcome }}` | |
| *Score:* `${{ steps.pylint_summary.outputs.score }}` | |
| <details> | |
| <summary>Report tail</summary> | |
| ``` | |
| ${{ steps.pylint_summary.outputs.summary }} | |
| ``` | |
| </details> | |
| 🔗 [Download reports](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) | |
| - name: Verify bytecode compilation | |
| run: | | |
| python -m compileall infrastructure samples setup shared tests | |
| # Run tests with continue-on-error so that coverage and PR comments are always published. | |
| # The final step will explicitly fail the job if any test failed, ensuring PRs cannot be merged with failing tests. | |
| - name: Run pytest with coverage and generate JUnit XML | |
| id: pytest | |
| run: | | |
| PYTHONPATH=$(pwd) COVERAGE_FILE=tests/python/.coverage-${{ matrix.python-version }} pytest --cov=shared/python --cov-config=tests/python/.coveragerc --cov-report=html:tests/python/htmlcov-${{ matrix.python-version }} --junitxml=tests/python/junit-${{ matrix.python-version }}.xml tests/python/ | |
| continue-on-error: true | |
| - name: Upload coverage HTML report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-html-${{ matrix.python-version }} | |
| path: tests/python/htmlcov-${{ matrix.python-version }}/ | |
| - name: Upload JUnit test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| continue-on-error: true | |
| with: | |
| name: junit-results-${{ matrix.python-version }} | |
| path: tests/python/junit-${{ matrix.python-version }}.xml | |
| - name: Publish Unit Test Results to PR | |
| if: always() | |
| uses: EnricoMi/publish-unit-test-result-action@v2 | |
| with: | |
| files: tests/python/junit-${{ matrix.python-version }}.xml | |
| comment_title: Python ${{ matrix.python-version }} Test Results | |
| # Explicitly fail the job if any test failed (so PRs cannot be merged with failing tests). | |
| # This runs after all reporting steps, meaning coverage and PR comments are always published. | |
| - name: Fail if tests failed | |
| if: steps.pytest.outcome == 'failure' | |
| run: | | |
| echo "::error ::Unit tests failed. See above for details." | |
| exit 1 | |
| - name: Fail if pylint failed | |
| if: steps.pylint.outcome == 'failure' | |
| run: | | |
| echo "::error ::Pylint violations detected. See PR comment or artifacts for details." | |
| exit 1 |