diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 98036a1..788841f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -513,7 +513,19 @@ jobs: # not install cleanly, which is the useful half. - name: Verify published packages install as a single copy each if: startsWith(github.ref, 'refs/tags/v') - run: node ./build/verify-npm-single-copy.mjs '${{ steps.version.outputs.version }}' + shell: bash + run: | + # This step runs yarn (inside verify-npm-single-copy.mjs), and it sits downstream of the + # second actions/setup-node above - the one that sets registry-url for the OIDC publish + # steps and therefore writes an .npmrc carrying a literal ${NODE_AUTH_TOKEN} placeholder, + # exported to every later step as $NPM_CONFIG_USERCONFIG. Yarn Classic substitutes every + # env-var placeholder in its resolved config on every invocation and throws when one is + # unset, and nothing sets NODE_AUTH_TOKEN (npm Trusted Publishing does not use it). Moving + # registry-url past the last yarn command fixed the yarn commands that run *before* + # publishing; this one runs after it, so it needs its own empty userconfig. Nothing here + # authenticates - it installs published, public packages from npmjs. + verify_npmrc="$(mktemp)" + NPM_CONFIG_USERCONFIG="$verify_npmrc" node ./build/verify-npm-single-copy.mjs '${{ steps.version.outputs.version }}' # Extract this version's section from the root CHANGELOG.md # as the draft release body. diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a95b9f..1783a8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,22 @@ so it stays clear which part of the repository actually moved. ## [Unreleased] +### Fixed + +- **The post-publish "Verify published packages install as a single copy each" step crashed on the + same `${NODE_AUTH_TOKEN}` placeholder that had broken every yarn command earlier in the job**, so + the `v10.0.0-rc.14` run failed *after* it had already published all 33 NuGet packages and all five + Angular packages: the draft GitHub Release was never created, and the single-copy check the step + exists for never actually ran. `v10.0.0-rc.13`'s fix moved `actions/setup-node`'s `registry-url` + onto a second `setup-node` call placed past the last yarn command in the job - but this step runs + *after* publishing, and therefore after that second call, whose generated `.npmrc` stays exported + as `$NPM_CONFIG_USERCONFIG` for every remaining step. Yarn Classic expands every env-var + placeholder in its resolved config on every invocation and throws when one is unset, and nothing + sets `NODE_AUTH_TOKEN` (npm Trusted Publishing does not use it). The step now runs with an empty + `NPM_CONFIG_USERCONFIG` of its own, which is all it needs: it installs published, public packages + from npmjs and authenticates nothing. Verified by hand against the published `10.0.0-rc.14` set - + Yarn Classic resolves exactly one copy of each of the five packages. + ## [10.0.0-rc.14] - 2026-09-04 ### Fixed diff --git a/build/resolve-npm-dist-tag.mjs b/build/resolve-npm-dist-tag.mjs index 8653b8c..a51c403 100644 --- a/build/resolve-npm-dist-tag.mjs +++ b/build/resolve-npm-dist-tag.mjs @@ -17,6 +17,14 @@ * solves. Reading the registry rather than hardcoding a date or a flag means the rule retires itself * the moment the first stable ships, with nobody having to remember to come back and change it. * + * One tag, not two: while a pre-release holds `latest`, `next` is left wherever the previous release + * put it. `npm publish` takes a single --tag, and moving a second one afterwards needs + * `npm dist-tag add`, which requires a standing credential this workflow deliberately does not have - + * npmjs publishing here is OIDC-based, and the short-lived token npm exchanges internally during a + * publish is never exposed to another command. So while this rule is in force, `next` has to be + * moved by hand if it should track the newest pre-release. The question retires itself along with + * the rule: from the first stable release on, pre-releases publish under `next` again. + * * Usage: node build/resolve-npm-dist-tag.mjs */