.github/workflows/main.yml #4
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: Main | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| workflow_dispatch: | |
| jobs: | |
| quality: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out | |
| uses: actions/checkout@v4 | |
| - uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pre-commit | |
| key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} | |
| - name: Set up the environment | |
| uses: ./.github/actions/setup-python-env | |
| - name: Run checks | |
| run: make check | |
| tests: | |
| runs-on: ${{ matrix.platform }} | |
| strategy: | |
| matrix: | |
| platform: [ubuntu-latest, macos-latest, windows-latest] | |
| # Must track requires-python in pyproject.toml. An entry below the | |
| # floor does not fail: uv ignores it and resolves a compatible | |
| # interpreter instead, so the job reports a false pass. | |
| python-version: ["3.11", "3.12", "3.13", "3.14"] | |
| fail-fast: false | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - name: Check out | |
| uses: actions/checkout@v4 | |
| - name: Set up the environment | |
| uses: ./.github/actions/setup-python-env | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Run tests | |
| run: uv run python -m pytest tests --cov --cov-config=pyproject.toml --cov-report=xml | |
| - name: Check typing | |
| run: uv run ty check | |
| - name: Upload coverage reports to Codecov on Ubuntu / Python 3.12 | |
| uses: codecov/codecov-action@v4 | |
| if: ${{ matrix.platform == 'ubuntu-latest' && matrix.python-version == '3.12' }} | |
| env: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| check-docs: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out | |
| uses: actions/checkout@v4 | |
| - name: Set up the environment | |
| uses: ./.github/actions/setup-python-env | |
| - name: Check if documentation can be built | |
| run: make docs-test | |
| version-preview: | |
| # Show contributors what a merge would release, based on the conventional | |
| # commits on the branch. Pull requests only; informational. | |
| if: github.event_name == 'pull_request' && github.event.pull_request.draft == false | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| steps: | |
| - name: Check out | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # PSR needs full history + tags to compute the bump | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Set up the environment | |
| uses: ./.github/actions/setup-python-env | |
| - name: Compute release preview | |
| id: preview | |
| run: | | |
| # PSR only computes a release on the main branch; name the checked-out | |
| # PR head 'main' so the preview reflects what a merge would release. | |
| git checkout -B main >/dev/null 2>&1 || true | |
| current=$(uv version --short 2>/dev/null || echo "unknown") | |
| next=$(uv run semantic-release version --print 2>/dev/null || echo "") | |
| if [ -n "$next" ] && [ "$next" != "$current" ]; then | |
| echo "released=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "released=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo "current=$current" >> "$GITHUB_OUTPUT" | |
| echo "next=$next" >> "$GITHUB_OUTPUT" | |
| # Stamp the upcoming changelog section locally (no commit/tag/push/build) | |
| # so the preview shows the notes this merge would add. | |
| if [ -n "$next" ] && [ "$next" != "$current" ]; then | |
| uv run semantic-release version --no-commit --no-tag --no-push --no-vcs-release --skip-build >/dev/null 2>&1 || true | |
| fi | |
| { | |
| echo "changelog<<PSR_EOF" | |
| git --no-pager diff HEAD -- CHANGELOG.md | awk '/^\+/ && !/^\+\+\+/ {sub(/^\+/,""); print}' | head -80 | |
| echo "PSR_EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Post release preview comment | |
| uses: marocchino/sticky-pull-request-comment@v2 | |
| with: | |
| header: version-preview | |
| message: | | |
| ## Release preview | |
| ${{ steps.preview.outputs.released == 'true' && format('Merging this PR would release **v{0}** (current: `v{1}`).', steps.preview.outputs.next, steps.preview.outputs.current) || format('No version bump from the current commits (stays at `v{0}`). Use conventional commit types (`feat`, `fix`, ...) to trigger a release.', steps.preview.outputs.current) }} | |
| <details><summary>Changelog preview (truncated)</summary> | |
| ```markdown | |
| ${{ steps.preview.outputs.changelog }} | |
| ``` | |
| </details> | |
| <sub>Preview via python-semantic-release and conventional commits.</sub> | |
| # Continuous benchmarking with Bencher: pytest-benchmark produces the JSON, | |
| # `bencher run` uploads it and comments the comparison against the base | |
| # branch, using statistical boundary models instead of a fixed ratio. | |
| # | |
| # Setup: create a project at https://bencher.dev (free for public repos), | |
| # then add the BENCHER_API_TOKEN secret and set BENCHER_PROJECT below. Until | |
| # the secret exists the benchmarks still run and upload their results as an | |
| # artifact; only the tracking step is skipped. | |
| benchmark: | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' && github.event.pull_request.draft == false | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| env: | |
| BENCHER_PROJECT: awl-python | |
| # The secrets context is not available in a step-level `if`, so the token | |
| # is promoted to an env var here and the steps gate on that instead. | |
| BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }} | |
| steps: | |
| - name: Check out | |
| uses: actions/checkout@v4 | |
| - name: Set up the environment | |
| uses: ./.github/actions/setup-python-env | |
| - name: Run benchmarks | |
| run: make bench | |
| - name: Track benchmarks with Bencher | |
| if: env.BENCHER_API_TOKEN != '' | |
| uses: bencherdev/bencher@main | |
| - name: Upload results to Bencher | |
| if: env.BENCHER_API_TOKEN != '' | |
| run: | | |
| bencher run \ | |
| --project "$BENCHER_PROJECT" \ | |
| --token "$BENCHER_API_TOKEN" \ | |
| --branch "$GITHUB_HEAD_REF" \ | |
| --start-point "$GITHUB_BASE_REF" \ | |
| --start-point-hash "${{ github.event.pull_request.base.sha }}" \ | |
| --start-point-clone-thresholds \ | |
| --start-point-reset \ | |
| --testbed ubuntu-latest \ | |
| --adapter python_pytest \ | |
| --err \ | |
| --github-actions "${{ secrets.GITHUB_TOKEN }}" \ | |
| --file benchmark_results.json | |
| - name: Upload benchmark results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: benchmark-results | |
| path: benchmark_results.json | |
| retention-days: 30 |