From 1706bfda2c003415024047acf8335e2d6349e4e5 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 20 Jun 2026 21:51:32 +0200 Subject: [PATCH] fix(release): validate plugin npm publish args --- scripts/plugin-npm-publish.sh | 32 +++++++++++++--- test/scripts/plugin-npm-publish.test.ts | 50 +++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 test/scripts/plugin-npm-publish.test.ts diff --git a/scripts/plugin-npm-publish.sh b/scripts/plugin-npm-publish.sh index 1821d69ab4a..b668ae04d15 100644 --- a/scripts/plugin-npm-publish.sh +++ b/scripts/plugin-npm-publish.sh @@ -2,18 +2,40 @@ set -euo pipefail -mode="${1:-}" -package_dir="${2:-}" +usage() { + echo "usage: bash scripts/plugin-npm-publish.sh [--dry-run|--pack-dry-run|--publish] " +} -if [[ "${mode}" != "--dry-run" && "${mode}" != "--pack-dry-run" && "${mode}" != "--publish" ]]; then - echo "usage: bash scripts/plugin-npm-publish.sh [--dry-run|--pack-dry-run|--publish] " >&2 - exit 2 +if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then + usage + exit 0 fi +mode="${1:-}" +if [[ "${mode}" != "--dry-run" && "${mode}" != "--pack-dry-run" && "${mode}" != "--publish" ]]; then + usage >&2 + exit 2 +fi +shift + +if [[ "${1:-}" == "--" ]]; then + shift +fi +package_dir="" +if [[ "$#" -gt 0 ]]; then + case "$1" in + -*) echo "unexpected plugin npm package-dir option: $1" >&2; exit 2 ;; + *) package_dir="$1"; shift ;; + esac +fi if [[ -z "${package_dir}" ]]; then echo "missing package dir" >&2 exit 2 fi +if [[ "$#" -gt 0 ]]; then + echo "unexpected plugin npm publish argument: $1" >&2 + exit 2 +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}")" diff --git a/test/scripts/plugin-npm-publish.test.ts b/test/scripts/plugin-npm-publish.test.ts new file mode 100644 index 00000000000..78f339b8caf --- /dev/null +++ b/test/scripts/plugin-npm-publish.test.ts @@ -0,0 +1,50 @@ +// Plugin NPM Publish tests cover publish wrapper argument safety. +import { spawnSync } from "node:child_process"; +import { describe, expect, it } from "vitest"; + +const scriptPath = "scripts/plugin-npm-publish.sh"; + +function runPluginPublishWrapper(args: string[]) { + return spawnSync("bash", [scriptPath, ...args], { + cwd: process.cwd(), + encoding: "utf8", + }); +} + +describe("plugin npm publish wrapper", () => { + it("prints help before package or npm checks", () => { + const result = runPluginPublishWrapper(["--help"]); + + expect(result.status).toBe(0); + expect(result.stdout.trim()).toBe( + "usage: bash scripts/plugin-npm-publish.sh [--dry-run|--pack-dry-run|--publish] ", + ); + expect(result.stderr).toBe(""); + }); + + it("rejects missing mode before package checks", () => { + const result = runPluginPublishWrapper([]); + + expect(result.status).toBe(2); + expect(result.stdout).toBe(""); + expect(result.stderr.trim()).toBe( + "usage: bash scripts/plugin-npm-publish.sh [--dry-run|--pack-dry-run|--publish] ", + ); + }); + + it("rejects option-like package dirs before package checks", () => { + const result = runPluginPublishWrapper(["--dry-run", "--wat"]); + + expect(result.status).toBe(2); + expect(result.stdout).toBe(""); + expect(result.stderr.trim()).toBe("unexpected plugin npm package-dir option: --wat"); + }); + + it("rejects extra arguments before package checks", () => { + const result = runPluginPublishWrapper(["--dry-run", "extensions/telegram", "extra"]); + + expect(result.status).toBe(2); + expect(result.stdout).toBe(""); + expect(result.stderr.trim()).toBe("unexpected plugin npm publish argument: extra"); + }); +});