Skip to content

ci(packaging): add garasign-signed release pipeline with PyPI OIDC - #29

Open
Jibola wants to merge 1 commit into
mongodb-developer:developfrom
Jibola:ci/python-release-signing
Open

Jibola wants to merge 1 commit into
mongodb-developer:developfrom
Jibola:ci/python-release-signing

Conversation

@Jibola

@Jibola Jibola commented Oct 15, 2026

Copy link
Copy Markdown

Summary

Adds a manual, drop-in signed-release pipeline covering the three controls required for the ABX launch:

  • Code signing — a GPG-signed git tag and detached .sig signatures over every distribution, both created inside the Garasign container.
  • PyPI publishing via OIDC — pypa/gh-action-pypi-publish with trusted publishing; no PyPI token is stored anywhere.
  • Signed release tracking — a draft GitHub Release carrying the distributions, their .sig files, and an authorized-publication.txt record (releaser, commit, SHA-256 of every artifact).

The four composite actions under .github/actions/ mirror mongodb-labs/drivers-github-tools@v3 (setup, git-sign, gpg-sign, authorized-pub + the draft-release step of python/post-publish), but are self-contained local files so this repo has no dependency on that external repo.

This is additive to release-python.yml (the existing manifest-driven coordinator), which is unchanged. Before the first real release, pick which workflow is canonical — a PyPI trusted publisher is bound to one workflow filename (both can be registered).

Flow

workflow_dispatch(ref, dry_run, publish_to_test_pypi)
  |
  v
prepare   read version from <PACKAGE_DIR>/pyproject.toml, require canonical PEP 440
          refuse if <TAG_PREFIX><version> exists on another commit
          release-setup -> garasign-git: git tag -a -s <tag>
          verify-tag against gpg-public-url (if set) -> push tag (unless dry_run)
  |
  v
build     checkout the exact SHA -> python -m build -> twine check -> upload dist-<run_id>
  |
  v
publish   [environment: release] download dist
          pypa/gh-action-pypi-publish (OIDC)      (unless dry_run)
          actions/attest-build-provenance         (unless dry_run)
  |
  v
sign-and- [environment: release] release-setup -> download dist
release   sign-artifacts: dist/* -> $RELEASE_ASSETS/*.sig
          create-draft-release: authorized-publication.txt
                                gh release create --draft --verify-tag
                                gh release upload *.sig dist/* authorized-publication.txt

Every job after prepare checks out needs.prepare.outputs.sha, so the tag, the built files, the PyPI upload, and the signatures all describe one commit.

Porting to other repos

Only three values need to change, in release.yml's env: block:

PRODUCT_NAME: <distribution name>
PACKAGE_DIR: <directory containing pyproject.toml, or ".">
TAG_PREFIX: <"v", "python-v", or "">

See docs/release/signed-release-pipeline.md for the full setup checklist and the list of what was deliberately trimmed relative to mongo-python-driver's release pipeline (Kondukto SBOM augmentation, SSDLC compliance report, S3 upload, multi-platform wheel matrix — none of which this repo needs yet).

One-time setup required before this can run for real

  • Three repository secrets: AWS_ROLE_ARN, AWS_REGION, AWS_SECRET_ID
  • AWS Secrets Manager secret with garasign-username, garasign-password, gpg-key-id (gpg-public-url optional)
  • AWS role trust policy updated for this repo's OIDC subject (both the signing-secrets role and the ecr-role-gha-ro pull role)
  • release GitHub environment with required reviewers
  • PyPI Trusted Publisher configured for release.yml / release environment
  • Decide which GPG key signs ABX artifacts (existing DBX drivers key or a new one)

Validation

  • All workflow/action YAML parses
  • Dry run (dry_run: true) exercised once the secrets/environment above exist — not yet runnable from this PR alone
  • TODO left on actions/attest-build-provenance@v4 — this repo pins everything else to a full SHA; flagging for reviewer input on the intended pin before merge

Add a manual release workflow and four composite actions mirrored from mongodb-labs/drivers-github-tools@v3: a GPG-signed tag and detached signatures created in the Garasign container, PyPI upload through trusted publishing with no stored token, build provenance, and a draft GitHub Release carrying the distributions, their .sig files, and an authorized-publication record with SHA-256 sums. Additive to release-python.yml and manual-only; dry_run defaults to true. Per-repository knobs are PRODUCT_NAME, PACKAGE_DIR, and TAG_PREFIX. docs/release/signed-release-pipeline.md records the one-time setup and what was trimmed relative to mongo-python-driver.

This branch has not been deployed

No deployments
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