fix(release): name the registry on every npm call

The 0.6.93 publish job got all the way to the end — notes verified, GitHub
release created with 28 assets, Homebrew formula published — and then died on
`npm whoami` with "npm auth failed", while the dedicated npm-auth-check job had
validated the very same token an hour earlier in the same run.

Both were right. They were talking to different registries.

The repo's root .npmrc sets `registry=https://pkg.hanzo.ai/`, and npm gives the
project file precedence over the user config that setup-node writes. So a bare
`npm whoami` at the repo root asks our own registry to validate an npmjs token.
pkg.hanzo.ai answers 200 with a body of `{}`. Older npm shrugged at that — which
is why this step passed for 0.6.92 eight hours earlier — and the npm that ships
with Node 24 reads it as "not logged in". The runners moved to Node 24 in
between; the deprecation notice is in both logs.

The publishes themselves were never affected, because each one runs `cd` into a
package directory and npm does not search parent directories for .npmrc — so
they used the user config and reached npmjs. That is a coincidence holding up
the supply chain, not a design.

So: name the registry on every npm call that talks to npmjs — whoami, publish,
and the `npm view` probes that decide whether a version is already published
and what the next version should be. Those last ones matter as much: they were
asking a proxy what npmjs contains, and the answer gates both the version bump
and the skip-if-already-published check.

Also stopped swallowing npm's own error in the publish job's whoami. The generic
"npm auth failed" message sent a real investigation toward the token, which was
fine the whole time.

Verified: cargo nextest run -p code-core --test hanzo_identity -> 4/4 pass;
the workflow still parses and all six jobs are intact.
This commit is contained in:
2026-08-06 23:25:37 -07:00
parent 04bae931a1
commit c74dc19e97
+24 -10
View File
@@ -61,7 +61,13 @@ jobs:
echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" > ~/.npmrc
if npm whoami >/dev/null 2>&1; then
# --registry is load-bearing: the repo's root .npmrc sets
# registry=https://pkg.hanzo.ai/, and npm gives the project file
# precedence over the user config setup-node writes. A bare
# `npm whoami` therefore asks OUR registry to validate an npmjs
# token; pkg.hanzo.ai answers 200 with a body of `{}`, which older
# npm tolerated and the npm on Node 24 reads as "not logged in".
if npm whoami --registry=https://registry.npmjs.org/ >/dev/null 2>&1; then
echo "npm auth ok"
else
echo "::error::npm auth failed (npm whoami). Ensure NPM_TOKEN is a granular/automation token with publish rights to @hanzo/*, bypass 2FA enabled: https://docs.npmjs.com/creating-and-viewing-access-tokens#creating-access-tokens ; update the secret: https://github.com/organizations/hanzoai/settings/secrets/actions/NPM_TOKEN" >&2
@@ -206,7 +212,7 @@ jobs:
# Find the highest published version across all packages
MAX_PUBLISHED="0.0.0"
for p in "${PKGS[@]}"; do
v=$(npm view "$p" version 2>/dev/null || echo "0.0.0")
v=$(npm view "$p" version --registry=https://registry.npmjs.org/ 2>/dev/null || echo "0.0.0")
if [ "$(printf '%s\n%s\n' "$MAX_PUBLISHED" "$v" | sort -V | tail -n1)" != "$MAX_PUBLISHED" ]; then
MAX_PUBLISHED="$v"
fi
@@ -221,7 +227,7 @@ jobs:
while :; do
used=false
for p in "${PKGS[@]}"; do
if [ "$(npm view "$p@$CANDIDATE" version 2>/dev/null || true)" = "$CANDIDATE" ]; then
if [ "$(npm view "$p@$CANDIDATE" version --registry=https://registry.npmjs.org/ 2>/dev/null || true)" = "$CANDIDATE" ]; then
used=true; break
fi
done
@@ -908,7 +914,7 @@ jobs:
set -euo pipefail
for dir in npm-binaries/*; do
echo "Publishing $(basename "$dir")"
(cd "$dir" && npm publish --access public)
(cd "$dir" && npm publish --access public --registry=https://registry.npmjs.org/)
done
- name: Sync README for npm
@@ -1372,19 +1378,23 @@ jobs:
config_path="${NPM_CONFIG_USERCONFIG:-$HOME/.npmrc}"
mkdir -p "$(dirname "$config_path")"
echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" > "$config_path"
npm whoami >/dev/null 2>&1 || { echo "npm auth failed (npm whoami). Ensure NPM_TOKEN is a granular/automation token with publish rights to @hanzo/* and bypass 2FA enabled; update the secret via npmjs.com." >&2; exit 1; }
# See the note in the npm-auth-check job: the root .npmrc points npm
# at pkg.hanzo.ai, so this must name npmjs explicitly or it validates
# the token against the wrong registry. Show npm's own error rather
# than swallowing it into a generic message.
npm whoami --registry=https://registry.npmjs.org/ || { echo "npm auth failed (npm whoami). Ensure NPM_TOKEN is a granular/automation token with publish rights to @hanzo/* and bypass 2FA enabled; update the secret via npmjs.com." >&2; exit 1; }
shopt -s nullglob
for dir in npm-binaries/*; do
name=$(jq -r '.name' "$dir/package.json")
version=$(jq -r '.version' "$dir/package.json")
echo "Preparing to publish $name@$version"
existing=$(npm view "$name@$version" version 2>/dev/null || true)
existing=$(npm view "$name@$version" version --registry=https://registry.npmjs.org/ 2>/dev/null || true)
if [ "$existing" = "$version" ]; then
echo "Skip: $name@$version already published"
continue
fi
echo "Publishing $(basename "$dir")"
(cd "$dir" && npm publish --access public)
(cd "$dir" && npm publish --access public --registry=https://registry.npmjs.org/)
done
- name: Publish main npm package (last)
@@ -1398,13 +1408,17 @@ jobs:
config_path="${NPM_CONFIG_USERCONFIG:-$HOME/.npmrc}"
mkdir -p "$(dirname "$config_path")"
echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" > "$config_path"
npm whoami >/dev/null 2>&1 || { echo "npm auth failed (npm whoami). Ensure NPM_TOKEN is a granular/automation token with publish rights to @hanzo/* and bypass 2FA enabled; update the secret via npmjs.com." >&2; exit 1; }
# See the note in the npm-auth-check job: the root .npmrc points npm
# at pkg.hanzo.ai, so this must name npmjs explicitly or it validates
# the token against the wrong registry. Show npm's own error rather
# than swallowing it into a generic message.
npm whoami --registry=https://registry.npmjs.org/ || { echo "npm auth failed (npm whoami). Ensure NPM_TOKEN is a granular/automation token with publish rights to @hanzo/* and bypass 2FA enabled; update the secret via npmjs.com." >&2; exit 1; }
name="@hanzo/dev"
version=$(jq -r '.version' package.json)
echo "Preparing to publish $name@$version"
existing=$(npm view "$name@$version" version 2>/dev/null || true)
existing=$(npm view "$name@$version" version --registry=https://registry.npmjs.org/ 2>/dev/null || true)
if [ "$existing" = "$version" ]; then
echo "Skip: $name@$version already published"
exit 0
fi
npm publish --access public
npm publish --access public --registry=https://registry.npmjs.org/