projenrc/next-version.ts (80 lines of code) (raw):
import { promises as fs } from 'fs';
import * as semver from 'semver';
/**
* Command for versioning packages
*
* If the TESTING_CANDIDATE environment variable is set, do a nominal bump
* of the version and append `-test.0`.
*/
async function main() {
const args = process.argv.slice(2);
// This is the current version
const currentVersion = process.env.VERSION ?? '';
// This is the proposed bump type
const suggestedBump: BumpType | undefined = process.env.SUGGESTED_BUMP as any;
if (!suggestedBump) {
throw new Error('SUGGESTED_BUMP not set');
}
let bump: BumpType | string = suggestedBump;
for (const arg of process.argv.slice(2)) {
const [cmd, value] = arg.split(':');
switch (cmd) {
case 'neverMajor':
// neverMajor should not come after something that sets the bump to
// something absolute.
if (!isBumpType(bump)) {
throw new Error(`Not a relative bump type: ${bump}`);
}
if (bump === 'major') {
bump = 'minor';
}
break;
case 'majorFromRevision': {
const contents = JSON.parse(await fs.readFile(value, 'utf-8'));
if (semver.major(currentVersion) === contents.revision) {
bump = `${semver.inc(currentVersion, 'minor')}`;
} else {
bump = `${contents.revision}.0.0`;
}
break;
}
case 'copyVersion': {
const contents = JSON.parse(await fs.readFile(value, 'utf-8'));
bump = `${contents.version}`;
break;
}
case 'append':
// If we have a relative bump type here still, we need to absolutize it
// first before appending.
bump = `${makeAbsolute(bump, currentVersion)}${value}`;
break;
case 'maybeRc': {
bump = maybeRc(makeAbsolute(bump, currentVersion)) ?? bump;
break;
}
default:
throw new Error(`Unknown command: ${cmd}`);
}
}
// this is a cli
// eslint-disable-next-line no-console
console.log(bump);
}
function maybeRc(version: string) {
if (process.env.TESTING_CANDIDATE === 'true') {
// To make an rc version for testing, we set the last component (either
// patch or prerelease version) to 999.
//
// Adding `rc.0` causes problems for Amplify tests, which install
// `aws-cdk@^2` which won't match the prerelease version.
const originalPre = semver.prerelease(version);
if (originalPre) {
return version.replace(new RegExp('\\.' + originalPre[1] + '$'), '.999');
} else {
const patch = semver.patch(version);
return version.replace(new RegExp('\\.' + patch + '$'), '.999');
}
}
}
type BumpType = 'major' | 'minor' | 'patch' | 'none';
function isBumpType(value: string): value is BumpType {
return value === 'major' || value === 'minor' || value === 'patch' || value === 'none';
}
function makeAbsolute(bump: string, currentVersion: string) {
if (!isBumpType(bump)) {
return bump;
}
if (bump === 'none') {
return currentVersion;
}
const ret = semver.inc(currentVersion, bump);
if (ret == null) {
throw new Error(`Could not bump: ${currentVersion} by ${bump}`);
}
return ret;
}
main().catch((error) => {
// this is a cli
// eslint-disable-next-line no-console
console.error(error);
process.exitCode = 1;
});