Skip to content

feat: add reusable npm publish workflow - #2

Open
kokorolx wants to merge 2 commits into
mainfrom
feat/reusable-npm-publish
Open

feat: add reusable npm publish workflow#2
kokorolx wants to merge 2 commits into
mainfrom
feat/reusable-npm-publish

Conversation

@kokorolx

@kokorolx kokorolx commented Sep 6, 2026

Copy link
Copy Markdown
Member

Adds npm-publish.yml, a reusable workflow scoped the same way governed-tag-release.yml is: it validates the immutable state a pushed release tag already points at, then publishes it to the npm registry with --provenance. It never calculates a version, creates or moves tags, commits source, or edits a changelog.

Validation before publish:

  • tag is canonical v-prefixed SemVer and matches both package.json and the caller's version file (version: X.Y.Z metadata, or a .json file with a top-level version field — plugin repos keep their canonical version in plugin.json)
  • refuses any preinstall/install/postinstall/prepare script in package.json
  • re-running a tag whose version is already on the registry is a no-op, not a failure

The caller-owned test-command runs in a separate job with no access to the npm token. Prerelease tags publish under their prerelease identifier as dist-tag (-beta.Nbeta), stable tags under latest.

First consumers: the five @img2threejs/plugin-* packages and the img2 harness (caller PRs open in their repos and will re-pin to the merged SHA of this PR per the pinning policy).

kokorolx and others added 2 commits August 21, 2026 18:41
Callers in this organization that ship an npm package have no reviewed way to publish one. This adds
`npm-publish.yml`, scoped the same way `governed-tag-release.yml` is: it validates the immutable state
a tag already points at and then publishes it. It never calculates a version, creates or moves tags,
commits source, or edits a changelog.

Validation before publishing: the tag is canonical v-prefixed SemVer, and `package.json`'s version and
the caller's `version-file` version both equal the tag without its `v`. A `package.json` declaring a
`preinstall`, `install`, `postinstall`, or `prepare` script is refused, because npm executes those on
every consumer install — including every `npx` invocation by someone who has never read the package.

Tests run in a separate job that receives no secrets. The caller owns `test-command`, following
`python-ci.yml`, so it must not run anywhere that can read the publish credential; only the `publish`
job holds the token, and only it requests `id-token: write` for `--provenance`.

The dist-tag is the tag's prerelease identifier, so `v1.5.0-beta.1` publishes under `beta` and
`v1.5.0-rc.2` under `rc`, matching this repository's release protocol where prerelease metadata already
routes to a GitHub prerelease. A stable tag publishes under `latest`. Re-running a tag whose version is
already on the registry is a no-op rather than a failure, mirroring the existing release workflow's
`existing_release` check.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Plugin repositories keep their canonical version in plugin.json, not in
`version: X.Y.Z` file metadata. When the caller's version-file ends in
.json, read its top-level version field via node instead of grepping for
the metadata line. The file path reaches node through the environment,
never by string interpolation.
kokorolx added a commit to img2threejs/img2 that referenced this pull request Sep 6, 2026
…inline logic

ci.yml and publish.yml now uses: img2threejs/ci-workflows's python-ci.yml and
npm-publish.yml, pinned by full commit SHA per org policy, rather than carrying
their own test/publish steps. Publish authenticates via the NPM_TOKEN secret
(a granular npm automation token), not OIDC trusted publishing; the reusable
workflow validates the tag against package.json, refuses install-time lifecycle
scripts, and no-ops on an already-published version.

Both workflow refs point at a feature branch of ci-workflows pending
img2threejs/ci-workflows#2; re-pin to its merged main SHA once that lands.
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