CI Pipeline #259
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: CI Pipeline | |
| on: | |
| push: | |
| branches: [master] | |
| pull_request: | |
| branches: [master] | |
| types: [opened, reopened, synchronize, ready_for_review] | |
| schedule: | |
| - cron: '14 3 * * *' # Every day at 03:14 UTC | |
| permissions: {} | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}-${{ github.event_name }} | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| name: Test Workflow - Python ${{ matrix.python-version }} on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 10 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, windows-latest] | |
| python-version: [3.11, 3.12, 3.13] | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: 🐍 Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: 🛠️ Setup UV | |
| uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| enable-cache: false | |
| - name: 📦 Install dependencies | |
| run: make install GROUP=test CI=true VERBOSE=true | |
| - name: 📂 Create coverage directory | |
| run: mkdir coverage | |
| - name: 🏃 Run Tests | |
| run: make coverage CI=true VERBOSE=true | |
| env: | |
| COVERAGE_FILE: coverage/.coverage_${{ matrix.os }}_python_${{ matrix.python-version }} | |
| CONTEXT: ${{ matrix.os }}-python-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }} | |
| - name: 🫙 Store tests coverage | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| if: always() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) | |
| with: | |
| name: coverage_${{ matrix.os }}_python_${{ matrix.python-version }} | |
| path: coverage | |
| include-hidden-files: true | |
| retention-days: 10 | |
| combine-coverage-reports: | |
| name: Combine Coverage Reports Workflow | |
| needs: [test] | |
| if: always() | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 5 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| python-version: [3.13] | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: 🐍 Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: 🛠️ Setup UV | |
| uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| enable-cache: false | |
| - name: 📦 Install dependencies | |
| run: make install GROUP=coverage CI=true VERBOSE=true | |
| - name: 📥 Download coverage files | |
| uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 | |
| with: | |
| merge-multiple: true | |
| pattern: coverage_* | |
| path: coverage | |
| - name: 🏃 Combine coverage files | |
| run: coverage combine coverage/.coverage_* | |
| - name: 📊 Generate coverage report | |
| run: | | |
| coverage report | |
| coverage html --show-contexts --title "Coverage for ${{ github.sha }}" | |
| - name: 🫙 Store coverage HTML report | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| with: | |
| name: coverage-html | |
| path: htmlcov | |
| retention-days: 10 | |
| - name: 🫙 Store coverage data report | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| with: | |
| name: coverage-data | |
| path: .coverage | |
| include-hidden-files: true | |
| retention-days: 10 | |
| publish-coverage-report-commit: | |
| name: Publish Coverage Report Commit Workflow | |
| needs: [combine-coverage-reports] | |
| if: needs.combine-coverage-reports.result == 'success' && github.event_name == 'push' && github.ref == 'refs/heads/master' | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 5 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| python-version: [3.13] | |
| permissions: | |
| contents: read | |
| statuses: write | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: 🐍 Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: 🛠️ Setup UV | |
| uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| enable-cache: false | |
| - name: 📦 Install dependencies | |
| run: make install GROUP=coverage CI=true VERBOSE=true | |
| - name: 📥 Download coverage files | |
| uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 | |
| with: | |
| name: coverage-html | |
| path: htmlcov | |
| - name: 📊 Upload coverage report | |
| run: smokeshow upload htmlcov | |
| env: | |
| SMOKESHOW_GITHUB_STATUS_DESCRIPTION: Coverage {coverage-percentage} | |
| SMOKESHOW_GITHUB_COVERAGE_THRESHOLD: 100 | |
| SMOKESHOW_GITHUB_CONTEXT: coverage | |
| SMOKESHOW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SMOKESHOW_GITHUB_PR_HEAD_SHA: ${{ github.head_sha }} | |
| SMOKESHOW_AUTH_KEY: ${{ secrets.SMOKESHOW_AUTH_KEY }} | |
| publish-coverage-comment-pr: | |
| name: Publish Coverage Report Pull Request Workflow | |
| needs: [combine-coverage-reports] | |
| if: needs.combine-coverage-reports.result == 'success' && github.event_name == 'pull_request' && github.base_ref == 'master' | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 5 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| python-version: [3.13] | |
| permissions: | |
| contents: write | |
| actions: read | |
| pull-requests: write | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| fetch-depth: 1000 | |
| persist-credentials: false | |
| - name: 📥 Download coverage files | |
| uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 | |
| with: | |
| name: coverage-data | |
| - name: 📊 Generate coverage comment | |
| id: coverage-comment | |
| uses: py-cov-action/python-coverage-comment-action@0544a9c648672334d94ec5dd1add7410b4470ddc # v3.37 | |
| with: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| MINIMUM_GREEN: 100 | |
| COMMENT_ARTIFACT_NAME: coverage_comment | |
| COMMENT_FILENAME: coverage_comment.txt | |
| - name: 🫙 Store coverage comment | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| if: steps.coverage-comment.outputs.COMMENT_FILE_WRITTEN == 'true' | |
| with: | |
| name: coverage_comment | |
| path: coverage_comment.txt | |
| format: | |
| name: Format Check Workflow - Python ${{ matrix.python-version }} on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 10 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| python-version: [3.13] | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: 🐍 Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: 🛠️ Setup UV | |
| uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| enable-cache: false | |
| - name: 📦 Install dependencies | |
| run: make install GROUP=format CI=true VERBOSE=true | |
| - name: 🏃 Run Formatter | |
| run: make format CI=true VERBOSE=true | |
| - name: 🧐 Verify no changes | |
| run: | | |
| CHANGES=$(git status --porcelain) | |
| if [[ -n "${CHANGES}" ]]; then | |
| echo "::error file=.github/workflows/ci.yaml,title=Format Check Workflow Failed::Code is not formatted correctly. Please run 'make format' locally and commit the changes." | |
| exit 1 | |
| fi | |
| lint: | |
| name: Lint Workflow - Python ${{ matrix.python-version }} on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 10 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| python-version: [3.13] | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: 🐍 Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: 🛠️ Setup UV | |
| uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| enable-cache: false | |
| - name: 📦 Install dependencies | |
| run: make install GROUP=lint CI=true VERBOSE=true | |
| - name: 🏃 Run Linter | |
| run: make lint CI=true VERBOSE=true | |
| analyze: | |
| name: Code Quality Workflow - ${{ matrix.language }} on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 10 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| language: [python] | |
| build-mode: [none] | |
| permissions: | |
| contents: read | |
| security-events: write | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: ▶️ CodeQL Initialization | |
| uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # v3.29.5 | |
| with: | |
| languages: ${{ matrix.language }} | |
| build-mode: ${{ matrix.build-mode }} | |
| queries: +security-extended,security-and-quality | |
| - name: 🔬 CodeQL Analysis | |
| uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # v3.29.5 | |
| with: | |
| category: '/language:${{ matrix.language }}' | |
| secrets: | |
| name: Secrets Scan Workflow - Python ${{ matrix.python-version }} on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 10 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| python-version: [3.13] | |
| permissions: | |
| contents: read | |
| security-events: write | |
| pull-requests: write | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: 🐍 Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: 🛠️ Setup UV | |
| uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| enable-cache: false | |
| - name: 📦 Install dependencies | |
| run: make install GROUP=develop CI=true VERBOSE=true | |
| - name: 🏃 Run secrets scanner | |
| run: make secrets CI=true VERBOSE=true | |
| audit: | |
| name: Audit Workflow - Python ${{ matrix.python-version }} on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 10 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| python-version: [3.13] | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: 🐍 Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: 🛠️ Setup UV | |
| uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| enable-cache: false | |
| - name: 📦 Install dependencies | |
| run: make install GROUP=audit CI=true VERBOSE=true | |
| - name: 🏃 Run audit | |
| run: make audit CI=true VERBOSE=true | |
| check-all: | |
| name: Check All Workflows Passed Workflow | |
| needs: [test, format, lint, analyze, secrets, audit] | |
| if: always() | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 5 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: ✅ All workflows passed | |
| uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 | |
| with: | |
| jobs: ${{ toJSON(needs) }} | |
| release: | |
| name: Create Tag and GitHub Release Workflow | |
| needs: [check-all] | |
| if: needs.check-all.result == 'success' && github.event_name == 'push' && github.ref == 'refs/heads/master' | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 5 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| outputs: | |
| released: ${{ steps.released.outputs.released }} | |
| tag: ${{ steps.released.outputs.tag }} | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - name: 🔖 Semantic Release | |
| id: released | |
| uses: python-semantic-release/python-semantic-release@6df5e876c8682fe0753ec2f8c81eb45547e52747 # v10.0.2 | |
| with: | |
| build: false | |
| push: true | |
| changelog: true | |
| commit: true | |
| tag: true | |
| vcs_release: true | |
| config_file: pyproject.toml | |
| git_committer_email: ${{ vars.GIT_COMMITTER_EMAIL }} | |
| git_committer_name: ${{ vars.GIT_COMMITTER_NAME }} | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| ssh_public_signing_key: ${{ vars.SSH_PUBLIC_SIGNING_KEY }} | |
| ssh_private_signing_key: ${{ secrets.SSH_PRIVATE_SIGNING_KEY }} | |
| publish: | |
| name: Publish Release to PyPI Workflow | |
| needs: [release] | |
| if: needs.release.result == 'success' && needs.release.outputs.released == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/master' | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 5 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| python-version: [3.13] | |
| permissions: | |
| contents: read | |
| id-token: write | |
| environment: | |
| name: pypi | |
| url: https://pypi.org/p/criteria-pattern/ | |
| steps: | |
| - name: 🛡️ Harden runner | |
| uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 | |
| with: | |
| egress-policy: audit | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| persist-credentials: false | |
| ref: refs/tags/${{ needs.release.outputs.tag }} | |
| - name: 🐍 Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: 🛠️ Setup UV | |
| uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| enable-cache: false | |
| - name: 📦 Install dependencies | |
| run: make install GROUP=release CI=true VERBOSE=true | |
| - name: 🏃🏻➡️ Build distribution | |
| run: make build CI=true VERBOSE=true | |
| - name: 🫙 Store distribution package | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| with: | |
| name: python-package-distributions | |
| path: dist/ | |
| retention-days: 10 | |
| - name: 🚀 Publish | |
| uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 |