mirror of
https://github.com/excalidraw/excalidraw
synced 2025-07-25 13:58:22 +08:00
chore: release multiple packages (#9698)
This commit is contained in:
@ -1,71 +0,0 @@
|
||||
const { exec, execSync } = require("child_process");
|
||||
const fs = require("fs");
|
||||
|
||||
const core = require("@actions/core");
|
||||
|
||||
const excalidrawDir = `${__dirname}/../packages/excalidraw`;
|
||||
const excalidrawPackage = `${excalidrawDir}/package.json`;
|
||||
const pkg = require(excalidrawPackage);
|
||||
const isPreview = process.argv.slice(2)[0] === "preview";
|
||||
|
||||
const getShortCommitHash = () => {
|
||||
return execSync("git rev-parse --short HEAD").toString().trim();
|
||||
};
|
||||
|
||||
const publish = () => {
|
||||
const tag = isPreview ? "preview" : "next";
|
||||
|
||||
try {
|
||||
execSync(`yarn --frozen-lockfile`);
|
||||
execSync(`yarn run build:esm`, { cwd: excalidrawDir });
|
||||
execSync(`yarn --cwd ${excalidrawDir} publish --tag ${tag}`);
|
||||
console.info(`Published ${pkg.name}@${tag}🎉`);
|
||||
core.setOutput(
|
||||
"result",
|
||||
`**Preview version has been shipped** :rocket:
|
||||
You can use [@excalidraw/excalidraw@${pkg.version}](https://www.npmjs.com/package/@excalidraw/excalidraw/v/${pkg.version}) for testing!`,
|
||||
);
|
||||
} catch (error) {
|
||||
core.setOutput("result", "package couldn't be published :warning:!");
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
// get files changed between prev and head commit
|
||||
exec(`git diff --name-only HEAD^ HEAD`, async (error, stdout, stderr) => {
|
||||
if (error || stderr) {
|
||||
console.error(error);
|
||||
core.setOutput("result", ":warning: Package couldn't be published!");
|
||||
process.exit(1);
|
||||
}
|
||||
const changedFiles = stdout.trim().split("\n");
|
||||
|
||||
const excalidrawPackageFiles = changedFiles.filter((file) => {
|
||||
return (
|
||||
file.indexOf("packages/excalidraw") >= 0 ||
|
||||
file.indexOf("buildPackage.js") > 0
|
||||
);
|
||||
});
|
||||
if (!excalidrawPackageFiles.length) {
|
||||
console.info("Skipping release as no valid diff found");
|
||||
core.setOutput("result", "Skipping release as no valid diff found");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// update package.json
|
||||
let version = `${pkg.version}-${getShortCommitHash()}`;
|
||||
|
||||
// update readme
|
||||
|
||||
if (isPreview) {
|
||||
// use pullNumber-commithash as the version for preview
|
||||
const pullRequestNumber = process.argv.slice(3)[0];
|
||||
version = `${pkg.version}-${pullRequestNumber}-${getShortCommitHash()}`;
|
||||
}
|
||||
pkg.version = version;
|
||||
|
||||
fs.writeFileSync(excalidrawPackage, JSON.stringify(pkg, null, 2), "utf8");
|
||||
|
||||
console.info("Publish in progress...");
|
||||
publish();
|
||||
});
|
@ -11,12 +11,9 @@ const getConfig = (outdir) => ({
|
||||
entryNames: "[name]",
|
||||
assetNames: "[dir]/[name]",
|
||||
alias: {
|
||||
"@excalidraw/common": path.resolve(__dirname, "../packages/common/src"),
|
||||
"@excalidraw/element": path.resolve(__dirname, "../packages/element/src"),
|
||||
"@excalidraw/excalidraw": path.resolve(__dirname, "../packages/excalidraw"),
|
||||
"@excalidraw/math": path.resolve(__dirname, "../packages/math/src"),
|
||||
"@excalidraw/utils": path.resolve(__dirname, "../packages/utils/src"),
|
||||
},
|
||||
external: ["@excalidraw/common", "@excalidraw/element", "@excalidraw/math"],
|
||||
});
|
||||
|
||||
function buildDev(config) {
|
||||
|
@ -28,12 +28,9 @@ const getConfig = (outdir) => ({
|
||||
assetNames: "[dir]/[name]",
|
||||
chunkNames: "[dir]/[name]-[hash]",
|
||||
alias: {
|
||||
"@excalidraw/common": path.resolve(__dirname, "../packages/common/src"),
|
||||
"@excalidraw/element": path.resolve(__dirname, "../packages/element/src"),
|
||||
"@excalidraw/excalidraw": path.resolve(__dirname, "../packages/excalidraw"),
|
||||
"@excalidraw/math": path.resolve(__dirname, "../packages/math/src"),
|
||||
"@excalidraw/utils": path.resolve(__dirname, "../packages/utils/src"),
|
||||
},
|
||||
external: ["@excalidraw/common", "@excalidraw/element", "@excalidraw/math"],
|
||||
loader: {
|
||||
".woff2": "file",
|
||||
},
|
||||
|
@ -1,38 +0,0 @@
|
||||
const fs = require("fs");
|
||||
const util = require("util");
|
||||
|
||||
const exec = util.promisify(require("child_process").exec);
|
||||
const updateChangelog = require("./updateChangelog");
|
||||
|
||||
const excalidrawDir = `${__dirname}/../packages/excalidraw/`;
|
||||
const excalidrawPackage = `${excalidrawDir}/package.json`;
|
||||
|
||||
const updatePackageVersion = (nextVersion) => {
|
||||
const pkg = require(excalidrawPackage);
|
||||
pkg.version = nextVersion;
|
||||
const content = `${JSON.stringify(pkg, null, 2)}\n`;
|
||||
fs.writeFileSync(excalidrawPackage, content, "utf-8");
|
||||
};
|
||||
|
||||
const prerelease = async (nextVersion) => {
|
||||
try {
|
||||
await updateChangelog(nextVersion);
|
||||
updatePackageVersion(nextVersion);
|
||||
await exec(`git add -u`);
|
||||
await exec(
|
||||
`git commit -m "docs: release @excalidraw/excalidraw@${nextVersion} 🎉"`,
|
||||
);
|
||||
|
||||
console.info("Done!");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
const nextVersion = process.argv.slice(2)[0];
|
||||
if (!nextVersion) {
|
||||
console.error("Pass the next version to release!");
|
||||
process.exit(1);
|
||||
}
|
||||
prerelease(nextVersion);
|
@ -1,28 +1,239 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const { execSync } = require("child_process");
|
||||
|
||||
const excalidrawDir = `${__dirname}/../packages/excalidraw`;
|
||||
const excalidrawPackage = `${excalidrawDir}/package.json`;
|
||||
const pkg = require(excalidrawPackage);
|
||||
const updateChangelog = require("./updateChangelog");
|
||||
|
||||
const publish = () => {
|
||||
try {
|
||||
console.info("Installing the dependencies in root folder...");
|
||||
execSync(`yarn --frozen-lockfile`);
|
||||
console.info("Installing the dependencies in excalidraw directory...");
|
||||
execSync(`yarn --frozen-lockfile`, { cwd: excalidrawDir });
|
||||
console.info("Building ESM Package...");
|
||||
execSync(`yarn run build:esm`, { cwd: excalidrawDir });
|
||||
console.info("Publishing the package...");
|
||||
execSync(`yarn --cwd ${excalidrawDir} publish`);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
// skipping utils for now, as it has independent release process
|
||||
const PACKAGES = ["common", "math", "element", "excalidraw"];
|
||||
const PACKAGES_DIR = path.resolve(__dirname, "../packages");
|
||||
|
||||
/**
|
||||
* Returns the arguments for the release script.
|
||||
*
|
||||
* Usage examples:
|
||||
* - yarn release --help -> prints this help message
|
||||
* - yarn release -> publishes `@excalidraw` packages with "test" tag and "-[hash]" version suffix
|
||||
* - yarn release --tag=test -> same as above
|
||||
* - yarn release --tag=next -> publishes `@excalidraw` packages with "next" tag and version "-[hash]" suffix
|
||||
* - yarn release --tag=next --non-interactive -> skips interactive prompts (runs on CI/CD), otherwise same as above
|
||||
* - yarn release --tag=latest --version=0.19.0 -> publishes `@excalidraw` packages with "latest" tag and version "0.19.0" & prepares changelog for the release
|
||||
*
|
||||
* @returns [tag, version, nonInteractive]
|
||||
*/
|
||||
const getArguments = () => {
|
||||
let tag = "test";
|
||||
let version = "";
|
||||
let nonInteractive = false;
|
||||
|
||||
for (const argument of process.argv.slice(2)) {
|
||||
if (/--help/.test(argument)) {
|
||||
console.info(`Available arguments:
|
||||
--tag=<tag> -> (optional) "test" (default), "next" for auto release, "latest" for stable release
|
||||
--version=<version> -> (optional) for "next" and "test", (required) for "latest" i.e. "0.19.0"
|
||||
--non-interactive -> (optional) disables interactive prompts`);
|
||||
|
||||
console.info(`\nUsage examples:
|
||||
- yarn release -> publishes \`@excalidraw\` packages with "test" tag and "-[hash]" version suffix
|
||||
- yarn release --tag=test -> same as above
|
||||
- yarn release --tag=next -> publishes \`@excalidraw\` packages with "next" tag and version "-[hash]" suffix
|
||||
- yarn release --tag=next --non-interactive -> skips interactive prompts (runs on CI/CD), otherwise same as above
|
||||
- yarn release --tag=latest --version=0.19.0 -> publishes \`@excalidraw\` packages with "latest" tag and version "0.19.0" & prepares changelog for the release`);
|
||||
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (/--tag=/.test(argument)) {
|
||||
tag = argument.split("=")[1];
|
||||
}
|
||||
|
||||
if (/--version=/.test(argument)) {
|
||||
version = argument.split("=")[1];
|
||||
}
|
||||
|
||||
if (/--non-interactive/.test(argument)) {
|
||||
nonInteractive = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (tag !== "latest" && tag !== "next" && tag !== "test") {
|
||||
console.error(`Unsupported tag "${tag}", use "latest", "next" or "test".`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (tag === "latest" && !version) {
|
||||
console.error("Pass the version to make the latest stable release!");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!version) {
|
||||
// set the next version based on the excalidraw package version + commit hash
|
||||
const excalidrawPackageVersion = require(getPackageJsonPath(
|
||||
"excalidraw",
|
||||
)).version;
|
||||
|
||||
const hash = getShortCommitHash();
|
||||
|
||||
if (!excalidrawPackageVersion.includes(hash)) {
|
||||
version = `${excalidrawPackageVersion}-${hash}`;
|
||||
} else {
|
||||
// ensuring idempotency
|
||||
version = excalidrawPackageVersion;
|
||||
}
|
||||
}
|
||||
|
||||
console.info(`Running with tag "${tag}" and version "${version}"...`);
|
||||
|
||||
return [tag, version, nonInteractive];
|
||||
};
|
||||
|
||||
const validatePackageName = (packageName) => {
|
||||
if (!PACKAGES.includes(packageName)) {
|
||||
console.error(`Package "${packageName}" not found!`);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
const release = () => {
|
||||
publish();
|
||||
console.info(`Published ${pkg.version}!`);
|
||||
const getPackageJsonPath = (packageName) => {
|
||||
validatePackageName(packageName);
|
||||
return path.resolve(PACKAGES_DIR, packageName, "package.json");
|
||||
};
|
||||
|
||||
release();
|
||||
const updatePackageJsons = (nextVersion) => {
|
||||
const packageJsons = new Map();
|
||||
|
||||
for (const packageName of PACKAGES) {
|
||||
const pkg = require(getPackageJsonPath(packageName));
|
||||
|
||||
pkg.version = nextVersion;
|
||||
|
||||
if (pkg.dependencies) {
|
||||
for (const dependencyName of PACKAGES) {
|
||||
if (!pkg.dependencies[`@excalidraw/${dependencyName}`]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pkg.dependencies[`@excalidraw/${dependencyName}`] = nextVersion;
|
||||
}
|
||||
}
|
||||
|
||||
packageJsons.set(packageName, `${JSON.stringify(pkg, null, 2)}\n`);
|
||||
}
|
||||
|
||||
// modify once, to avoid inconsistent state
|
||||
for (const packageName of PACKAGES) {
|
||||
const content = packageJsons.get(packageName);
|
||||
fs.writeFileSync(getPackageJsonPath(packageName), content, "utf-8");
|
||||
}
|
||||
};
|
||||
|
||||
const getShortCommitHash = () => {
|
||||
return execSync("git rev-parse --short HEAD").toString().trim();
|
||||
};
|
||||
|
||||
const askToCommit = (tag, nextVersion) => {
|
||||
if (tag !== "latest") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const rl = require("readline").createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
|
||||
rl.question(
|
||||
"Do you want to commit these changes to git? (Y/n): ",
|
||||
(answer) => {
|
||||
rl.close();
|
||||
|
||||
if (answer.toLowerCase() === "y") {
|
||||
execSync(`git add -u`);
|
||||
execSync(
|
||||
`git commit -m "chore: release @excalidraw/excalidraw@${nextVersion} 🎉"`,
|
||||
);
|
||||
} else {
|
||||
console.warn(
|
||||
"Skipping commit. Don't forget to commit manually later!",
|
||||
);
|
||||
}
|
||||
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const buildPackages = () => {
|
||||
console.info("Running yarn install...");
|
||||
execSync(`yarn --frozen-lockfile`, { stdio: "inherit" });
|
||||
|
||||
console.info("Removing existing build artifacts...");
|
||||
execSync(`yarn rm:build`, { stdio: "inherit" });
|
||||
|
||||
for (const packageName of PACKAGES) {
|
||||
console.info(`Building "@excalidraw/${packageName}"...`);
|
||||
execSync(`yarn run build:esm`, {
|
||||
cwd: path.resolve(PACKAGES_DIR, packageName),
|
||||
stdio: "inherit",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const askToPublish = (tag, version) => {
|
||||
return new Promise((resolve) => {
|
||||
const rl = require("readline").createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
|
||||
rl.question(
|
||||
"Do you want to publish these changes to npm? (Y/n): ",
|
||||
(answer) => {
|
||||
rl.close();
|
||||
|
||||
if (answer.toLowerCase() === "y") {
|
||||
publishPackages(tag, version);
|
||||
} else {
|
||||
console.info("Skipping publish.");
|
||||
}
|
||||
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const publishPackages = (tag, version) => {
|
||||
for (const packageName of PACKAGES) {
|
||||
execSync(`yarn publish --tag ${tag}`, {
|
||||
cwd: path.resolve(PACKAGES_DIR, packageName),
|
||||
stdio: "inherit",
|
||||
});
|
||||
|
||||
console.info(
|
||||
`Published "@excalidraw/${packageName}@${tag}" with version "${version}"! 🎉`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/** main */
|
||||
(async () => {
|
||||
const [tag, version, nonInteractive] = getArguments();
|
||||
|
||||
buildPackages();
|
||||
|
||||
if (tag === "latest") {
|
||||
await updateChangelog(version);
|
||||
}
|
||||
|
||||
updatePackageJsons(version);
|
||||
|
||||
if (nonInteractive) {
|
||||
publishPackages(tag, version);
|
||||
} else {
|
||||
await askToCommit(tag, version);
|
||||
await askToPublish(tag, version);
|
||||
}
|
||||
})();
|
||||
|
@ -20,14 +20,16 @@ const headerForType = {
|
||||
perf: "Performance",
|
||||
build: "Build",
|
||||
};
|
||||
|
||||
const badCommits = [];
|
||||
const getCommitHashForLastVersion = async () => {
|
||||
try {
|
||||
const commitMessage = `"release @excalidraw/excalidraw@${lastVersion}"`;
|
||||
const commitMessage = `"release @excalidraw/excalidraw"`;
|
||||
const { stdout } = await exec(
|
||||
`git log --format=format:"%H" --grep=${commitMessage}`,
|
||||
);
|
||||
return stdout;
|
||||
// take commit hash from latest release
|
||||
return stdout.split(/\r?\n/)[0];
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
Reference in New Issue
Block a user