2023-04-03 10:52:27 +00:00
|
|
|
import cp from "child_process";
|
2023-03-29 08:36:37 +00:00
|
|
|
import fs from "fs";
|
|
|
|
import path from "path";
|
|
|
|
import { fileURLToPath } from "url";
|
2023-04-03 10:52:27 +00:00
|
|
|
import { promisify } from "util";
|
2023-03-29 08:36:37 +00:00
|
|
|
|
|
|
|
const PACKAGE_JSON = "package.json";
|
|
|
|
// hack to get __dirname
|
|
|
|
const DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
|
|
|
2023-11-01 15:15:24 +00:00
|
|
|
const NEXT_TAG = "next";
|
|
|
|
const LATEST_TAG = "latest";
|
|
|
|
const CURRENT_TAG = readPublishTag();
|
|
|
|
|
2023-03-29 08:36:37 +00:00
|
|
|
const exec = promisify(cp.exec);
|
|
|
|
const readFile = promisify(fs.readFile);
|
2023-11-01 15:15:24 +00:00
|
|
|
const writeFile = promisify(fs.writeFile);
|
2023-03-29 08:36:37 +00:00
|
|
|
|
|
|
|
run()
|
|
|
|
.then(() => {
|
|
|
|
console.info("Successfully published packages.");
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.error("Failed at publishing packages with ", err.message);
|
|
|
|
});
|
|
|
|
|
|
|
|
async function run() {
|
|
|
|
const rootPackage = await readJSON(path.resolve(DIR, "../", PACKAGE_JSON));
|
|
|
|
const workspacePaths = rootPackage.workspaces;
|
|
|
|
|
2023-11-01 15:15:24 +00:00
|
|
|
if (CURRENT_TAG === NEXT_TAG) {
|
|
|
|
await makeReleaseCandidate();
|
|
|
|
}
|
2023-03-29 08:36:37 +00:00
|
|
|
|
2023-11-01 15:15:24 +00:00
|
|
|
const workspaces = await Promise.all(workspacePaths.map(readWorkspace));
|
2023-03-29 08:36:37 +00:00
|
|
|
|
2023-11-01 15:15:24 +00:00
|
|
|
if (CURRENT_TAG === NEXT_TAG) {
|
|
|
|
await upgradeWakuDependencies(workspaces);
|
|
|
|
}
|
2023-03-29 08:36:37 +00:00
|
|
|
|
|
|
|
await Promise.all(
|
|
|
|
workspaces
|
2023-11-01 15:15:24 +00:00
|
|
|
.filter(async (info) => {
|
|
|
|
const allowPublishing = await shouldBePublished(info);
|
|
|
|
|
|
|
|
if (allowPublishing) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
})
|
2023-03-29 08:36:37 +00:00
|
|
|
.map(async (info) => {
|
|
|
|
try {
|
|
|
|
await exec(
|
2023-11-01 15:15:24 +00:00
|
|
|
`npm publish --workspace ${info.workspace} --tag ${CURRENT_TAG} --access public`
|
2023-03-29 08:36:37 +00:00
|
|
|
);
|
|
|
|
console.info(
|
2023-04-03 10:52:27 +00:00
|
|
|
`Successfully published ${info.workspace} with version ${info.version}.`
|
2023-03-29 08:36:37 +00:00
|
|
|
);
|
|
|
|
} catch (err) {
|
|
|
|
console.error(
|
|
|
|
`Cannot publish ${info.workspace} with version ${info.version}. Error: ${err.message}`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readJSON(path) {
|
|
|
|
const rawJSON = await readFile(path, "utf-8");
|
|
|
|
return JSON.parse(rawJSON);
|
|
|
|
}
|
|
|
|
|
2023-11-01 15:15:24 +00:00
|
|
|
async function writeWorkspace(packagePath, text) {
|
|
|
|
const resolvedPath = path.resolve(DIR, "../", packagePath, PACKAGE_JSON);
|
|
|
|
await writeFile(resolvedPath, text);
|
|
|
|
}
|
|
|
|
|
2023-03-29 08:36:37 +00:00
|
|
|
async function readWorkspace(packagePath) {
|
|
|
|
const json = await readJSON(
|
|
|
|
path.resolve(DIR, "../", packagePath, PACKAGE_JSON)
|
|
|
|
);
|
|
|
|
|
|
|
|
return {
|
|
|
|
name: json.name,
|
|
|
|
private: !!json.private,
|
|
|
|
version: json.version,
|
2023-11-01 15:15:24 +00:00
|
|
|
workspace: packagePath,
|
|
|
|
rawPackageJson: json
|
2023-03-29 08:36:37 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
async function shouldBePublished(info) {
|
|
|
|
if (info.private) {
|
2023-11-01 15:15:24 +00:00
|
|
|
console.info(`Skipping ${info.name} because it is private.`);
|
2023-03-29 08:36:37 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
const npmTag = `${info.name}@${info.version}`;
|
|
|
|
const { stdout } = await exec(`npm view ${npmTag} version`);
|
|
|
|
|
|
|
|
if (stdout.trim() !== info.version.trim()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
console.info(`Workspace ${info.path} is already published.`);
|
|
|
|
} catch (err) {
|
|
|
|
if (err.message.includes("code E404")) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
console.error(
|
|
|
|
`Cannot check published version of ${info.path}. Received error: ${err.message}`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2023-11-01 15:15:24 +00:00
|
|
|
|
|
|
|
async function makeReleaseCandidate() {
|
|
|
|
try {
|
|
|
|
console.info("Marking workspace versions as release candidates.");
|
|
|
|
await exec(
|
|
|
|
`npm version prerelease --preid $(git rev-parse --short HEAD) --workspaces true`
|
|
|
|
);
|
|
|
|
} catch (e) {
|
|
|
|
console.error("Failed to mark release candidate versions.", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function readPublishTag() {
|
|
|
|
const args = process.argv.slice(2);
|
|
|
|
const tagIndex = args.indexOf("--tag");
|
|
|
|
|
|
|
|
if (tagIndex !== -1 && args[tagIndex + 1]) {
|
|
|
|
return args[tagIndex + 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
return LATEST_TAG;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function upgradeWakuDependencies(workspaces) {
|
|
|
|
console.log("Upgrading Waku dependencies in workspaces.");
|
|
|
|
const map = workspaces.reduce((acc, item) => {
|
|
|
|
if (!item.private) {
|
|
|
|
acc[item.name] = item;
|
|
|
|
}
|
|
|
|
return acc;
|
|
|
|
}, {});
|
|
|
|
const packageNames = Object.keys(map);
|
|
|
|
workspaces.forEach(async (info) => {
|
|
|
|
if (info.private) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
["dependencies", "devDependencies", "peerDependencies"].forEach((type) => {
|
|
|
|
const deps = info.rawPackageJson[type];
|
|
|
|
if (!deps) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
packageNames.forEach((name) => {
|
|
|
|
if (deps[name]) {
|
|
|
|
deps[name] = map[name].version;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
try {
|
|
|
|
await writeWorkspace(info.workspace, JSON.stringify(info.rawPackageJson));
|
|
|
|
} catch (error) {
|
|
|
|
console.error(
|
|
|
|
`Failed to update package.json for ${info.name} with: `,
|
|
|
|
error
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|