fix: verify npm package registration before release

This commit is contained in:
Armin Ronacher 2026-08-06 18:16:01 +02:00
parent 9b4f6a9e1f
commit 9b17fd5bb3

View file

@ -8,17 +8,18 @@
*
* Steps:
* 1. Check for uncommitted changes
* 2. Bump version via npm run version:xxx or set an explicit version
* 3. Update CHANGELOG.md files: [Unreleased] -> [version] - date
* 4. Regenerate release artifacts
* 5. Run checks and tests
* 6. Commit and tag the release
* 7. Add new [Unreleased] section to changelogs
* 8. Commit next-cycle changelog updates
* 9. Push main and the tag to trigger CI publishing
* 2. Verify every public workspace package is registered on npm
* 3. Bump version via npm run version:xxx or set an explicit version
* 4. Update CHANGELOG.md files: [Unreleased] -> [version] - date
* 5. Regenerate release artifacts
* 6. Run checks and tests
* 7. Commit and tag the release
* 8. Add new [Unreleased] section to changelogs
* 9. Commit next-cycle changelog updates
* 10. Push main and the tag to trigger CI publishing
*/
import { execSync } from "node:child_process";
import { execSync, spawnSync } from "node:child_process";
import { existsSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { findPackageDirectories } from "./package-workspaces.mjs";
@ -50,6 +51,41 @@ function getVersion() {
return pkg.version;
}
function assertPackagesAreRegisteredWithNpm() {
const packageNames = findPackageDirectories()
.map((directory) => JSON.parse(readFileSync(join(directory, "package.json"), "utf8")))
.filter((pkg) => pkg.private !== true)
.map((pkg) => pkg.name);
const unregisteredPackages = [];
console.log("Checking npm package registration...");
for (const packageName of packageNames) {
const result = spawnSync(process.platform === "win32" ? "npm.cmd" : "npm", ["view", packageName, "version", "--json"], {
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"],
});
if (result.status === 0 && result.stdout.trim()) {
console.log(` ${packageName}`);
continue;
}
const output = [result.stdout, result.stderr, result.error?.message].filter(Boolean).join("\n");
if (output.includes("E404") || output.includes("404 Not Found")) {
unregisteredPackages.push(packageName);
continue;
}
throw new Error(output ? `Failed to query npm registration for ${packageName}\n${output}` : `Failed to query npm registration for ${packageName}`);
}
if (unregisteredPackages.length > 0) {
throw new Error(`The following public workspace packages are not registered on npm:\n${unregisteredPackages.map((packageName) => ` ${packageName}`).join("\n")}\nRegister them before running a release.`);
}
console.log(" All public workspace packages are registered on npm\n");
}
function compareVersions(a, b) {
const aParts = a.split(".").map(Number);
const bParts = b.split(".").map(Number);
@ -190,16 +226,19 @@ if (status && status.trim()) {
}
console.log(" Working directory clean\n");
// 2. Bump or set version
// 2. Verify npm package registration before modifying the worktree.
assertPackagesAreRegisteredWithNpm();
// 3. Bump or set version
const version = bumpOrSetVersion(RELEASE_TARGET);
console.log(` New version: ${version}\n`);
// 3. Update changelogs
// 4. Update changelogs
console.log("Updating CHANGELOG.md files...");
updateChangelogsForRelease(version);
console.log();
// 4. Regenerate release artifacts
// 5. Regenerate release artifacts
console.log("Regenerating release artifacts...");
run("npm run generate:models");
run("npm run check:model-data");
@ -207,7 +246,7 @@ run("npm run shrinkwrap:coding-agent");
run("npm run install-lock:coding-agent");
console.log();
// 5. Run checks and tests
// 6. Run checks and tests
console.log("Running checks...");
run("npm run check");
console.log();
@ -220,25 +259,25 @@ console.log("Running tests...");
run("./test.sh");
console.log();
// 6. Commit and tag
// 7. Commit and tag
console.log("Committing and tagging...");
stageChangedFiles();
run(`git commit -m "Release v${version}"`);
run(`git tag v${version}`);
console.log();
// 7. Add new [Unreleased] sections
// 8. Add new [Unreleased] sections
console.log("Adding [Unreleased] sections for next cycle...");
addUnreleasedSection();
console.log();
// 8. Commit
// 9. Commit
console.log("Committing changelog updates...");
stageChangedFiles();
run(`git commit -m "Add [Unreleased] section for next cycle"`);
console.log();
// 9. Push
// 10. Push
console.log("Pushing to remote...");
run("git push origin main");
run(`git push origin v${version}`);