From ca99f78f666a50878807cce010f6109a67275119 Mon Sep 17 00:00:00 2001 From: Parfii-bot Date: Sun, 3 May 2026 23:48:07 +0800 Subject: [PATCH] fix(release): path-scoped npmrc + hard-fail publish (v0.14.3 retry) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 "::warning::"` 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/` 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) --- .github/workflows/release.yml | 47 ++++++++++++++----- _ts_packages/package-lock.json | 2 +- _ts_packages/packages/mcp-server/package.json | 2 +- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0388676..23b738f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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//). { 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" diff --git a/_ts_packages/package-lock.json b/_ts_packages/package-lock.json index 31898f0..eedbd9b 100644 --- a/_ts_packages/package-lock.json +++ b/_ts_packages/package-lock.json @@ -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", diff --git a/_ts_packages/packages/mcp-server/package.json b/_ts_packages/packages/mcp-server/package.json index 2d14aa3..7710752 100644 --- a/_ts_packages/packages/mcp-server/package.json +++ b/_ts_packages/packages/mcp-server/package.json @@ -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",