From 8ed7f8ee93a2af51ed8f04c9b118b89aad51ee35 Mon Sep 17 00:00:00 2001 From: Isaac Bell <2613157+IsaacBell@users.noreply.github.com> Date: Fri, 2 Oct 2026 02:27:27 -0400 Subject: [PATCH] Check the npm login before publishing npm answers an upload without a valid login with 404, which only shows up after the full check suite has run. The publish task now checks the login first (pnpm whoami, then pnpm login if needed), then runs the checks. --- docs/RELEASING.md | 6 ++++-- mise.toml | 6 +++--- scripts/release.sh | 19 ++++++++++++++++++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/docs/RELEASING.md b/docs/RELEASING.md index c71ab11..c5e55f1 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -13,8 +13,10 @@ npm publish needs 2FA. mise run publish-dry-run apps/ ``` -3. Publish from a clean `main` (runs `mise run check` first, then `pnpm publish`, then tags - `@`): +3. Publish from a clean `main`. The task checks the npm login first (`pnpm whoami`; if it + fails, it runs `pnpm login` and checks again), so an expired login stops it in seconds, not + after the test suite. Then it runs `mise run check`, `pnpm publish`, and tags + `@`: ```bash mise run publish apps/ diff --git a/mise.toml b/mise.toml index f3dc92b..995a20e 100644 --- a/mise.toml +++ b/mise.toml @@ -87,9 +87,9 @@ description = "Audit local capture surfaces and browser extensions (macOS/Linux) run = "bash apps/am-i-being-recorded/bin/am-i-being-recorded.sh" [tasks.publish] -description = "Publish one package to npm (2FA), then tag it. Usage: mise run publish apps/" -depends = ["check"] -run = "bash scripts/release.sh publish" +description = "Check the npm login, run the checks, publish one package to npm (2FA), then tag it. Usage: mise run publish apps/" +raw = true +run = ["bash scripts/release.sh login", { task = "check" }, "bash scripts/release.sh publish"] [tasks.publish-dry-run] description = "List the files one package would publish. Usage: mise run publish-dry-run apps/" diff --git a/scripts/release.sh b/scripts/release.sh index ec6fd35..d64634a 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -2,6 +2,7 @@ # Release one package from this monorepo to npm. The name and version come from the # package's own package.json, so one script serves every package. # +# scripts/release.sh login # make sure npm is logged in (pnpm login if not) # scripts/release.sh dry-run apps/ # list the files that would ship # scripts/release.sh publish apps/ # publish (npm asks for 2FA), then tag # @@ -13,13 +14,28 @@ set -euo pipefail cd "$(dirname "$0")/.." +registry=https://registry.npmjs.org/ + die() { echo "release.sh: $*" >&2 exit 1 } +# npm answers an upload without a valid login with 404, not 401, so check before publishing. +ensure_login() { + pnpm whoami --registry "$registry" >/dev/null 2>&1 && return + echo "release.sh: not logged in to npm; running pnpm login" >&2 + pnpm login --registry "$registry" + pnpm whoami --registry "$registry" >/dev/null 2>&1 || die "still not logged in to npm" +} + +if [[ ${1:-} == login ]]; then + ensure_login + exit +fi + [[ $# -eq 2 ]] || { - echo "usage: release.sh dry-run|publish " >&2 + echo "usage: release.sh login | dry-run|publish " >&2 exit 2 } action=$1 @@ -42,6 +58,7 @@ dry-run) (cd "$dir" && pnpm pack --dry-run) ;; publish) + ensure_login if [[ -n "$(pnpm view "$name@$version" version 2>/dev/null)" ]]; then die "$name@$version is already on npm; bump the version in $pkg" fi