@tinymce/beehive-flow
Version:
A CLI tool implementing the beehive flow git branching process
186 lines • 7.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createReleaseBranch = exports.getBranchDetails = exports.readModulesIfEnabled = exports.readModules = exports.isValidPrerelease = exports.getBranchType = exports.mainBranchName = exports.versionFromReleaseBranch = exports.getReleaseBranchName = void 0;
const tslib_1 = require("tslib");
const fs = tslib_1.__importStar(require("fs"));
const path = tslib_1.__importStar(require("path"));
const O = tslib_1.__importStar(require("fp-ts/Option"));
const simple_git_1 = require("simple-git");
const PromiseUtils = tslib_1.__importStar(require("../utils/PromiseUtils"));
const StringUtils_1 = require("../utils/StringUtils");
const Git = tslib_1.__importStar(require("../utils/Git"));
const BuildProperties_1 = require("./BuildProperties");
const Version = tslib_1.__importStar(require("./Version"));
const PreRelease = tslib_1.__importStar(require("./PreRelease"));
const PackageJson = tslib_1.__importStar(require("./PackageJson"));
const YarnWorkspaces = tslib_1.__importStar(require("./YarnWorkspaces"));
const getReleaseBranchName = ({ major, minor }) => `release/${major}.${minor}`;
exports.getReleaseBranchName = getReleaseBranchName;
const versionFromReleaseBranch = async (branchName) => {
const regexp = /^release\/(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)$/;
const r = regexp.exec(branchName);
if (r === null || r.groups === undefined) {
return PromiseUtils.fail('Could not parse major.minor version from branch name');
}
else {
const g = r.groups;
const major = parseInt(g.major, 10);
const minor = parseInt(g.minor, 10);
return { major, minor };
}
};
exports.versionFromReleaseBranch = versionFromReleaseBranch;
exports.mainBranchName = 'main';
const getBranchType = (branchName) => {
if (branchName === exports.mainBranchName) {
return O.some("main" /* BranchType.Main */);
}
else {
const parts = branchName.split('/');
switch (parts[0]) {
case 'feature':
return O.some("feature" /* BranchType.Feature */);
case 'hotfix':
return O.some("hotfix" /* BranchType.Hotfix */);
case 'spike':
return O.some("spike" /* BranchType.Spike */);
case 'release':
return O.some("release" /* BranchType.Release */);
case 'dependabot':
return O.some("dependabot" /* BranchType.Dependabot */);
default:
return O.none;
}
}
};
exports.getBranchType = getBranchType;
const isValidPrerelease = (actual, expected) => actual !== undefined && (actual === expected || actual.startsWith(`${expected}.`));
exports.isValidPrerelease = isValidPrerelease;
const findChangelog = (dir) => {
const changelogFile = path.join(dir, 'CHANGELOG.md');
if (fs.existsSync(changelogFile)) {
return {
changelogFile,
changelogFormat: 'keepachangelog'
};
}
else {
return {
changelogFile: '',
changelogFormat: 'none'
};
}
};
const readModule = async (dir) => {
const packageJsonFile = path.join(dir, 'package.json');
const packageJson = await PackageJson.parsePackageJsonFile(packageJsonFile);
const changelog = findChangelog(dir);
return {
packageJson,
packageJsonFile,
...changelog
};
};
const readModules = async (dir) => {
const ws = await YarnWorkspaces.info(dir);
return PromiseUtils.parMapRecord(ws, (w) => readModule(path.join(dir, w.location)));
};
exports.readModules = readModules;
const readModulesIfEnabled = async (dir, packageJson) => {
const workspacesEnabled = packageJson.workspaces !== undefined;
if (workspacesEnabled) {
return { workspacesEnabled, modules: await (0, exports.readModules)(dir) };
}
else {
return { workspacesEnabled, modules: {} };
}
};
exports.readModulesIfEnabled = readModulesIfEnabled;
const getBranchDetails = async (dir) => {
const fail = PromiseUtils.fail;
const git = (0, simple_git_1.gitP)(dir);
await git.checkIsRepo(simple_git_1.CheckRepoActions.IS_REPO_ROOT);
const currentBranch = await Git.currentBranch(git);
const rootModule = await readModule(dir);
const { workspacesEnabled, modules } = await (0, exports.readModulesIfEnabled)(dir, rootModule.packageJson);
const version = rootModule.packageJson.version;
if (version === undefined) {
throw new Error('Version missing in package.json file');
}
const baseState = {
currentBranch,
version,
rootModule
};
const loc = `${currentBranch} branch: package.json version`;
const sPackageVersion = Version.versionToString(version);
const sPre = (0, StringUtils_1.showStringOrUndefined)(version.preRelease);
const rcOrReleaseReady = async () => {
if (version.preRelease === undefined) {
return "releaseReady" /* BranchState.ReleaseReady */;
}
else if ((0, exports.isValidPrerelease)(version.preRelease, PreRelease.releaseCandidate)) {
return "releaseCandidate" /* BranchState.ReleaseCandidate */;
}
else {
const rc = PreRelease.releaseCandidate;
return fail(`${loc}: prerelease version part should be either "${rc}" or start with "${rc}." or not be set, but it is "${sPre}"`);
}
};
const validateMainBranch = rcOrReleaseReady;
const validateReleaseBranch = async () => {
const branchVersion = await (0, exports.versionFromReleaseBranch)(currentBranch);
const sBranchVersion = Version.majorMinorVersionToString(branchVersion);
if (version.major !== branchVersion.major || version.minor !== branchVersion.minor) {
return fail(`${loc}: major.minor of branch (${sBranchVersion}) is not consistent with package version (${sPackageVersion})`);
}
else {
return rcOrReleaseReady();
}
};
const detect = async (branchType) => {
switch (branchType) {
case "main" /* BranchType.Main */:
return validateMainBranch();
case "feature" /* BranchType.Feature */:
case "dependabot" /* BranchType.Dependabot */:
return "feature" /* BranchState.Feature */;
case "hotfix" /* BranchType.Hotfix */:
return "hotfix" /* BranchState.Hotfix */;
case "spike" /* BranchType.Spike */:
return "spike" /* BranchState.Spike */;
case "release" /* BranchType.Release */:
return validateReleaseBranch();
}
};
if (version.buildMetaData !== undefined) {
return fail(`package.json version has an unexpected buildMetaData part`);
}
else {
const obt = (0, exports.getBranchType)(currentBranch);
if (O.isNone(obt)) {
return fail('Invalid branch name. beehive-flow is strict about branch names. Valid names: main, feature/*, hotfix/*, spike/*, release/x.y');
}
else {
const branchType = obt.value;
const branchState = await detect(branchType);
return {
...baseState,
branchState,
branchType,
workspacesEnabled,
modules
};
}
}
};
exports.getBranchDetails = getBranchDetails;
const createReleaseBranch = async (releaseBranchName, git, dir) => {
console.log(`Creating ${releaseBranchName} branch`);
await Git.checkoutNewBranch(git, releaseBranchName);
const buildPropertiesFile = await (0, BuildProperties_1.writeBuildPropertiesFile)(dir, releaseBranchName);
await git.add([buildPropertiesFile]);
await git.commit(`Creating release branch: ${releaseBranchName}`);
};
exports.createReleaseBranch = createReleaseBranch;
//# sourceMappingURL=BranchLogic.js.map