UNPKG

@i-novus/k8s-version-release

Version:

Release version with git-tag and switch to next snapshot version

123 lines (120 loc) 4.93 kB
#!/usr/bin/env node // src/k8s-version-release.ts import process from "process"; import { stat, readFile, writeFile, access } from "fs/promises"; import { dirname, join } from "path"; import { execSync } from "child_process"; import { input, confirm } from "@inquirer/prompts"; try { let isVersionValid = function(version) { return !!version.match(/^\d+\.\d+\.\d+$/); }, getNextVersion = function(version) { if (!isVersionValid(version)) { throw new Error(`Version "${version}" is not valid`); } const [major, minor, patch] = version.split("."); return [major, minor, Number(patch) + 1].join("."); }; isVersionValid2 = isVersionValid, getNextVersion2 = getNextVersion; const { npm_package_json, npm_package_version } = process.env; const K8S_DIRNAME = ".k8s"; const CHART_CONFIG_FILENAME = "Chart.yaml"; if (!npm_package_json) { throw new Error('ENV variable "npm_package_json" is not set'); } await stat(npm_package_json); if (!npm_package_version) { throw new Error('ENV variable "npm_package_version" is not set'); } const projectPath = dirname(npm_package_json); const chartConfigPath = join(projectPath, K8S_DIRNAME, CHART_CONFIG_FILENAME); await stat(chartConfigPath); let packageManager; if (await checkFileExists(join(projectPath, "package-lock.json"))) { packageManager = "npm"; } else if (await checkFileExists(join(projectPath, "yarn.lock"))) { packageManager = "yarn"; } else { throw new Error('Lock file "package-lock.json" or "yarn.lock" not found'); } const regexResult = npm_package_version.match(/^\d+\.\d+\.\d+/); const coreVersion = regexResult ? regexResult[0] : null; if (!coreVersion) { throw new Error(`Can not parse package.json version "${npm_package_version}" by regular expression /^\\d+\\.\\d+\\.\\d+/`); } const gitStatus = execSync("git status").toString(); if (!gitStatus.includes("nothing to commit")) { throw new Error('There are uncommitted changes. Use "git status" to display them'); } console.log(`Current version "${npm_package_version}"`); const gitTags = execSync("git for-each-ref --format='%(refname:short)' refs/tags").toString().split("\n").map((s) => s.trim()).filter(Boolean); const isCurrentVersionReleased = gitTags.includes(coreVersion); let versionToRelease = coreVersion; if (isCurrentVersionReleased) { console.log(`Version "${coreVersion}" has already been released`); versionToRelease = getNextVersion(versionToRelease); } versionToRelease = await typeVersion("Which version do you want to release?", versionToRelease); let nextVersion = await typeVersion("What will be the next version?", getNextVersion(versionToRelease)); nextVersion += "-SNAPSHOT"; console.log("Creating a release commit"); await setChartConfigVersion(versionToRelease); await setPackageJsonVersion(versionToRelease); execSync(`${packageManager} install`); execSync("git add ."); execSync(`git commit -m "${versionToRelease}"`); execSync(`git tag -fa ${versionToRelease} -m "${versionToRelease}"`); console.log("Creating a next version commit"); await setChartConfigVersion(nextVersion); await setPackageJsonVersion(nextVersion); execSync(`${packageManager} install`); execSync("git add ."); execSync(`git commit -m "${nextVersion}"`); if (await confirm({ message: "Push the release commit and commit with the next version?", default: true })) { execSync("git push origin --follow-tags"); } async function setChartConfigVersion(version) { const chartConfig = await readFile(chartConfigPath, { encoding: "utf-8" }); await writeFile(chartConfigPath, chartConfig.replace(/version: .+/, `version: ${version}`)); } async function setPackageJsonVersion(version) { if (!npm_package_json) { throw new Error('ENV variable "npm_package_json" is not set'); } const packageJson = await readFile(npm_package_json, { encoding: "utf-8" }); await writeFile(npm_package_json, packageJson.replace(/"version": ".+",/, `"version": "${version}",`)); } async function typeVersion(message, defaultValue) { return input({ message, required: true, default: defaultValue, validate: (version) => { if (!isVersionValid(version)) { return "Version is invalid. The expected format is X.X.X, where X is a positive integer"; } if (gitTags.includes(version)) { return `Version "${version}" has already been released`; } return true; } }); } async function checkFileExists(file) { try { await access(file); return true; } catch { return false; } } } catch (error) { if (error instanceof Error && "stdout" in error && error.stdout instanceof Buffer) { throw new Error(`${error.stack} ${error.stdout.toString()}`); } else { throw error; } } var isVersionValid2; var getNextVersion2;