1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Various improvements to release-tool

- Pass more IO from script to user to provide better UX
- Interactive versioning using lerna directly
- Remove all CMD args in favour of interactive

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2023-02-23 12:51:35 -05:00
parent 2550b1efbd
commit 3658e9def4
3 changed files with 41 additions and 146 deletions

42
package-lock.json generated
View File

@ -5955,15 +5955,6 @@
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
}, },
"node_modules/@types/jsonfile": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.1.tgz",
"integrity": "sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/keyv": { "node_modules/@types/keyv": {
"version": "3.1.4", "version": "3.1.4",
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
@ -28093,6 +28084,7 @@
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.1.2.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.1.2.tgz",
"integrity": "sha512-BlIbgFryTbw3Dz6hyoWFhKk+unCcHMSkZGrTFVAx2WmttdBSonsdtRlwiuTbDqTKr+UlXIUqJVS4QT5tUzGENQ==", "integrity": "sha512-BlIbgFryTbw3Dz6hyoWFhKk+unCcHMSkZGrTFVAx2WmttdBSonsdtRlwiuTbDqTKr+UlXIUqJVS4QT5tUzGENQ==",
"dev": true,
"bin": { "bin": {
"rimraf": "dist/cjs/src/bin.js" "rimraf": "dist/cjs/src/bin.js"
}, },
@ -34464,7 +34456,7 @@
"version": "6.4.0-beta.13", "version": "6.4.0-beta.13",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"rimraf": "^4.1.2" "semver": "^7.3.8"
}, },
"bin": { "bin": {
"create-release-pr": "dist/index.js" "create-release-pr": "dist/index.js"
@ -34472,23 +34464,9 @@
"devDependencies": { "devDependencies": {
"@swc/cli": "^0.1.61", "@swc/cli": "^0.1.61",
"@swc/core": "^1.3.35", "@swc/core": "^1.3.35",
"@types/command-line-args": "^5.2.0",
"@types/fs-extra": "^11.0.1",
"@types/node": "^16.18.11", "@types/node": "^16.18.11",
"@types/semver": "^7.3.13", "@types/semver": "^7.3.13",
"command-line-args": "^5.2.1", "rimraf": "^4.1.2"
"fs-extra": "^11.1.0",
"semver": "^7.3.8"
}
},
"packages/release-tool/node_modules/@types/fs-extra": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.1.tgz",
"integrity": "sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA==",
"dev": true,
"dependencies": {
"@types/jsonfile": "*",
"@types/node": "*"
} }
}, },
"packages/release-tool/node_modules/@types/node": { "packages/release-tool/node_modules/@types/node": {
@ -34497,20 +34475,6 @@
"integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==", "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==",
"dev": true "dev": true
}, },
"packages/release-tool/node_modules/fs-extra": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz",
"integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=14.14"
}
},
"packages/semver": { "packages/semver": {
"name": "@k8slens/semver", "name": "@k8slens/semver",
"version": "6.4.0-beta.13", "version": "6.4.0-beta.13",

View File

@ -16,15 +16,11 @@
"devDependencies": { "devDependencies": {
"@swc/cli": "^0.1.61", "@swc/cli": "^0.1.61",
"@swc/core": "^1.3.35", "@swc/core": "^1.3.35",
"@types/command-line-args": "^5.2.0",
"@types/fs-extra": "^11.0.1",
"@types/node": "^16.18.11", "@types/node": "^16.18.11",
"@types/semver": "^7.3.13", "@types/semver": "^7.3.13",
"command-line-args": "^5.2.1", "rimraf": "^4.1.2"
"fs-extra": "^11.1.0",
"semver": "^7.3.8"
}, },
"dependencies": { "dependencies": {
"rimraf": "^4.1.2" "semver": "^7.3.8"
} }
} }

View File

@ -4,9 +4,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import child_process from "child_process"; import child_process from "child_process";
import commandLineArgs from "command-line-args"; import { readFile } from "fs/promises";
import fse from "fs-extra";
import { basename } from "path";
import { createInterface } from "readline"; import { createInterface } from "readline";
import semver from "semver"; import semver from "semver";
import { promisify } from "util"; import { promisify } from "util";
@ -18,89 +16,40 @@ const {
lte: semverLte, lte: semverLte,
} = semver; } = semver;
const exec = promisify(child_process.exec); const exec = promisify(child_process.exec);
const execFile = promisify(child_process.execFile); const spawn = promisify(child_process.spawn);
const options = commandLineArgs([ const repoRoot = (await exec("git rev-parse --show-toplevel")).stdout;
{
name: "type",
defaultOption: true,
},
{
name: "preid",
},
{
name: "check-commits",
type: Boolean,
},
]);
const validReleaseValues = [ if (process.cwd() !== repoRoot) {
"major", console.error("It looks like you are running this script from the 'scripts' directory. This script assumes it is run from the root of the git repo");
"minor",
"patch",
];
const validPrereleaseValues = [
"premajor",
"preminor",
"prepatch",
"prerelease",
];
const validPreidValues = [
"alpha",
"beta",
];
const errorMessages = {
noReleaseType: `No release type provided. Valid options are: ${[...validReleaseValues, ...validPrereleaseValues].join(", ")}`,
invalidRelease: (invalid: string) => `Invalid release type was provided (value was "${invalid}"). Valid options are: ${[...validReleaseValues, ...validPrereleaseValues].join(", ")}`,
noPreid: `No preid was provided. Use '--preid' to specify. Valid options are: ${validPreidValues.join(", ")}`,
invalidPreid: (invalid: string) => `Invalid preid was provided (value was "${invalid}"). Valid options are: ${validPreidValues.join(", ")}`,
wrongCwd: "It looks like you are running this script from the 'scripts' directory. This script assumes it is run from the root of the git repo",
};
if (!options.type) {
console.error(errorMessages.noReleaseType);
process.exit(1);
} }
if (validReleaseValues.includes(options.type)) { const currentVersion = new SemVer(JSON.parse((await readFile("./lerna.json", "utf-8"))).version);
// do nothing, is valid
} else if (validPrereleaseValues.includes(options.type)) {
if (!options.preid) {
console.error(errorMessages.noPreid);
process.exit(1);
}
if (!validPreidValues.includes(options.preid)) { await spawn("npm", ["run", "bump-version"], {
console.error(errorMessages.invalidPreid(options.preid)); stdio: "inherit",
process.exit(1); });
}
} else {
console.error(errorMessages.invalidRelease(options.type));
process.exit(1);
}
if (basename(process.cwd()) === "scripts") { const newVersion = new SemVer(JSON.parse((await readFile("./lerna.json", "utf-8"))).version);
console.error(errorMessages.wrongCwd);
}
const currentVersion = new SemVer((await fse.readJson("./lerna.json")).version);
console.log(`current version: ${currentVersion.format()}`);
const newVersion = currentVersion.inc(options.type, options.preid);
const newVersionMilestone = `${newVersion.major}.${newVersion.minor}.${newVersion.patch}`; const newVersionMilestone = `${newVersion.major}.${newVersion.minor}.${newVersion.patch}`;
const prBranch = `release/v${newVersion.format()}`; const prBranch = `release/v${newVersion.format()}`;
await exec(`npm run bump-version --yes ${newVersion.format()}`); await spawn("git", ["checkout", "-b", prBranch], {
await exec(`git checkout -b ${prBranch}`); stdio: "inherit",
await exec("git add lerna.json packages/*/package.json"); });
await exec(`git commit -sm "Release ${newVersion.format()}"`); await spawn("git", ["add", "lerna.json", "packages/*/package.json"], {
stdio: "inherit",
});
await spawn("git", ["commit", "-sm", `"Release ${newVersion.format()}"`], {
stdio: "inherit",
});
console.log(`new version: ${newVersion.format()}`); console.log(`new version: ${newVersion.format()}`);
console.log("fetching tags..."); console.log("fetching tags...");
await exec("git fetch --tags --force"); await spawn("git", ["fetch", "--tags", "--force"], {
stdio: "inherit",
});
const actualTags = (await exec("git tag --list", { encoding: "utf-8" })).stdout.split(/\r?\n/).map(line => line.trim()); const actualTags = (await exec("git tag --list", { encoding: "utf-8" })).stdout.split(/\r?\n/).map(line => line.trim());
const [previousReleasedVersion] = actualTags const [previousReleasedVersion] = actualTags
@ -193,9 +142,7 @@ function getPrEntry(pr: ExtendedGithubPrData) {
} }
const rl = createInterface(process.stdin); const rl = createInterface(process.stdin);
const prBase = newVersion.patch === 0 const prBase = (await exec("git branch --show-current")).stdout.trim();
? "master"
: `release/v${newVersion.major}.${newVersion.minor}`;
function askQuestion(question: string): Promise<boolean> { function askQuestion(question: string): Promise<boolean> {
return new Promise<boolean>(resolve => { return new Promise<boolean>(resolve => {
@ -220,20 +167,15 @@ function askQuestion(question: string): Promise<boolean> {
} }
async function handleRelaventPr(pr: ExtendedGithubPrData) { async function handleRelaventPr(pr: ExtendedGithubPrData) {
if (options["check-commits"] && !(await askQuestion(`Would you like to use #${pr.number}: ${pr.title}? - Y/N`))) { if (prBase !== "master" && !(await askQuestion(`Would you like to use #${pr.number}: ${pr.title}? - Y/N`))) {
return; return;
} }
if (prBase !== "master") { if (prBase !== "master") {
try { try {
const promise = exec(`git cherry-pick ${pr.mergeCommit.oid}`); await spawn("git", ["cherry-pick", pr.mergeCommit.oid], {
stdio: "inherit",
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion });
promise.child.stdout!.pipe(process.stdout);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
promise.child.stderr!.pipe(process.stderr);
await promise;
} catch { } catch {
console.error(`Failed to cherry-pick ${pr.mergeCommit.oid}, please resolve conflicts and then press enter here:`); console.error(`Failed to cherry-pick ${pr.mergeCommit.oid}, please resolve conflicts and then press enter here:`);
await new Promise<void>(resolve => rl.once("line", () => resolve())); await new Promise<void>(resolve => rl.once("line", () => resolve()));
@ -290,7 +232,10 @@ const prBodyLines = [
), ),
]; ];
const prBody = prBodyLines.join("\n"); const prBody = prBodyLines.join("\n");
const createPrArgs = [
await exec(`git push --set-upstream origin ${prBranch}`);
await spawn("gh", [
"pr", "pr",
"create", "create",
"--base", prBase, "--base", prBase,
@ -298,17 +243,7 @@ const createPrArgs = [
"--label", "skip-changelog", "--label", "skip-changelog",
"--label", "release", "--label", "release",
"--milestone", `${newVersion.major}.${newVersion.minor}.${newVersion.patch}`, "--milestone", `${newVersion.major}.${newVersion.minor}.${newVersion.patch}`,
"--body-file", "-", "--body-file", prBody,
]; ], {
stdio: "inherit"
await exec(`git push --set-upstream origin ${prBranch}`); });
const createPrProcess = execFile("gh", createPrArgs);
createPrProcess.child.stdout?.pipe(process.stdout);
createPrProcess.child.stderr?.pipe(process.stderr);
createPrProcess.child.stdin?.write(prBody);
createPrProcess.child.stdin?.end();
await createPrProcess;