Release tooling: PyPI Trusted Publishing + v1.0.0 - #14
Conversation
- Add .github/workflows/release.yml: on a published GitHub Release, build the sdist + wheel and upload to PyPI via Trusted Publishing (OIDC, id-token: write, environment: pypi). No API token stored. Actions pinned to SHAs. - Verify-tag-matches-version guard so a release can't publish a different version than its tag claims. - Bump to 1.0.0 and flip the Development Status classifier to Production/Stable. - Make __init__.__version__ the single source of truth via setuptools dynamic version, so pyproject and the package can't drift. - README 'Releasing' section; bump the k8s example image tag to 1.0.0. Build verified locally (optimum_keysync-1.0.0 sdist + wheel); 84 tests pass.
📝 WalkthroughWalkthroughThis PR adds a GitHub Actions Sequence Diagram(s)sequenceDiagram
participant GitHubRelease as GitHub Release
participant ReleaseWorkflow as release workflow
participant Checkout as actions/checkout
participant SetupPython as actions/setup-python
participant Build as python -m build
participant Publish as pypa/gh-action-pypi-publish
participant PyPI as PyPI
GitHubRelease->>ReleaseWorkflow: published event
ReleaseWorkflow->>Checkout: checkout pinned commit
ReleaseWorkflow->>SetupPython: install Python 3.12
ReleaseWorkflow->>ReleaseWorkflow: compare release tag with __version__
ReleaseWorkflow->>Build: build sdist and wheel
ReleaseWorkflow->>Publish: publish artifacts via OIDC
Publish->>PyPI: upload distributions
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/release.yml:
- Line 31: The checkout step in the release workflow is persisting credentials
unnecessarily, so update the actions/checkout usage to disable credential
persistence for this job. Adjust the checkout configuration so the workflow
still fetches the repo but does not keep the token in local git config, and keep
the change scoped to the checkout action invocation in the release job.
In `@README.md`:
- Around line 140-141: The release instructions in the README are pointing to
the wrong version source, since the workflow uses optimum_keysync.__version__
rather than pyproject.toml. Update the release docs to tell maintainers to bump
the version where the package actually reads it, then commit, merge to main, and
create the GitHub Release tagged v<version>; also align the release workflow
reference in .github/workflows/release.yml with the same version source so the
documented steps match the version check.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: getoptimum/coderabbit/.coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 25c79856-d533-4307-a7ea-a9529bec773a
⛔ Files ignored due to path filters (1)
pyproject.tomlis excluded by none and included by none
📒 Files selected for processing (4)
.github/workflows/release.ymlREADME.mdexamples/kubernetes/cronjob.yamlsrc/optimum_keysync/__init__.py
| steps: | ||
| # Action versions pinned to commit SHAs (tag in the comment) per the | ||
| # OpenSSF / GitHub-hardening guidance used across this repo's workflows. | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Disable checkout credential persistence.
This job never pushes to GitHub, so keeping the checkout token in local git config only increases exposure to later steps and build hooks.
Suggested fix
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: falseAs per path instructions, "Check permissions (least privilege) ... Flag secret exposure in logs, overly broad permissions" and zizmor warns "credential persistence through GitHub Actions artifacts (artipacked)."
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| with: | |
| persist-credentials: false |
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 31-31: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release.yml at line 31, The checkout step in the release
workflow is persisting credentials unnecessarily, so update the actions/checkout
usage to disable credential persistence for this job. Adjust the checkout
configuration so the workflow still fetches the repo but does not keep the token
in local git config, and keep the change scoped to the checkout action
invocation in the release job.
Sources: Path instructions, Linters/SAST tools
| 1. Bump `version` in `pyproject.toml` and merge to `main`. | ||
| 2. Publish a GitHub Release tagged `v<version>` (e.g. `v1.0.0`). |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Point the release docs at the real version source.
Line 140 still tells maintainers to bump pyproject.toml, but this PR’s workflow reads optimum_keysync.__version__. Following the README as written will cause the next tagged release to fail the version check. Also at: .github/workflows/release.yml: Line 46.
Suggested fix
-1. Bump `version` in `pyproject.toml` and merge to `main`.
+1. Bump `src/optimum_keysync/__init__.py`'s `__version__` and merge to `main`.As per path instructions, "Prioritize technical accuracy and copy-pastable commands" and "Flag references to removed APIs, wrong paths, or steps that contradict the repo."
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 1. Bump `version` in `pyproject.toml` and merge to `main`. | |
| 2. Publish a GitHub Release tagged `v<version>` (e.g. `v1.0.0`). | |
| 1. Bump `src/optimum_keysync/__init__.py`'s `__version__` and merge to `main`. | |
| 2. Publish a GitHub Release tagged `v<version>` (e.g. `v1.0.0`). |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.md` around lines 140 - 141, The release instructions in the README are
pointing to the wrong version source, since the workflow uses
optimum_keysync.__version__ rather than pyproject.toml. Update the release docs
to tell maintainers to bump the version where the package actually reads it,
then commit, merge to main, and create the GitHub Release tagged v<version>;
also align the release workflow reference in .github/workflows/release.yml with
the same version source so the documented steps match the version check.
Source: Path instructions
What
Sets the repo up to publish to PyPI through the GitHub Release flow, and cuts the version to 1.0.0.
Release automation
.github/workflows/release.ymlruns when a GitHub Release is published. It builds the sdist + wheel and uploads to PyPI via Trusted Publishing (OIDC) (id-token: write,environment: pypi) — no API token stored in the repo. Actions are SHA-pinned to match the repo's hardening convention (pypa/gh-action-pypi-publishv1.14.0).v) matches the package version, so a release can never publish a version different from what its tag claims.Versioning
Development Statusclassifier flipped to5 - Production/Stable.src/optimum_keysync/__init__.py:__version__the single source of truth via setuptools dynamic version (dynamic = ["version"]+[tool.setuptools.dynamic]), sopyproject.tomland the package can't drift. (Previously both hardcoded the version independently.)Docs/examples
1.0.0.Verified locally
python -m build→optimum_keysync-1.0.0.tar.gz+...-py3-none-any.whl(dynamic version resolves to 1.0.0).pytest84 passed;ruffandmypyclean.Register the trusted publisher on PyPI (PyPI is configured in its web UI, not here):
optimum-keysyncgetoptimum/optimum-customer-key-importrelease.ymlpypiAlso create the
pypienvironment in repo Settings → Environments (optionally add release protection rules). If the project doesn't exist on PyPI yet, use PyPI's "pending publisher" so the first release creates it.How to cut the release after merge
main.v1.0.0.Written with Claude Code
Summary by CodeRabbit
New Features
1.0.0.Documentation
Chores
1.0.0across release and deployment configs.