From 6dd2f7cbac8a4a3f1de7b2abe612feb8b9e8468f Mon Sep 17 00:00:00 2001 From: George Fu Date: Fri, 29 Mar 2024 13:21:07 -0400 Subject: [PATCH] chore(scripts): adds script to tag a target version-group as latest (#5947) --- .../npm-registry/mark-version-as-latest.mjs | 74 +++++++++++++++++++ scripts/utils/spawn-process.js | 20 ++++- 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 scripts/npm-registry/mark-version-as-latest.mjs diff --git a/scripts/npm-registry/mark-version-as-latest.mjs b/scripts/npm-registry/mark-version-as-latest.mjs new file mode 100644 index 000000000000..a2575c78a764 --- /dev/null +++ b/scripts/npm-registry/mark-version-as-latest.mjs @@ -0,0 +1,74 @@ +#!/usr/bin/env node + +/** + * This script will output commands to set a target version as "latest" on the NPM public registry. + * + * The canonical list of packages will be generated from this repository's current state (lib/packages/clients), + * so anything missing from this workspace will not be considered. + */ +// + +import readline from "readline"; +import fs from "fs"; +import path, { dirname } from "path"; +import { fileURLToPath } from "node:url"; +import { spawnProcessReturnValue } from "../utils/spawn-process.js"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +async function ask(question) { + return new Promise((resolve) => { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + rl.question(question + "\n", (answer) => { + resolve(answer); + rl.close(); + }); + }); +} + +const root = path.join(__dirname, "..", ".."); + +const packages = []; + +function recordPackages(dir) { + const packageFolders = fs.readdirSync(dir); + for (const packageFolder of packageFolders) { + const pkgJson = JSON.parse(fs.readFileSync(path.join(dir, packageFolder, "package.json"), "utf-8")); + packages.push(pkgJson.name); + } +} + +recordPackages(path.join(root, "lib")); +recordPackages(path.join(root, "packages")); +recordPackages(path.join(root, "clients")); + +const targetVersion = await ask("What is the version that should become [latest] (e.g. 3.512.0 no v-prefix)?"); + +for (const pkg of packages) { + try { + const viewVersion = await spawnProcessReturnValue("npm", ["view", `${pkg}@<=${targetVersion}`, "version"], { + returnOutput: true, + }); + if (viewVersion) { + const lines = viewVersion.split("\n").filter((s) => !!s.trim()); + const versionMatch = lines[lines.length - 1].match(/'(.*?)'/); + if (versionMatch?.[1]) { + // this indicates multiple versions matching. + const latestBeforeTargetVersion = versionMatch[1]; + console.log(`npm dist-tag add ${pkg}@${latestBeforeTargetVersion} latest`); + } else { + // this indicates a single version matching. + console.log(`npm dist-tag add ${pkg}@${lines} latest`); + } + } + } catch (e) { + if (e.toString().includes("is not in this registry.")) { + console.log(`# ${pkg} does not exist at or below ${targetVersion}.`); + } else { + throw e; + } + } +} diff --git a/scripts/utils/spawn-process.js b/scripts/utils/spawn-process.js index 3be8332fdd33..dccde9769c86 100644 --- a/scripts/utils/spawn-process.js +++ b/scripts/utils/spawn-process.js @@ -15,4 +15,22 @@ const spawnProcess = async (command, args = [], options = {}) => { }); }; -module.exports = { spawnProcess }; +const spawnProcessReturnValue = async (command, args = [], options = {}) => { + const childProcess = spawn(command, args, options); + + let buffer = ""; + let errBuffer = ""; + childProcess.stdout.on("data", (data) => { + buffer += data.toString(); + }); + childProcess.stderr.on("data", (data) => { + errBuffer += data.toString(); + }); + + return new Promise((resolve, reject) => { + childProcess.on("error", reject); + childProcess.on("exit", (code, signal) => (code === 0 ? resolve(buffer) : reject(errBuffer))); + }); +}; + +module.exports = { spawnProcess, spawnProcessReturnValue };