From 8d837b513409363510aa0504abeee91a7583aac6 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 23 Jul 2026 12:11:54 -0700 Subject: [PATCH 1/6] fix(release): require an explicit dist-tag on v4.x v4.x is a maintenance line, so defaulting to 'latest' is wrong (it points npm install at 4.x instead of 5.x). Make dist_tag required with no default and fail fast if it's empty, before the version bump is pushed. --- .github/workflows/prod-release.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index c0e650243..4e24e42bc 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -11,9 +11,8 @@ on: description: '[Optional] Override semantic versioning with explict version (allowed values: "patch", "minor", "major", or explicit version)' default: '' dist_tag: - description: 'NPM distribution tag' - required: false - default: 'latest' + description: 'NPM distribution tag (required; this is a 4.x maintenance line, so do not use "latest")' + required: true env: NODE_OPTIONS: "--max-old-space-size=4096" @@ -34,6 +33,12 @@ jobs: echo "::error::Dispatch this workflow from a branch (got ${{ github.ref_type }} '${{ github.ref_name }}'). To release a specific commit, point a branch at it first." exit 1 + - name: Require a dist-tag + if: github.event.inputs.dist_tag == '' + run: | + echo "::error::Specify an npm dist-tag. This is the 4.x maintenance line; do not publish to 'latest'." + exit 1 + - name: Checkout code uses: actions/checkout@v4 with: From 4646fb4fc89e1a0c98a3f8c0c4b1a6d34ffec604 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 23 Jul 2026 12:16:50 -0700 Subject: [PATCH 2/6] fix(release): omit --dist-tag when empty so latest isn't moved Instead of requiring a tag, when dist_tag is empty run lerna publish without --dist-tag. Modern npm won't move the 'latest' tag when publishing a lower version, so 4.x maintenance releases don't hijack latest. --- .github/workflows/prod-release.yml | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index 4e24e42bc..fe66b675e 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -11,8 +11,9 @@ on: description: '[Optional] Override semantic versioning with explict version (allowed values: "patch", "minor", "major", or explicit version)' default: '' dist_tag: - description: 'NPM distribution tag (required; this is a 4.x maintenance line, so do not use "latest")' - required: true + description: 'NPM dist-tag. Leave empty to publish without moving the "latest" tag (use for 4.x maintenance releases).' + required: false + default: '' env: NODE_OPTIONS: "--max-old-space-size=4096" @@ -33,12 +34,6 @@ jobs: echo "::error::Dispatch this workflow from a branch (got ${{ github.ref_type }} '${{ github.ref_name }}'). To release a specific commit, point a branch at it first." exit 1 - - name: Require a dist-tag - if: github.event.inputs.dist_tag == '' - run: | - echo "::error::Specify an npm dist-tag. This is the 4.x maintenance line; do not publish to 'latest'." - exit 1 - - name: Checkout code uses: actions/checkout@v4 with: @@ -114,10 +109,18 @@ jobs: run: npm install -g npm@latest - run: npm ci - run: npm run build --if-present - - run: npx lerna publish from-package --yes --dist-tag "$DIST_TAG" + # If no dist-tag is given, omit --dist-tag entirely so npm doesn't move + # `latest` (modern npm won't set `latest` when publishing a lower version). + - name: Publish env: NPM_CONFIG_PROVENANCE: true DIST_TAG: ${{ github.event.inputs.dist_tag }} + run: | + if [ -n "$DIST_TAG" ]; then + npx lerna publish from-package --yes --dist-tag "$DIST_TAG" + else + npx lerna publish from-package --yes + fi # Once publishing is complete, validate that the published packages are useable validate: From 9b7268f65825623d4f9bcf77d2db22ae268bed7c Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 23 Jul 2026 12:21:07 -0700 Subject: [PATCH 3/6] fix(release): default dist-tag to latest; omit --dist-tag when deleted --- .github/workflows/prod-release.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index fe66b675e..0889c20ca 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -11,9 +11,9 @@ on: description: '[Optional] Override semantic versioning with explict version (allowed values: "patch", "minor", "major", or explicit version)' default: '' dist_tag: - description: 'NPM dist-tag. Leave empty to publish without moving the "latest" tag (use for 4.x maintenance releases).' + description: 'NPM dist-tag to publish under; delete to publish without an explicit dist-tag' required: false - default: '' + default: 'latest' env: NODE_OPTIONS: "--max-old-space-size=4096" @@ -109,8 +109,6 @@ jobs: run: npm install -g npm@latest - run: npm ci - run: npm run build --if-present - # If no dist-tag is given, omit --dist-tag entirely so npm doesn't move - # `latest` (modern npm won't set `latest` when publishing a lower version). - name: Publish env: NPM_CONFIG_PROVENANCE: true From 7c2b4455325b1b1dc8b5e535e2fb8a1f43a24db3 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 23 Jul 2026 20:24:30 +0000 Subject: [PATCH 4/6] fix(release): clarify dist_tag input help ("leave empty" not "delete") --- .github/workflows/prod-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index 0889c20ca..7a53631b0 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -11,7 +11,7 @@ on: description: '[Optional] Override semantic versioning with explict version (allowed values: "patch", "minor", "major", or explicit version)' default: '' dist_tag: - description: 'NPM dist-tag to publish under; delete to publish without an explicit dist-tag' + description: 'NPM dist-tag to publish under; leave empty to publish without an explicit dist-tag' required: false default: 'latest' From 9e1ed66d3b2562820d8cfc6cc0da469226c5dc16 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 23 Jul 2026 14:22:51 -0700 Subject: [PATCH 5/6] fix(release): publish with --concurrency 1 Serialize package publishes so we don't submit 27 provenance attestations to the Rekor transparency log in parallel, reducing timeout-induced 409s. --- .github/workflows/prod-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index 7a53631b0..c89b3cb4b 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -115,9 +115,9 @@ jobs: DIST_TAG: ${{ github.event.inputs.dist_tag }} run: | if [ -n "$DIST_TAG" ]; then - npx lerna publish from-package --yes --dist-tag "$DIST_TAG" + npx lerna publish from-package --yes --concurrency 1 --dist-tag "$DIST_TAG" else - npx lerna publish from-package --yes + npx lerna publish from-package --yes --concurrency 1 fi # Once publishing is complete, validate that the published packages are useable From f8299533c264a59ee8349bd41c07e8b60321a672 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 23 Jul 2026 21:33:29 +0000 Subject: [PATCH 6/6] fix(deps): sync lockfile so npm ci passes on npm 10 (restore lerna @types/node subtree) --- package-lock.json | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/package-lock.json b/package-lock.json index 007216541..56e3a0456 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13785,6 +13785,18 @@ } } }, + "node_modules/lerna/node_modules/@types/node": { + "version": "26.1.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", + "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "undici-types": "~8.3.0" + } + }, "node_modules/lerna/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -20943,6 +20955,15 @@ "node": ">=18.17" } }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/universal-user-agent": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz",