chore: PEP 440 compliance, mypy --strict cleanliness, lint/format pass #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
| # Continuous integration for GenoLeWM. | |
| # | |
| # Jobs: | |
| # lint — ruff format check, ruff lint | |
| # types — mypy --strict | |
| # tests — pytest matrix (Python × OS), coverage upload | |
| # gates — custom AST linters + public-API snapshot | |
| # build — package build smoke test (sdist + wheel) | |
| # docs — mkdocs strict build | |
| # ci-required — required-check fan-in | |
| # | |
| # All jobs run on every PR and on pushes to main. The matrix is | |
| # intentionally lean on PRs (Linux only by default; macOS/Windows | |
| # included via matrix.include) and full on main / releases. | |
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ["v*"] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} | |
| env: | |
| PYTHONDONTWRITEBYTECODE: "1" | |
| PYTHONUNBUFFERED: "1" | |
| PIP_DISABLE_PIP_VERSION_CHECK: "1" | |
| FORCE_COLOR: "1" | |
| jobs: | |
| lint: | |
| name: Lint (ruff) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| cache: pip | |
| cache-dependency-path: pyproject.toml | |
| - name: Install | |
| run: python -m pip install -e ".[dev]" | |
| - name: ruff format --check | |
| run: ruff format --check geno_lewm tools tests | |
| - name: ruff check | |
| run: ruff check geno_lewm tools tests --output-format=github | |
| types: | |
| name: Types (mypy --strict) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| cache: pip | |
| cache-dependency-path: pyproject.toml | |
| - name: Install | |
| run: python -m pip install -e ".[dev]" | |
| - name: mypy | |
| run: mypy geno_lewm tools | |
| gates: | |
| name: Contract gates (errors / events / surface / net / print / spdx) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| cache: pip | |
| cache-dependency-path: pyproject.toml | |
| - name: Install | |
| run: python -m pip install -e ".[dev]" | |
| - name: check_error_codes (RFC-0012) | |
| run: python -m tools.lint.check_error_codes | |
| - name: check_event_names (RFC-0013) | |
| run: python -m tools.lint.check_event_names | |
| - name: check_no_print (RFC-0015) | |
| run: python -m tools.lint.check_no_print | |
| - name: check_network_confined (RFC-0010) | |
| run: python -m tools.lint.check_network_confined | |
| - name: check_license_headers (SPDX) | |
| run: python -m tools.lint.check_license_headers | |
| - name: public-API snapshot (RFC-0014) | |
| run: python -m tools.api.snapshot check | |
| tests: | |
| name: Tests (Python ${{ matrix.python }} on ${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| python: ["3.10", "3.11", "3.12", "3.13"] | |
| include: | |
| - os: macos-latest | |
| python: "3.12" | |
| - os: windows-latest | |
| python: "3.12" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python }} | |
| cache: pip | |
| cache-dependency-path: pyproject.toml | |
| - name: Install | |
| run: python -m pip install -e ".[dev]" | |
| - name: pytest | |
| run: pytest --cov=geno_lewm --cov-branch --cov-report=xml --cov-report=term-missing -n auto | |
| - name: Upload coverage to Codecov | |
| if: matrix.os == 'ubuntu-latest' && matrix.python == '3.12' | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| files: ./coverage.xml | |
| fail_ci_if_error: false | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| build: | |
| name: Build (sdist + wheel) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| cache: pip | |
| cache-dependency-path: pyproject.toml | |
| - name: Install build deps | |
| run: python -m pip install build twine | |
| - name: Build | |
| run: python -m build | |
| - name: Twine check | |
| run: twine check dist/* | |
| - name: Smoke install | |
| run: | | |
| python -m pip install dist/*.whl | |
| python -c "import geno_lewm; print(geno_lewm.__version__)" | |
| python -c "from geno_lewm import EditSpec, apply_edit; print(EditSpec(chrom='1', pos=1, ref='A', alt='T'))" | |
| - name: Upload dist artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| retention-days: 14 | |
| docs: | |
| name: Docs (mkdocs --strict) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| cache: pip | |
| cache-dependency-path: pyproject.toml | |
| - name: Install | |
| run: python -m pip install -e ".[docs]" | |
| - name: Build docs (strict) | |
| run: mkdocs build --strict | |
| - name: Upload site artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: docs-site | |
| path: site/ | |
| retention-days: 14 | |
| # Single required check that fans-in all the matrix jobs above. | |
| # Branch protection just needs to require this one. | |
| ci-required: | |
| name: CI required | |
| if: always() | |
| needs: [lint, types, gates, tests, build, docs] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check jobs | |
| if: >- | |
| needs.lint.result != 'success' || | |
| needs.types.result != 'success' || | |
| needs.gates.result != 'success' || | |
| needs.tests.result != 'success' || | |
| needs.build.result != 'success' || | |
| needs.docs.result != 'success' | |
| run: | | |
| echo "One or more required CI jobs failed; see job logs above." | |
| exit 1 | |
| - run: echo "All required CI jobs passed." |