feat: generic_sif_runner proven working #9
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
| # .github/workflows/ci.yml | |
| # | |
| # CI/CD pipeline for omni_tool_runtime | |
| # | |
| # Jobs | |
| # ──── | |
| # lint – ruff check + format | |
| # typecheck – mypy | |
| # test – pytest + coverage (matrix: 3.11, 3.12, 3.13) | |
| # publish – build sdist/wheel, push to PyPI (on version tag push) | |
| # docker – build & push Docker image (on version tag push) | |
| name: CI/CD | |
| on: | |
| push: | |
| branches: ["main", "master"] | |
| tags: ["v*.*.*"] | |
| pull_request: | |
| branches: ["main", "master"] | |
| # Cancel in-flight runs for the same ref so PRs don't queue up | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| # Keeps pip quiet and ensures outputs are unbuffered | |
| PIP_DISABLE_PIP_VERSION_CHECK: "1" | |
| PYTHONUNBUFFERED: "1" | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| # 1. LINT (ruff) | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| jobs: | |
| lint: | |
| name: Lint (ruff) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Cache pip | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: lint-pip-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }} | |
| - name: Install ruff | |
| run: pip install ruff | |
| - name: ruff check (lint) | |
| run: ruff check . | |
| - name: ruff format (check only) | |
| run: ruff format --check . | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| # 2. TYPE-CHECK (mypy) | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| typecheck: | |
| name: Type-check (mypy) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Cache pip | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: mypy-pip-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }} | |
| - name: Install package + mypy | |
| # Install with all extras so mypy can see optional deps (azure, aws) | |
| run: | | |
| pip install -e ".[azure,aws]" | |
| pip install mypy boto3-stubs[s3] azure-storage-blob azure-identity | |
| - name: mypy | |
| run: mypy omni_tool_runtime --ignore-missing-imports | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| # 3. TEST (pytest + coverage matrix) | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| test: | |
| name: Test (Python ${{ matrix.python-version }}) | |
| runs-on: ubuntu-latest | |
| needs: [lint, typecheck] | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.11", "3.12", "3.13"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Cache pip | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: test-pip-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }} | |
| - name: Install package + test deps | |
| run: pip install -e ".[dev]" | |
| - name: Run tests with coverage | |
| run: | | |
| pytest \ | |
| --cov=omni_tool_runtime \ | |
| --cov-report=term-missing \ | |
| --cov-report=xml:coverage.xml \ | |
| --cov-fail-under=85 \ | |
| -v | |
| - name: Upload coverage report | |
| # Only upload once (Python 3.12) to avoid duplicate reports | |
| if: matrix.python-version == '3.12' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report | |
| path: coverage.xml | |
| retention-days: 7 | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| # 4. PUBLISH TO PyPI (only on version tags, e.g. v1.2.3) | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| publish: | |
| name: Publish to PyPI | |
| runs-on: ubuntu-latest | |
| needs: [test] | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| # Trusted publishing — no API token stored in secrets | |
| permissions: | |
| id-token: write # required for OIDC PyPI trusted publishing | |
| contents: read | |
| environment: | |
| name: pypi | |
| url: https://pypi.org/p/omnibioai-tool-runtime | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Install build tools | |
| run: pip install build | |
| - name: Build sdist + wheel | |
| run: python -m build | |
| - name: Verify dist contents | |
| run: ls -lh dist/ | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| # Uses OIDC trusted publishing — configure the PyPI project to trust | |
| # this repo's GitHub Actions environment ("pypi") before first release. | |
| # No PYPI_API_TOKEN secret needed. | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| # 5. DOCKER (only on version tags) | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| docker: | |
| name: Build & Push Docker image | |
| runs-on: ubuntu-latest | |
| needs: [test] | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| permissions: | |
| contents: read | |
| packages: write # required to push to GHCR | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Extract version from tag | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: | | |
| ghcr.io/${{ github.repository }} | |
| tags: | | |
| # tag the image with the git tag (v1.2.3 → 1.2.3) | |
| type=semver,pattern={{version}} | |
| # also push a "latest" tag | |
| type=raw,value=latest | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and push | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| # Layer cache speeds up rebuilds | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max |