Skip to content

ci: add and harden SDK release workflows - #8

Merged
calvin-archastro merged 2 commits into
mainfrom
ci/publish-release-regen-workflows
Jun 11, 2026
Merged

ci: add and harden SDK release workflows#8
calvin-archastro merged 2 commits into
mainfrom
ci/publish-release-regen-workflows

Conversation

@calvin-archastro

@calvin-archastro calvin-archastro commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

What changed

This updates the Python SDK CI, release, publish, and regeneration workflows so they use locked dependency inputs instead of floating installs:

  • Pins GitHub Actions by commit SHA and gives CI read-only repository permissions.
  • Expands CI to Python 3.11, 3.12, and 3.13.
  • Uses npm ci --ignore-scripts plus npm audit --audit-level=moderate for Node tooling.
  • Locks @archastro/sdk-generator in package-lock.json and removes the manual @latest generator input.
  • Runs SDK regeneration from the local locked generator binary instead of npx.
  • Runs contract tests against the local locked Prism binary instead of npx.
  • Pins uv to 0.11.3 with the release checksum in every workflow.
  • Uses uv sync --locked --all-extras and builds with uv build --no-build-isolation.
  • Adds locked build-backend dependencies to uv.lock and smoke-tests the built wheel with hash-enforced runtime requirements.
  • Updates README publish/regeneration instructions to match the locked workflow path.

Diagrams

sequenceDiagram
  participant Dev as Developer
  participant GH as GitHub Actions
  participant NPM as npm registry
  participant UV as uv resolver
  participant Tests as SDK tests
  participant PyPI as PyPI
  Dev->>GH: push PR branch
  GH->>NPM: npm ci with scripts disabled
  GH->>NPM: npm audit moderate gate
  GH->>UV: install pinned uv with checksum
  GH->>UV: uv sync locked
  GH->>Tests: run lint unit harness contract
  GH->>UV: build with no isolation
  GH->>UV: export locked runtime requirements
  GH->>Tests: install hashes then local wheel no deps
  alt release tag
    GH->>PyPI: publish prebuilt dist by trusted publisher
  else regenerate SDK
    GH->>Tests: run locked local sdk generator
  end
Loading
classDiagram
  class CIWorkflow {
    String python_matrix_3_11_3_12_3_13
    String permissions_contents_read
    String npm_ci_ignore_scripts
    String npm_audit_moderate
    String uv_sync_locked
    String wheel_smoke_hashes
  }
  class ReleaseWorkflow {
    String npm_ci_ignore_scripts
    String npm_audit_moderate
    String uv_sync_locked
    String wheel_smoke_hashes
  }
  class RegenerateWorkflow {
    String npm_ci_ignore_scripts
    String local_sdk_generator
    String package_lock_version
  }
  class PublishWorkflow {
    String uv_sync_locked
    String build_no_isolation
    String trusted_publisher
  }
  class PackageLocks {
    String package_lock_json
    String uv_lock
    String hatchling_locked
    String sdk_generator_locked
  }
  CIWorkflow --> PackageLocks : uses
  ReleaseWorkflow --> PackageLocks : uses
  RegenerateWorkflow --> PackageLocks : uses
  PublishWorkflow --> PackageLocks : uses
Loading

Scope indicator

CI/tooling-only for the Python SDK repository. There are no intended runtime SDK API changes; the only test-code change is how the contract harness locates its locked local Prism binary.

Risk assessment

Low to medium. The production SDK runtime is not intentionally changed, but release, publish, and regeneration paths are stricter now. The main risk is a workflow environment mismatch or a future generated overwrite of the local Prism launcher change. Local verification covered the workflow commands, lockfile behavior, contract tests, and wheel install path.

User impact

SDK users should see no API or behavior change. Maintainers get reproducible CI, safer release and regeneration jobs, and less exposure to supply-chain drift from floating Node or Python build inputs.

Testing

  • npm ci --ignore-scripts
  • npm audit --audit-level=moderate
  • uv sync --locked --all-extras
  • uv run ruff check
  • uv run ruff format --check
  • uv run pytest tests/test_http_client.py src/archastro/phx_channel/tests/test_unit.py
  • uv run pytest tests/harness
  • ARCHASTRO_RUN_CHANNEL_CONTRACT_TESTS=1 uv run pytest tests/contract
  • Python 3.11 focused unit run with UV_PROJECT_ENVIRONMENT=/tmp/archastro-python-venv-311-supplychain
  • Python 3.12 focused unit run with UV_PROJECT_ENVIRONMENT=/tmp/archastro-python-venv-312-supplychain
  • uv build --no-build-isolation
  • uv export --locked --no-dev --no-emit-project --format requirements.txt --output-file dist/runtime-requirements.txt
  • uv pip install --python .wheel-smoke --require-hashes -r dist/runtime-requirements.txt
  • uv pip install --python .wheel-smoke --no-deps dist/*.whl
  • .wheel-smoke/bin/python -c "import archastro.platform; import archastro.phx_channel"
  • Negative hash test confirmed uv pip install --require-hashes rejects a tampered requirement hash.
  • Workflow YAML parse check for all modified workflows.
  • git diff --check --cached

Follow-ups and known issues

  • tests/contract/conftest.py is generated. The local Prism binary behavior should be upstreamed into @archastro/sdk-generator so future SDK regeneration preserves it.
  • GitHub Actions should still validate this on the hosted Ubuntu runners after push.

Mirrors the three CI/CD workflows the archastro-js repo uses, adapted
for the single-package Python SDK and PyPI Trusted Publishing.

publish.yml — fires on `v*` tag pushes (and is reachable via
workflow_dispatch so release.yml can re-trigger after pushing the tag,
since GITHUB_TOKEN-pushed tags don't fire workflow runs themselves).
Authenticates to PyPI via OIDC — no API token required after the
first manual publish + Trusted Publisher configured at
pypi.org/manage/project/archastro-sdk/. Uses pypa/gh-action-pypi-publish
(commit-pinned), validates that the tag matches `pyproject.toml`'s
`[project].version`, creates a matching GitHub Release.

release.yml — manual workflow_dispatch with a bump knob
(patch/minor/major). Runs the same lint + unit + harness + contract
suites as ci.yml on Python 3.12 (single matrix entry to keep the
release gate fast), bumps the version with `uv version --bump`, pushes
the bump on a `release/v$VERSION` branch, tags `v$VERSION`, dispatches
publish.yml against the tag, then opens + squash-merges a PR back into
main so the bump lands.

regenerate-sdk.yml — manual workflow_dispatch with two knobs
(openapi_ref, generator_spec). Runs `./scripts/regenerate_sdk.sh` with
`uv` installed up-front because the script invokes `uv run ruff ...`
to normalize generated output. Detects diffs in src/, tests/, and
specs/. Force-pushes to the stable `auto/regenerate-sdk` branch and
either opens or updates a PR — the PR's own CI is what runs build +
tests, so this workflow stays narrowly scoped to "produce the diff".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@archastro

archastro Bot commented Apr 27, 2026

Copy link
Copy Markdown

Reviewed b4c5335. No findings.


Reply @archastro <verb>: review · do <pattern> · don't <pattern> · forget <slug> · list

@calvin-archastro calvin-archastro changed the title ci: add publish + release + regenerate-sdk workflows ci: add and harden SDK release workflows Jun 11, 2026
@calvin-archastro
calvin-archastro merged commit 8ad1828 into main Jun 11, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant