fix(ci): allow plugin npm preview without publish token (#58929)

This commit is contained in:
Vincent Koc
2026-04-01 19:16:46 +09:00
committed by GitHub
parent d766bfc6b2
commit f1595f59b4
3 changed files with 99 additions and 9 deletions

View File

@@ -30,6 +30,10 @@ const CORRECTION_VERSION_REGEX =
* @property {"node-auth-token" | "npm-token" | "none"} source
*/
/**
* @typedef {"--dry-run" | "--publish"} NpmPublishMode
*/
/**
* @param {string} version
* @param {Record<string, string | undefined>} groups
@@ -201,3 +205,19 @@ export function resolveNpmDistTagMirrorAuth(params = {}) {
return { hasAuth: false, source: "none" };
}
/**
* @param {{
* mode: NpmPublishMode;
* mirrorDistTags: string[] | readonly string[];
* hasAuth: boolean;
* }} params
* @returns {boolean}
*/
export function shouldRequireNpmDistTagMirrorAuth(params) {
return (
params.mode === "--publish" &&
params.mirrorDistTags.some((distTag) => distTag.trim().length > 0) &&
!params.hasAuth
);
}

View File

@@ -18,11 +18,12 @@ fi
package_name="$(node -e 'const pkg = require(require("node:path").resolve(process.argv[1], "package.json")); console.log(pkg.name)' "${package_dir}")"
package_version="$(node -e 'const pkg = require(require("node:path").resolve(process.argv[1], "package.json")); console.log(pkg.version)' "${package_dir}")"
current_beta_version="$(npm view "${package_name}" dist-tags.beta 2>/dev/null || true)"
mapfile -t publish_plan < <(
PACKAGE_VERSION="${package_version}" CURRENT_BETA_VERSION="${current_beta_version}" node --input-type=module <<'EOF'
publish_plan_output="$(
PACKAGE_VERSION="${package_version}" CURRENT_BETA_VERSION="${current_beta_version}" PUBLISH_MODE="${mode}" node --input-type=module <<'EOF'
import {
resolveNpmDistTagMirrorAuth,
resolveNpmPublishPlan,
shouldRequireNpmDistTagMirrorAuth,
} from "./scripts/lib/npm-publish-plan.mjs";
const plan = resolveNpmPublishPlan(
@@ -33,17 +34,25 @@ const auth = resolveNpmDistTagMirrorAuth({
nodeAuthToken: process.env.NODE_AUTH_TOKEN,
npmToken: process.env.NPM_TOKEN,
});
const shouldRequireMirrorAuth = shouldRequireNpmDistTagMirrorAuth({
mode: process.env.PUBLISH_MODE === "--publish" ? "--publish" : "--dry-run",
mirrorDistTags: plan.mirrorDistTags,
hasAuth: auth.hasAuth,
});
console.log(plan.channel);
console.log(plan.publishTag);
console.log(plan.mirrorDistTags.join(","));
console.log(auth.source);
console.log(shouldRequireMirrorAuth ? "required" : "optional");
EOF
)
release_channel="${publish_plan[0]}"
publish_tag="${publish_plan[1]}"
mirror_dist_tags_csv="${publish_plan[2]:-}"
mirror_auth_source="${publish_plan[3]:-none}"
)"
release_channel="$(printf '%s\n' "${publish_plan_output}" | sed -n '1p')"
publish_tag="$(printf '%s\n' "${publish_plan_output}" | sed -n '2p')"
mirror_dist_tags_csv="$(printf '%s\n' "${publish_plan_output}" | sed -n '3p')"
mirror_auth_source="$(printf '%s\n' "${publish_plan_output}" | sed -n '4p')"
mirror_auth_requirement="$(printf '%s\n' "${publish_plan_output}" | sed -n '5p')"
mirror_auth_source="${mirror_auth_source:-none}"
mirror_auth_requirement="${mirror_auth_requirement:-optional}"
publish_cmd=(npm publish --access public --tag "${publish_tag}" --provenance)
echo "Resolved package dir: ${package_dir}"
@@ -55,6 +64,7 @@ echo "Resolved publish tag: ${publish_tag}"
echo "Resolved mirror dist-tags: ${mirror_dist_tags_csv:-<none>}"
echo "Publish auth: GitHub OIDC trusted publishing"
echo "Mirror dist-tag auth source: ${mirror_auth_source}"
echo "Mirror dist-tag auth requirement: ${mirror_auth_requirement}"
mirror_auth_token=""
case "${mirror_auth_source}" in
@@ -66,7 +76,7 @@ case "${mirror_auth_source}" in
;;
esac
if [[ -n "${mirror_dist_tags_csv}" && -z "${mirror_auth_token}" ]]; then
if [[ "${mirror_auth_requirement}" == "required" && -z "${mirror_auth_token}" ]]; then
echo "npm dist-tag mirroring requires explicit npm auth via NODE_AUTH_TOKEN or NPM_TOKEN." >&2
echo "Refusing publish before npm latest/beta promotion can diverge." >&2
exit 1

View File

@@ -0,0 +1,60 @@
import { describe, expect, it } from "vitest";
import {
resolveNpmDistTagMirrorAuth,
resolveNpmPublishPlan,
shouldRequireNpmDistTagMirrorAuth,
} from "../scripts/lib/npm-publish-plan.mjs";
describe("shouldRequireNpmDistTagMirrorAuth", () => {
it("does not require npm auth for dry-run preview commands", () => {
const plan = resolveNpmPublishPlan("2026.4.1");
const auth = resolveNpmDistTagMirrorAuth({});
expect(
shouldRequireNpmDistTagMirrorAuth({
mode: "--dry-run",
mirrorDistTags: plan.mirrorDistTags,
hasAuth: auth.hasAuth,
}),
).toBe(false);
});
it("requires npm auth for real publishes that mirror dist-tags", () => {
const plan = resolveNpmPublishPlan("2026.4.1");
const auth = resolveNpmDistTagMirrorAuth({});
expect(
shouldRequireNpmDistTagMirrorAuth({
mode: "--publish",
mirrorDistTags: plan.mirrorDistTags,
hasAuth: auth.hasAuth,
}),
).toBe(true);
});
it("does not require auth when there are no mirror dist-tags", () => {
const plan = resolveNpmPublishPlan("2026.4.1-beta.1");
const auth = resolveNpmDistTagMirrorAuth({});
expect(
shouldRequireNpmDistTagMirrorAuth({
mode: "--publish",
mirrorDistTags: plan.mirrorDistTags,
hasAuth: auth.hasAuth,
}),
).toBe(false);
});
it("does not require auth when a publish already has npm auth", () => {
const plan = resolveNpmPublishPlan("2026.4.1");
const auth = resolveNpmDistTagMirrorAuth({ npmToken: "token" });
expect(
shouldRequireNpmDistTagMirrorAuth({
mode: "--publish",
mirrorDistTags: plan.mirrorDistTags,
hasAuth: auth.hasAuth,
}),
).toBe(false);
});
});