chore(release): prepare axiam-python-sdk 1.0.0-alpha21 #43
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: SDK CI — Python | |
| on: | |
| pull_request: | |
| branches: [main] | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: read | |
| jobs: | |
| scaffold-check: | |
| name: SDK Scaffold Check | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Verify LICENSE file | |
| run: test -f LICENSE | |
| test: | |
| name: Test (Python ${{ matrix.python-version }}) | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # D-18: CI test matrix = Python 3.10/3.11/3.12/3.13 on ubuntu-latest. | |
| python-version: ['3.10', '3.11', '3.12', '3.13'] | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install dependencies (incl. fastapi/django/dev extras) | |
| run: pip install -e '.[dev,fastapi,django]' | |
| - name: Test | |
| run: pytest tests -v | |
| - name: Dependency vulnerability scan (CI-03) | |
| run: | | |
| # Patch the build tooling before auditing: Python 3.10/3.11 ship an | |
| # older setuptools (79.0.1, flagged by PYSEC-2026-3447, fixed in | |
| # 83.0.0) and pip. Upgrading resolves those findings rather than | |
| # suppressing them; the SDK's own runtime deps are audited as-is. | |
| pip install --upgrade pip 'setuptools>=83.0.0' | |
| pip install pip-audit | |
| pip-audit --skip-editable --desc | |
| - name: Byte-compile examples (D-13) | |
| run: python -m py_compile examples/*.py | |
| tls-bypass-gate: | |
| name: TLS-bypass gate (SC#3) | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| # §6 / SC#3: strict TLS is always on (verify=True hardcoded); the only | |
| # escape hatch is an explicit custom_ca parameter — there must be no | |
| # insecure/skip-verification surface anywhere in the SDK's own source | |
| # tree, including examples and tests. Extended beyond the literal | |
| # verify=False string to ssl._create_unverified_context and verify=0 | |
| # (falsy-but-not-literal-False) per CF-03's "no TLS-bypass idiom | |
| # appears anywhere" requirement. | |
| - name: TLS-bypass gate — no TLS-bypass patterns (SC#3) | |
| run: | | |
| if grep -rnE 'verify\s*=\s*(False|0)|ssl\._create_unverified_context' \ | |
| src examples tests 2>/dev/null | grep -q .; then | |
| echo "FAIL: found a TLS-bypass pattern in the SDK source tree" | |
| grep -rnE 'verify\s*=\s*(False|0)|ssl\._create_unverified_context' \ | |
| src examples tests || true | |
| exit 1 | |
| fi | |
| echo "OK: no TLS-bypass patterns found" | |
| grpc-drift-check: | |
| name: gRPC stub drift-check (D-04) | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up Python | |
| uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: '3.12' | |
| # D-04 / Pitfall 5: Python does not use buf. Codegen is | |
| # `python -m grpc_tools.protoc` (via scripts/gen_grpc.sh) for BOTH local | |
| # and CI, run against this repo's own vendored proto/axiam/v1. | |
| - name: Install grpcio-tools (matches the pinned grpcio runtime) | |
| run: pip install 'grpcio-tools==1.78.*' | |
| - name: Regenerate gRPC stubs | |
| run: bash scripts/gen_grpc.sh | |
| - name: Fail on drift — committed stubs must match protos (D-04) | |
| run: git diff --exit-code src/axiam_sdk/grpc/gen | |
| lint: | |
| name: Lint (mypy --strict + ruff + interrogate) (D-20) | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up Python | |
| uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: '3.12' | |
| - name: Install dependencies (incl. fastapi/django/dev extras) | |
| run: pip install -e '.[dev,fastapi,django]' | |
| - name: mypy --strict | |
| run: mypy --strict src | |
| - name: ruff check | |
| run: ruff check . | |
| - name: ruff format --check | |
| run: ruff format --check . | |
| # Docstring-coverage gate on the public API surface (pdoc-published): | |
| # config (fail-under = 100, the generated grpc/gen/* stub exclusion) | |
| # lives in [tool.interrogate] in pyproject.toml, mirroring the | |
| # generated-stub exemptions already documented there for ruff/mypy. | |
| - name: interrogate (docstring coverage) | |
| run: interrogate -c pyproject.toml src/axiam_sdk | |
| build-check: | |
| name: Build + twine check (SC#5) | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up Python | |
| uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: '3.12' | |
| - name: Install build + twine | |
| run: pip install build twine | |
| - name: Build sdist + wheel (SC#5) | |
| run: python -m build | |
| - name: twine check (SC#5) | |
| run: twine check dist/* | |
| # Publishing to PyPI is IRREVERSIBLE — a version number can never be reused. | |
| # Git tags are NOT branch-scoped, so without this gate a release tag cut on a | |
| # feature branch would ship unreviewed code to the world under a version that | |
| # can never be reclaimed. The publish job below `needs:` this. | |
| verify-tag-on-main: | |
| name: Verify tag is on main | |
| if: github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Assert the tagged commit is an ancestor of origin/main | |
| run: | | |
| set -euo pipefail | |
| git fetch --no-tags origin main | |
| if ! git merge-base --is-ancestor "${GITHUB_SHA}" origin/main; then | |
| echo "::error::Tag ${GITHUB_REF_NAME} points at ${GITHUB_SHA}, which is NOT on origin/main. Release tags must be cut from main." | |
| exit 1 | |
| fi | |
| echo "OK: ${GITHUB_REF_NAME} (${GITHUB_SHA}) is on origin/main." | |
| publish: | |
| name: Publish to PyPI | |
| # Manual-on-tag, side-effecting step: this job only runs when a maintainer | |
| # pushes a plain vX.Y.Z tag on this standalone SDK repo. It is never | |
| # triggered by a PR, so no publish-adjacent OIDC token is ever exposed to a | |
| # PR-triggered job. | |
| if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') | |
| needs: verify-tag-on-main | |
| runs-on: ubuntu-latest | |
| environment: pypi | |
| permissions: | |
| contents: read | |
| # Required for PyPI Trusted Publishing (OIDC) — no stored API token | |
| # (D-05). The Trusted Publisher registered on PyPI must name THIS repo | |
| # (ilpanich/axiam-python-sdk), this workflow file (sdk-ci-python.yml) and | |
| # the `pypi` environment, or the token exchange is rejected. | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up Python | |
| uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: '3.12' | |
| # D-04: the committed gRPC stubs must be up to date before a release | |
| # tag is trusted — same drift-check as the PR gate, run again here as | |
| # a belt-and-suspenders confirm on the tagged commit. | |
| - name: Install grpcio-tools (matches the pinned grpcio runtime) | |
| run: pip install 'grpcio-tools==1.78.*' | |
| - name: Regenerate gRPC stubs | |
| run: bash scripts/gen_grpc.sh | |
| - name: Fail on drift — committed stubs must match protos (D-04) | |
| run: git diff --exit-code src/axiam_sdk/grpc/gen | |
| - name: Install build + twine | |
| run: pip install build twine | |
| - name: Build sdist + wheel (SC#5) | |
| run: python -m build | |
| - name: twine check (SC#5) | |
| run: twine check dist/* | |
| # PyPI Trusted Publishing (OIDC, D-05) — no password/token input; the | |
| # id-token: write permission above is what authorizes the exchange. | |
| - name: Publish to PyPI (Trusted Publishing) | |
| uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1 | |
| with: | |
| packages-dir: dist |