2025-08-27 09:24:46 +00:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
|
2025-11-26 02:30:44 +00:00
|
|
|
import { execSync } from "child_process";
|
|
|
|
|
import { readFileSync } from "fs";
|
|
|
|
|
import semver from "semver";
|
2025-08-27 09:24:46 +00:00
|
|
|
|
|
|
|
|
// Get the current version from package.json
|
2025-11-26 02:30:44 +00:00
|
|
|
const packageJson = JSON.parse(readFileSync("package.json", "utf8"));
|
2025-08-27 09:24:46 +00:00
|
|
|
const currentVersion = packageJson.version;
|
|
|
|
|
|
2025-08-27 09:27:21 +00:00
|
|
|
// Get the latest tag version
|
|
|
|
|
let latestTag = null;
|
|
|
|
|
try {
|
2025-11-26 02:30:44 +00:00
|
|
|
const tagOutput = execSync("git tag -l --sort=-v:refname", {
|
|
|
|
|
encoding: "utf8",
|
|
|
|
|
}).trim();
|
2025-08-27 09:27:21 +00:00
|
|
|
if (tagOutput) {
|
2025-11-26 02:30:44 +00:00
|
|
|
// Get first line (latest tag) - cross-platform compatible
|
|
|
|
|
latestTag = tagOutput.split("\n")[0].replace(/^v/, "");
|
2025-08-27 09:27:21 +00:00
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
// No tags found
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check for version mismatch warning
|
|
|
|
|
if (latestTag && semver.gt(latestTag, currentVersion)) {
|
2025-11-26 02:30:44 +00:00
|
|
|
console.warn(
|
|
|
|
|
`⚠️ Warning: package.json version (${currentVersion}) is behind latest tag (${latestTag})`
|
|
|
|
|
);
|
2025-08-27 09:27:21 +00:00
|
|
|
console.warn(` You may want to sync package.json version first.`);
|
2025-11-26 02:30:44 +00:00
|
|
|
console.log("");
|
2025-08-27 09:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
2025-08-27 12:18:22 +00:00
|
|
|
// Parse command line arguments (support flags like --dry-run anywhere)
|
2025-09-24 02:44:51 +00:00
|
|
|
// Filter out the '--' separator that npm/pnpm uses for argument passing
|
2025-11-26 02:30:44 +00:00
|
|
|
const args = process.argv.slice(2).filter((arg) => arg !== "--");
|
|
|
|
|
const knownIncrements = new Set(["patch", "minor", "major", "continue"]);
|
2025-08-27 12:18:22 +00:00
|
|
|
let increment = undefined;
|
|
|
|
|
const argParts = [];
|
|
|
|
|
for (const a of args) {
|
|
|
|
|
if (knownIncrements.has(a) && !increment) increment = a;
|
|
|
|
|
else argParts.push(a);
|
|
|
|
|
}
|
2025-08-27 09:24:46 +00:00
|
|
|
|
|
|
|
|
// Check if we're already on a beta version
|
|
|
|
|
const isCurrentlyBeta = semver.prerelease(currentVersion) !== null;
|
|
|
|
|
|
2025-08-27 12:04:27 +00:00
|
|
|
let releaseCommand = null;
|
2025-08-27 09:24:46 +00:00
|
|
|
|
2025-11-26 02:30:44 +00:00
|
|
|
if (isCurrentlyBeta && (!increment || increment === "continue")) {
|
2025-08-27 12:04:27 +00:00
|
|
|
// If already on beta and no increment specified, just bump the prerelease number
|
2025-08-27 09:24:46 +00:00
|
|
|
console.log(`📦 Current version: ${currentVersion} (beta)`);
|
2025-11-26 02:30:44 +00:00
|
|
|
console.log("🔄 Continuing beta sequence...");
|
2025-08-27 12:04:27 +00:00
|
|
|
// Use a special config without preRelease to continue existing beta sequence cleanly
|
2025-11-26 02:30:44 +00:00
|
|
|
releaseCommand =
|
|
|
|
|
"npx release-it --config .release-it.beta-continue.cjs prerelease";
|
|
|
|
|
} else if (
|
|
|
|
|
increment === "patch" ||
|
|
|
|
|
increment === "minor" ||
|
|
|
|
|
increment === "major"
|
|
|
|
|
) {
|
2025-08-27 09:24:46 +00:00
|
|
|
// If increment is specified, create new beta.0 for that version
|
|
|
|
|
console.log(`📦 Current version: ${currentVersion}`);
|
|
|
|
|
console.log(`🚀 Creating new ${increment} beta version...`);
|
2025-08-27 12:04:27 +00:00
|
|
|
releaseCommand = `npx release-it --config .release-it.beta.cjs ${increment} --preRelease=beta`;
|
2025-08-27 09:24:46 +00:00
|
|
|
} else if (!isCurrentlyBeta) {
|
|
|
|
|
// If not on beta and no increment, default to patch
|
|
|
|
|
console.log(`📦 Current version: ${currentVersion} (stable)`);
|
2025-11-26 02:30:44 +00:00
|
|
|
console.log("🚀 Creating new patch beta version...");
|
|
|
|
|
releaseCommand =
|
|
|
|
|
"npx release-it --config .release-it.beta.cjs patch --preRelease=beta";
|
2025-08-27 09:24:46 +00:00
|
|
|
} else {
|
|
|
|
|
// Default to continuing prerelease
|
|
|
|
|
console.log(`📦 Current version: ${currentVersion} (beta)`);
|
2025-11-26 02:30:44 +00:00
|
|
|
console.log("🔄 Continuing beta sequence...");
|
|
|
|
|
releaseCommand =
|
|
|
|
|
"npx release-it --config .release-it.beta-continue.cjs prerelease";
|
2025-08-27 09:24:46 +00:00
|
|
|
}
|
|
|
|
|
|
2025-08-27 12:18:22 +00:00
|
|
|
// Add any additional arguments and ensure --dry-run passes through to release-it
|
2025-11-26 02:30:44 +00:00
|
|
|
let additionalArgs = argParts.join(" ");
|
2025-08-27 09:24:46 +00:00
|
|
|
if (additionalArgs) {
|
2025-11-26 02:30:44 +00:00
|
|
|
releaseCommand += " " + additionalArgs;
|
2025-08-27 09:24:46 +00:00
|
|
|
}
|
2025-08-27 14:20:10 +00:00
|
|
|
// If this is a dry-run, relax git cleanliness requirements to avoid false negatives
|
2025-11-26 02:30:44 +00:00
|
|
|
if (argParts.includes("--dry-run")) {
|
|
|
|
|
releaseCommand +=
|
|
|
|
|
" --no-git.requireCleanWorkingDir --no-git.requireUpstream";
|
2025-08-27 14:20:10 +00:00
|
|
|
}
|
2025-08-27 09:24:46 +00:00
|
|
|
|
|
|
|
|
console.log(`\n📝 Executing: ${releaseCommand}\n`);
|
|
|
|
|
|
2025-08-27 14:20:10 +00:00
|
|
|
// Pass dry-run env flag downstream so hooks can skip writes
|
2025-11-26 02:30:44 +00:00
|
|
|
const __dry =
|
|
|
|
|
args.includes("--dry-run") ||
|
|
|
|
|
(additionalArgs && additionalArgs.includes("--dry-run"));
|
|
|
|
|
if (__dry) process.env.RELEASE_IT_DRY_RUN = "1";
|
2025-08-27 14:20:10 +00:00
|
|
|
|
|
|
|
|
// NOTE: In dry-run we want hooks to no-op; we propagate a flag via env
|
|
|
|
|
|
2025-08-27 09:24:46 +00:00
|
|
|
try {
|
2025-11-26 02:30:44 +00:00
|
|
|
// (dry-run) pass env flag to hooks
|
2025-08-27 14:20:10 +00:00
|
|
|
|
2025-11-26 02:30:44 +00:00
|
|
|
execSync(releaseCommand, { stdio: "inherit" });
|
2025-08-27 09:24:46 +00:00
|
|
|
} catch (error) {
|
2025-11-26 02:30:44 +00:00
|
|
|
console.error("❌ Release failed:", error.message);
|
2025-08-27 09:24:46 +00:00
|
|
|
process.exit(1);
|
2025-11-26 02:30:44 +00:00
|
|
|
}
|