fix(release): path-scoped npmrc + hard-fail publish (v0.14.3 retry)
v0.14.2 publish run reported "success" but @keisei/mcp-server NEVER landed on keigit because: 1. Host-scoped `.npmrc` token (`//keigit.com/:_authToken=...`) was silently ignored by npm 10 — every publish errored with ENEEDAUTH. 2. The publish loop's `|| echo ":⚠️:"` swallowed the failure so the job exited 0 (W1+W3 finding F3). Two fixes in one commit: A) Path-scoped npmrc per Forgejo docs: `//keigit.com/api/packages/keisei/npm/:_authToken=${KEIGIT_TOKEN}` + `always-auth=true` for scoped registry. Also tee'd to $HOME/.npmrc so the publish loop's `cd packages/<pkg>` cwd doesn't lose the auth line. [VERIFIED: curl PUT with Bearer to /api/packages/keisei/npm/ returns 400 "package is invalid" (auth ACCEPTED, payload bad) — auth format is correct] B) Hard-fail publish loop for packages with publishConfig: - Iterate all packages - For each: read .publishConfig presence - If publish errors AND has publishConfig → record gated_failed=1 - If publish errors AND no publishConfig → notice "skipped" (adapter without registry pin reached npm.org default, expected fail) - End of loop: exit 1 if any gated_failed - Adapters without publishConfig (gmail/grok/recall/telegram/youtube) correctly skip; only @keisei/mcp-server is gated, and a real failure now blocks the job. Bump 0.14.2 → 0.14.3 (0.14.2 tag exists with previous failed publish). Verification done locally: - PAT owner Parfionovich is member of org keisei [REAL: api/v1/user + api/v1/users/Parfionovich/orgs] - Bearer auth to keigit npm registry works [REAL: curl probe → 400 "package invalid", not 401 "unauthorized"] - Cargo workspace clean [REAL: cargo check exit 0] After tag v0.14.3: - npm-publish job creates .npmrc with path-scoped auth - Publishes @keisei/mcp-server@0.14.3 to https://keigit.com/api/packages/keisei/npm/ - Adapters skip cleanly (no publishConfig, no NPM_TOKEN) - Job exits 0 only if mcp-server actually landed Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3b8b726a1c
commit
a6948770d1
3 changed files with 36 additions and 15 deletions
47
.github/workflows/release.yml
vendored
47
.github/workflows/release.yml
vendored
|
|
@ -342,13 +342,21 @@ jobs:
|
|||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# v0.14.3 fix: path-scoped _authToken per Forgejo docs
|
||||
# (https://forgejo.org/docs/latest/user/packages/npm/). The prior
|
||||
# host-scoped form (`//keigit.com/:_authToken=...`) was silently
|
||||
# ignored by npm 10 → ENEEDAUTH. Path-scoped exactly matches the
|
||||
# @keisei:registry URL, so npm reliably resolves the token.
|
||||
# Also write to $HOME/.npmrc so it's found regardless of cwd
|
||||
# (the publish loop cd's into packages/<pkg>/).
|
||||
{
|
||||
echo "@keisei:registry=https://keigit.com/api/packages/keisei/npm/"
|
||||
echo "//keigit.com/:_authToken=${KEIGIT_TOKEN}"
|
||||
echo "//keigit.com/api/packages/keisei/npm/:_authToken=${KEIGIT_TOKEN}"
|
||||
echo "always-auth=true"
|
||||
if [ -n "${NPM_TOKEN:-}" ]; then
|
||||
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}"
|
||||
fi
|
||||
} > .npmrc
|
||||
} | tee "$HOME/.npmrc" > .npmrc
|
||||
# Sanity (no secrets in log — print only registry lines):
|
||||
grep -v _authToken .npmrc
|
||||
|
||||
|
|
@ -367,21 +375,34 @@ jobs:
|
|||
working-directory: _ts_packages
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# publishConfig.registry in each package.json decides destination.
|
||||
# Currently only @keisei/mcp-server has a publishConfig — the other
|
||||
# adapters skip publish (no registry pin → npm.org default → no
|
||||
# token in .npmrc → publish fails → ::warning emitted, job continues).
|
||||
# v0.14.3 fix (W1+W3 finding F3): hard-fail on a package WITH a
|
||||
# publishConfig.registry whose publish errored. Adapters without
|
||||
# publishConfig still skip gracefully (no registry pin → npm.org
|
||||
# default → ENEEDAUTH → counted as "skipped" not "failed").
|
||||
gated_failed=0
|
||||
for pkg in packages/*/; do
|
||||
if [ -f "$pkg/package.json" ]; then
|
||||
name=$(node -p "require('./$pkg/package.json').name")
|
||||
echo "::group::publish $name"
|
||||
( cd "$pkg" && npm publish --access public ) \
|
||||
|| echo "::warning::publish failed for $name (no registry pin, missing token, version conflict, or registry error — see log)"
|
||||
echo "::endgroup::"
|
||||
[ -f "$pkg/package.json" ] || continue
|
||||
name=$(node -p "require('./$pkg/package.json').name")
|
||||
has_pub=$(node -p "require('./$pkg/package.json').publishConfig ? '1' : '0'")
|
||||
echo "::group::publish $name"
|
||||
if ( cd "$pkg" && npm publish --access public ); then
|
||||
echo "::notice::published $name"
|
||||
else
|
||||
if [ "$has_pub" = "1" ]; then
|
||||
gated_failed=1
|
||||
echo "::error::publish FAILED for $name (has publishConfig — this is a real error, see log above)"
|
||||
else
|
||||
echo "::notice::publish skipped for $name (no publishConfig — npm.org default reached, ENEEDAUTH expected without NPM_TOKEN)"
|
||||
fi
|
||||
fi
|
||||
echo "::endgroup::"
|
||||
done
|
||||
if [ "$gated_failed" -ne 0 ]; then
|
||||
echo "::error::one or more packages with publishConfig failed to publish"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Cleanup .npmrc
|
||||
if: always()
|
||||
working-directory: _ts_packages
|
||||
run: rm -f .npmrc
|
||||
run: rm -f .npmrc "$HOME/.npmrc"
|
||||
|
|
|
|||
2
_ts_packages/package-lock.json
generated
2
_ts_packages/package-lock.json
generated
|
|
@ -3707,7 +3707,7 @@
|
|||
},
|
||||
"packages/mcp-server": {
|
||||
"name": "@keisei/mcp-server",
|
||||
"version": "0.14.2",
|
||||
"version": "0.14.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.0.0",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keisei/mcp-server",
|
||||
"version": "0.14.2",
|
||||
"version": "0.14.3",
|
||||
"description": "MCP server exposing KeiSeiKit Rust primitives as Model Context Protocol tools — published to keigit.com (Forgejo npm registry, public DNS)",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
|
|
|
|||
Loading…
Reference in a new issue