Skip to content

ci: separate release workflows for npm + PyPI (OIDC trusted publishing)#3

Merged
lexaisnotdead merged 3 commits into
mainfrom
ci/release-workflows
Jul 23, 2026
Merged

ci: separate release workflows for npm + PyPI (OIDC trusted publishing)#3
lexaisnotdead merged 3 commits into
mainfrom
ci/release-workflows

Conversation

@lexaisnotdead

@lexaisnotdead lexaisnotdead commented Jul 23, 2026

Copy link
Copy Markdown
Member

Two independent release workflows (not one shared) so each package versions/releases on its own and each OIDC trusted publisher is least-privilege — the npm workflow can't publish PyPI and vice-versa.

Workflow Trigger tag Publishes
release-npm.yml typescript-v* @hashlock-tech/sdk → npm (with provenance)
release-pypi.yml python-v* hashlock-sdk → PyPI

Both use OIDC Trusted Publishing — no long-lived tokens in the repo. Token fallback documented inline. Both builds were verified locally (TS dist + Python wheel/sdist).

After merge, configure the two trusted publishers (one per registry, each pointing at its workflow file), then release with e.g. git tag typescript-v1.0.0 && git push origin typescript-v1.0.0.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Added automated release workflows to publish the TypeScript package to npm and the Python package to PyPI.
    • Releases are triggered by version-specific tags, validate that the tag version matches the package version, build artifacts, and publish using trusted publishing with provenance support.

