diff --git a/Makefile b/Makefile index 9e10253..646545d 100644 --- a/Makefile +++ b/Makefile @@ -89,14 +89,19 @@ npm-build: require-version ## Assemble npm/dist/ (CLI + mcp-server) from artifac .PHONY: npm-dry-run npm-dry-run: ## Dry-run publish every assembled package - @set -euo pipefail; for d in npm/dist/csdd-*/ npm/dist/csdd/; do \ + @set -euo pipefail; \ + if [ ! -f npm/dist/csdd/package.json ]; then echo "npm/dist not assembled — run: make npm-build VERSION=vX.Y.Z first" >&2; exit 1; fi; \ + for d in npm/dist/csdd-*/ npm/dist/csdd/; do \ + [ -f "$$d/package.json" ] || continue; \ echo "== $$d"; npm publish "$$d" --access public --dry-run; done .PHONY: npm-publish npm-publish: ## Publish the assembled packages (CLI + mcp-server), skips already-published; OTP=123456 if 2FA @set -euo pipefail; \ + if [ ! -f npm/dist/csdd/package.json ]; then echo "npm/dist not assembled — run: make dist VERSION=vX.Y.Z && make mcp-dist && make npm-build VERSION=vX.Y.Z" >&2; exit 1; fi; \ otp=; if [ -n "$(OTP)" ]; then otp="--otp=$(OTP)"; fi; \ for d in npm/dist/csdd-*/ npm/dist/csdd/; do \ + [ -f "$$d/package.json" ] || continue; \ name=$$(cd "$$d" && node -p "require('./package.json').name"); \ ver=$$(cd "$$d" && node -p "require('./package.json').version"); \ if npm view "$$name@$$ver" version >/dev/null 2>&1; then \ diff --git a/npm/scripts/build-packages.mjs b/npm/scripts/build-packages.mjs index 217f410..34756e9 100644 --- a/npm/scripts/build-packages.mjs +++ b/npm/scripts/build-packages.mjs @@ -53,6 +53,23 @@ const version = tag.replace(/^v/, ""); const artifactsDir = resolve(process.argv[3] ?? join(repoRoot, "artifacts")); const outDir = join(npmDir, "dist"); +// Preflight: every platform artifact must exist before we touch npm/dist, so a +// version mismatch (e.g. `npm-build VERSION=v0.1.2` against v0.1.1 tarballs) +// fails with a clear message instead of a cryptic tar/unzip error — and never +// wipes a good npm/dist or leaves a half-built one that breaks `npm-publish`. +const missingArtifacts = TARGETS.map((t) => { + const ext = t.goos === "windows" ? "zip" : "tar.gz"; + return join(artifactsDir, `csdd_${tag}_${t.goos}_${t.goarch}.${ext}`); +}).filter((f) => !existsSync(f)); +if (missingArtifacts.length > 0) { + console.error( + `error: missing release artifacts for ${tag} in ${artifactsDir}:\n` + + missingArtifacts.map((f) => " " + f).join("\n") + + `\nbuild them first: make dist VERSION=${tag}` + ); + process.exit(1); +} + rmSync(outDir, { recursive: true, force: true }); mkdirSync(outDir, { recursive: true });