Repository navigation
ci: publish only the verified release tarball and split the GitHub release job - #317
Conversation
The publish job now downloads the package artifact by its exact name and checks the tarball's SHA-256 against the digest recorded by build-package before running npm publish. It no longer restores an npm cache, and it runs in the npm-publish environment. Creating the GitHub release moves to its own job, which holds only the contents write grant, attaches the same verified tarball, and tags the commit that was built. setup-and-version now requires VERSION to be a semantic version and derives the npm dist-tag: main publishes as latest, and maintenance/<N>.x publishes as maintenance-<N>.x only for versions in major N. npm refuses dist-tags that parse as semver ranges, such as 4.x. Other branches stop before publishing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
🛣️ Rokt Platform Paved Roads Scan Complete✅ No paved-road issues detected Scanned files against 188 rules. · Reviewed commit: 📜 Scan history (3 scans)
ℹ️ About Rokt Platform Paved Roads AgentThis scan was performed by the Rokt Platform Paved Roads Agent, an automated paved-road standards review tool for pull requests. See the User Guide for details on severity levels, feedback reactions, and scan configuration. Reply |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
🔒 Security Scan Complete✅ No security issues detected Scanned files against 71 rules. · Reviewed commit: 📜 Scan history (3 scans)
ℹ️ About PR Security AgentThis scan was performed by PR Security Agent, an automated security review tool for pull requests. See the User Guide for details on severity levels, feedback reactions, and scan configuration. Reply |
There was a problem hiding this comment.
Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.
Besides the inline finding, I checked two other things and neither is a problem. First, the new artifact-name output is set: the package-tarball step writes it at .github/actions/build-package/action.yml:53. Second, the downloaded tarball ends up at Rokt.Widget/rokt-react-native-sdk-<version>.tgz. Both uploaded files sit under Rokt.Widget/, so the artifact stores them at its root, and that matches the path the digest checks and the release upload expect.
Extended reasoning...
I confirmed the composite action writes the artifact-name output that the new download steps use. I also confirmed that the upload-artifact path layout puts the tarball where the sha256sum --check lines and the release upload look for it.
A prerelease VERSION such as 5.0.0-rc.1 on main was published as npm latest and marked as the latest GitHub release. Prereleases now publish under next on any release branch, and the GitHub release is marked latest only when the npm tag is latest. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A prerelease from maintenance/<N>.x moved next, which main's prereleases use, back to an older major. Maintenance prereleases now publish under maintenance-<N>.x-next, and only main's prereleases use next. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
I reviewed the latest push and didn't find any new bugs. Both of my earlier dist-tag comments are addressed in the code. Because this changes the npm OIDC publishing pipeline, which CODEOWNERS assigns to the SDK team, a human look before the next release is still worthwhile.
What was reviewed:
- Prerelease tagging: a prerelease on
mainnow getsnext, and one onmaintenance/<N>.xgetsmaintenance-<N>.x-next.makeLatestnow depends on the computed tag beinglatest, not on the branch. - Artifact handoff:
artifact-nameandsha256are produced by thepackage-tarballstep, passed on as job outputs, and checked in bothpublish-npmandgithub-releasebefore the tarball is used. - Permissions:
publish-npmkeepsid-token: writewith onlycontents: readand no checkout.github-releasehascontents: writeand noid-token.
Extended reasoning...
The change touches two CI files: the shared build-package composite action, which now records the tarball's SHA-256 and artifact name, and release-publish.yml. In release-publish.yml the combined release job becomes separate publish-npm and github-release jobs, and dist-tag selection plus a semver check move into setup-and-version. The sensitive surface is the npm trusted-publishing path (id-token: write, the new npm-publish environment) and the release job's contents: write token. The two findings raised on earlier pushes, prereleases on main publishing as latest and maintenance prereleases taking over next, are fixed in the current diff. I deferred instead of approving because .github/workflows/ and .github/actions/ belong to a CODEOWNERS team and the release jobs only run end to end on a real release.
nickolas-dimitrakas
left a comment
There was a problem hiding this comment.
Approving. Digest check, job split, permissions and dist-tag logic look right; I confirmed with semver that maintenance-4.x and maintenance-4.x-next are not ranges. Before merging: the npm-publish environment doesn't exist yet, so create it (required reviewers, restrict to main and maintenance/*) and confirm the npm trusted-publisher entry matches it, or the first release will fail at publish.
Why
A release should publish exactly the tarball that its own run built. Today the publish step does not guarantee that:
maintenance/4.xrequests4.x. npm rejects that tag because it reads as a version range.VERSIONfrommainaslatest.Once this lands:
latest.Programme
Standalone change, no programme.
What changes
build-packageoutputs the tarball's SHA-256 and artifact name.release-and-tagbecomes two jobs:publish-npmdownloads that artifact by exact name, checks it withsha256sum --check, and runsnpm publish. It has no checkout and no npm cache, holdsid-token: writewithcontents: read, and runs in thenpm-publishenvironment.github-releaseholdscontents: writeand noid-token. It verifies the same file, then creates the release with that exact tarball, tagged atgithub.sha.setup-and-versionrequiresVERSIONto beMAJOR.MINOR.PATCH[-prerelease].main, the release publishes aslatest.maintenance/<N>.xpublishes asmaintenance-<N>.xwhenVERSION's major is N.VERSIONpublishes asnextfrommain, or asmaintenance-<N>.x-nextfrom a maintenance branch. The GitHub release is marked latest only for alatestpublish.Start reading at
.github/workflows/release-publish.yml.Linked work
None.
Rollout
Path: CI only, and merging publishes nothing. The
build-packageaction is shared withpull-request.yml, so from merge every PR's package job also records the digest; this PR's own CI runs that step. The release jobs change from the nextRelease – Publishrun, which happens whenVERSIONchanges.Feature flags: none.
Turning it off: revert this pull request. The revert applies from the next workflow run.
What we watch: the package job on this PR and on later PRs, and the
publish-npmandgithub-releasejobs of the next release. A failing digest check, dist-tag step or publish means we revert.Risks
npm publish, so nothing is published.github-releasefails afterpublish-npmsucceeds.maintenance-<N>.x.<N>.xwas refused by npm, and no maintenance dist-tag exists today.Risk class: medium. The release jobs only run end to end on a real release.
Who
Written by: the pull request's author.
Code reviewed before opening: no one.
Design reviewed before opening: no one.
Decision this implements: no separate decision record.
Checked: on 14 and 15 October 2026, locally:
VERSIONcases, including prereleases.4.xis a range andmaintenance-4.xis not.trunk checkon both files.Not checked: a real release run.
Size
Hand-written: 103 lines (74 added, 29 removed) across 2 files.
Generated: none.
🤖 Generated with Claude Code