Two independent workflows so each package versions/releases on its own and each OIDC
trusted publisher is least-privilege (npm can't publish PyPI and vice-versa):
- release-npm.yml  → tag typescript-v* → @hashlock-tech/sdk (npm, with provenance)
- release-pypi.yml → tag python-v*     → hashlock-sdk (PyPI)
No long-lived tokens in the repo; token fallback documented inline.

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

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 866c5c0d-8a5f-4ba0-b5a3-94f8be6926e1

📥 Commits

Reviewing files that changed from the base of the PR and between 65f2b23 and e458825.

📒 Files selected for processing (1)
  • .github/workflows/release-npm.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/release-npm.yml

📝 Walkthrough

Walkthrough

Adds tag-triggered GitHub Actions workflows that validate package versions, build artifacts, and publish the TypeScript package to npm and the Python package to PyPI using OIDC trusted publishing.

Changes

Package release automation

Layer / File(s) Summary
npm trusted publishing workflow
.github/workflows/release-npm.yml
Triggers on typescript-v* tags, verifies the package version, builds and packs the TypeScript package with Node 24.18.0, then publishes the artifact to npm with provenance.
PyPI trusted publishing workflow
.github/workflows/release-pypi.yml
Triggers on python-v* tags, verifies the package version, builds Python distributions with Python 3.11, then publishes them to PyPI through OIDC Trusted Publishing.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

npm release flow

sequenceDiagram
  participant Tag as Git tag
  participant Build as npm build job
  participant Publish as npm publish job
  Tag->>Build: Trigger typescript-v* workflow
  Build->>Build: Validate version, build, and pack
  Build->>Publish: Transfer .tgz artifact
  Publish->>Publish: Publish with OIDC provenance
Loading

PyPI release flow

sequenceDiagram
  participant Tag as Git tag
  participant Build as PyPI build job
  participant Publish as PyPI publish job
  Tag->>Build: Trigger python-v* workflow
  Build->>Build: Validate version and build distributions
  Build->>Publish: Transfer distribution artifact
  Publish->>Publish: Publish through OIDC Trusted Publishing
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the addition of separate npm and PyPI release workflows using OIDC trusted publishing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/release-workflows

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Checkov (3.3.8)
.github/workflows/release-npm.yml

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 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-npm.yml:
- Line 23: Add persist-credentials: false to the actions/checkout@v4 steps in
both .github/workflows/release-npm.yml (lines 23-23) and
.github/workflows/release-pypi.yml (lines 20-20), ensuring neither release
workflow leaves GITHUB_TOKEN configured in git.
- Line 9: Add a pre-build validation step in the release workflow that reads the
version from typescript/package.json and compares it with GITHUB_REF_NAME after
removing the typescript- tag prefix. Fail the job before the build or publish
steps when they differ, while allowing matching tags to continue unchanged.
- Around line 11-31: The workflows currently run untrusted build commands with
OIDC permissions. In .github/workflows/release-npm.yml lines 11-31, create a
non-privileged build job that installs/builds and uploads the npm package
artifact, then make the privileged publish job depend on it, download only that
artifact, and run npm publish; in .github/workflows/release-pypi.yml lines
11-29, similarly move python -m build into a job without id-token: write, upload
the distributions, and have the privileged publish job download and publish only
those artifacts.

In @.github/workflows/release-pypi.yml:
- Line 27: Pin all publishing workflow actions to immutable 40-character commit
SHAs for the audited versions: update actions/checkout and actions/setup-node in
.github/workflows/release-npm.yml lines 23-24, and actions/checkout,
actions/setup-python, and pypa/gh-action-pypi-publish in
.github/workflows/release-pypi.yml lines 20-21 and 27. Preserve the existing
action versions and workflow behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e8631da4-f846-4895-99f8-6ce24f036165

📥 Commits

Reviewing files that changed from the base of the PR and between 22e769a and e0bd09d.

📒 Files selected for processing (2)
  • .github/workflows/release-npm.yml
  • .github/workflows/release-pypi.yml

Comment thread .github/workflows/release-npm.yml
Comment thread .github/workflows/release-npm.yml Outdated
Comment thread .github/workflows/release-npm.yml Outdated
Comment thread .github/workflows/release-pypi.yml Outdated
Address the CodeRabbit findings on the release workflows (all verified still-valid):
- Split each into a non-privileged build job (npm install/build, python -m build) and a
  minimal publish job that alone holds id-token: write — the OIDC job never runs untrusted
  install/build scripts (it publishes only the uploaded artifact).
- Guard version drift: fail before publish if the tag (minus the typescript-/python- prefix)
  != the manifest version (package.json / pyproject.toml).
- persist-credentials: false on all checkouts (no leftover GITHUB_TOKEN in git config).
- Pin every action to a 40-char commit SHA (checkout, setup-node, setup-python,
  upload/download-artifact, gh-action-pypi-publish), keeping the audited versions.

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

Copy link
Copy Markdown
Member Author

Verified all four review findings against the current workflows — all still valid, all applied (commit 65f2b23):

  1. Least-privilege split — each workflow now has a non-privileged build job (npm install/npm run build, python -m build) that uploads the artifact, and a minimal publish job that alone holds id-token: write and only publishes the uploaded artifact (npm publishes the packed *.tgz; PyPI publishes the downloaded dist/). The OIDC-privileged job never runs untrusted install/build scripts.
  2. Version/tag guard — a step fails before build/publish if the tag (minus the typescript-/python- prefix) doesn't match the manifest version (package.json / pyproject.toml).
  3. persist-credentials: false on every actions/checkout.
  4. SHA-pinned actionscheckout, setup-node, setup-python, upload/download-artifact, and gh-action-pypi-publish pinned to 40-char commit SHAs (audited versions preserved, noted in trailing comments).

Validated: both files parse as YAML; 10 pinned SHAs / 0 unpinned @vN; id-token: write present only in the two publish jobs.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/release-npm.yml (1)

35-35: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Add a committed npm lockfile for release installs.

The release workflow currently installs from ranged dependencies in typescript/package.json, and there is no tracked typescript/package-lock.json; npm ci would fail here until the lockfile is added.

🤖 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-npm.yml at line 35, Add and commit
typescript/package-lock.json generated from typescript/package.json, then update
the release workflow’s install step to use npm ci so dependencies are installed
from the lockfile.
🤖 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-npm.yml:
- Line 59: Remove the mutable global npm installation from the OIDC release job.
Update the workflow’s Node setup/toolchain configuration to use a pinned Node
version at or above 22.14.0 with bundled npm 11.5.1 or newer, preserving trusted
publishing without running registry-supplied install scripts in the privileged
job.

---

Nitpick comments:
In @.github/workflows/release-npm.yml:
- Line 35: Add and commit typescript/package-lock.json generated from
typescript/package.json, then update the release workflow’s install step to use
npm ci so dependencies are installed from the lockfile.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 03f5a5b8-c642-44d3-9369-3023e485fea3

📥 Commits

Reviewing files that changed from the base of the PR and between e0bd09d and 65f2b23.

📒 Files selected for processing (2)
  • .github/workflows/release-npm.yml
  • .github/workflows/release-pypi.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/release-pypi.yml

Comment thread .github/workflows/release-npm.yml Outdated
Per review: don't run `npm install -g npm@latest` (registry-supplied, with install
scripts) inside the id-token: write job. Pin the publish job to Node 24.18.0, whose
bundled npm 11.16.0 already satisfies OIDC trusted publishing (>= 11.5.1) — no runtime
npm upgrade in the privileged context. (Reviewer's '22.14.0' bundles npm 10.9.2; the
earliest Node with npm >= 11.5.1 is 24.5.0.) Build job unchanged (no OIDC there).

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

Copy link
Copy Markdown
Member Author

Applied (commit e458825) — finding valid, with one correction to the suggested value.

Removed npm install -g npm@latest from the OIDC publish job and pinned it to Node 24.18.0, whose bundled npm 11.16.0 already satisfies OIDC trusted publishing (≥ 11.5.1) — so the privileged job runs no registry-supplied install scripts. The publish job now runs only: download-artifactsetup-nodenpm publish *.tgz --provenance --access public.

Note on the suggested 22.14.0: verified against nodejs.org/dist — Node 22.14.0 bundles npm 10.9.2, not 11.5.1. The earliest Node bundling npm ≥ 11.5.1 is 24.5.0; 24.18.0 is the current LTS on that line. The build job (no OIDC) is left on Node 22 unchanged.

@lexaisnotdead
lexaisnotdead merged commit 7396e2b into main Jul 23, 2026
5 checks passed
@lexaisnotdead
lexaisnotdead deleted the ci/release-workflows branch July 24, 2026 14:35
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