Skip to content

Replace npm release workflow with a local interactive PHP script#3604

Closed
Kocal wants to merge 1 commit into
symfony:2.xfrom
Kocal:manual-npm-releases
Closed

Replace npm release workflow with a local interactive PHP script#3604
Kocal wants to merge 1 commit into
symfony:2.xfrom
Kocal:manual-npm-releases

Conversation

@Kocal

@Kocal Kocal commented May 29, 2026

Copy link
Copy Markdown
Member
Q A
Bug fix? no
New feature? no
Deprecations? no
Documentation? no
Issues Fix #...
License MIT

I'm open to discussion, but I strongly believe automated releases on npm must not be a thing anymore.

The release-on-npm.yaml workflow has been failing repeatedly when publishing @symfony/ux-native (see run 26623506573 and #3522) EDIT: I forgot to enable OIDC on @symfony/ux-native npm package 🙄.

The combination of OIDC (#3142), workflow permissions tweaks, and an automated bump+commit+push from CI is hard to debug and adds a real security surface for a step that runs once per release.

This PR drops the workflow and adds bin/release-on-npm.php, an interactive script run manually after pushing a release tag.

All UX packages have been configured on npm to only allow manual releases with 2FA enabled
image

After merging and upmerge, the OIDC (trusted publisher) will be removed from npm packages, since it won't be useful anymore.

Usage

php bin/release-on-npm.php 2.37.0 # default remote: upstream
php bin/release-on-npm.php 2.37.0 --remote=origin

@Kocal Kocal self-assigned this May 29, 2026
@carsonbot carsonbot added the Status: Needs Review Needs to be reviewed label May 29, 2026
@carsonbot carsonbot changed the title Replace npm release workflow with a local interactive PHP script Replace npm release workflow with a local interactive PHP script May 29, 2026
@Kocal Kocal requested a review from kbond May 29, 2026 08:42
@carsonbot carsonbot added Status: Reviewed Has been reviewed by a maintainer and removed Status: Needs Review Needs to be reviewed labels May 29, 2026
@Kocal Kocal closed this May 29, 2026
@Kocal

Kocal commented May 29, 2026

Copy link
Copy Markdown
Member Author

Let's go for another, automated, but more secure, solution.

Kocal added a commit that referenced this pull request Jun 4, 2026
This PR was squashed before being merged into the 2.x branch.

Discussion
----------

[CI] Harden the release-on-npm workflow

| Q              | A
| -------------- | ---
| Bug fix?       | no
| New feature?   | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations?  | no <!-- if yes, also update UPGRADE-*.md and src/**/CHANGELOG.md -->
| Documentation? | no <!-- required for new features, or documentation updates -->
| Issues         | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License        | MIT

Following #3604

## Summary

Following an audit of `.github/workflows/release-on-npm.yaml` with my super friend Claude,
this PR tightens several aspects of the npm release pipeline.
OIDC trusted publisher protects authentication on the npm side, but says nothing about the integrity of the code being published.
The changes below close that gap.

Each commit addresses one finding from the audit, tagged `(F<n>)` in its title.

## Commits

- **[CI] Publish from the tagged commit, not the branch HEAD (F1)** — checkout `${{ github.ref }}` (the tag) instead
of the hardcoded `2.x` branch, and verify the tagged commit is an ancestor of the matching release branch
(`2.x` for `v2.*.*`, `3.x` for `v3.*.*`). Closes a TOCTOU where `2.x` HEAD could drift between tag creation and job execution.

- **[CI] Stop touching package.json versions during release (F8)** — drop the `pnpm version` + commit + push back to
`2.x` block. The Git tag is the single source of truth; version bumps are now done manually before tagging. The workflow token is downgraded from `contents: write` to `contents: read`, and **the new `MAINTAINERS.md` documents the bump procedure.**
Code can not be commited/pushed to the repo anymore ✨

- **[CI] Pin npm version used by the release workflow (F6)** — replace `npm@latest` with `npm@11.16.0` so a compromised npm release cannot ship through the release path without an explicit, reviewable bump PR.

- **[CI] Generate npm provenance attestations on publish (F7)** — add `--provenance` to `pnpm publish`. Each tarball now carries a signed SLSA attestation pointing to the repo, commit and workflow run, verifiable via `npm audit signatures`.

- **[CI] Serialize release runs per tag (F9)** — add a concurrency group keyed on `github.ref_name`, so two runs on the same tag queue instead of overlapping. Distinct tags (`v2.x.y` vs `v3.0.0`) still run in parallel.

- **[CI] Build assets and refuse to publish if dist files drift (F2)** — run `pnpm build` on the tagged commit and fail if `git diff --quiet` reports anything. Mirrors the existing `dist-files-unbuilt.yaml` PR check, brought into the release path so tampered dist/source pairs cannot publish even if the branch CI was bypassed.

Commits
-------

6607915 [CI] Build assets and refuse to publish if dist files drift (F2)
aa5fcb8 [CI] Serialize release runs per tag (F9)
49d7697 [CI] Generate npm provenance attestations on publish (F7)
b61c0d5 [CI] Pin npm version used by the release workflow (F6)
86131fe [CI] Stop touching package.json versions during release (F8)
4ab4f5b [CI] Publish from the tagged commit, not the branch HEAD (F1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: Reviewed Has been reviewed by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants