mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-07 07:55:13 +02:00
114 lines
3.1 KiB
JavaScript
114 lines
3.1 KiB
JavaScript
const { readFileSync } = require('node:fs');
|
|
const { join } = require('node:path');
|
|
|
|
const SEMVER_PATTERN =
|
|
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
const FIRST_STABLE_RELEASE_FLOOR_VERSION = '0.0.0';
|
|
|
|
function parseSemver(version) {
|
|
const match = SEMVER_PATTERN.exec(version);
|
|
if (!match) {
|
|
throw new Error(`Invalid public npm package version: ${version}`);
|
|
}
|
|
|
|
return {
|
|
major: Number(match[1]),
|
|
minor: Number(match[2]),
|
|
patch: Number(match[3]),
|
|
prerelease: match[4] ?? null,
|
|
};
|
|
}
|
|
|
|
function readReleasePolicy(cwd) {
|
|
return JSON.parse(readFileSync(join(cwd, 'release-policy.json'), 'utf8'));
|
|
}
|
|
|
|
function releaseKind(env) {
|
|
return env.KTX_RELEASE_KIND || env.INPUT_RELEASE_KIND || 'rc';
|
|
}
|
|
|
|
function stableBaseVersion(version) {
|
|
const parsed = parseSemver(version);
|
|
return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
|
|
}
|
|
|
|
function isFirstStableReleaseFloor(context) {
|
|
return (
|
|
releaseKind(context.env) === 'stable' &&
|
|
context.env.KTX_STABLE_RELEASE_FLOOR_TAG &&
|
|
context.lastRelease.version === FIRST_STABLE_RELEASE_FLOOR_VERSION &&
|
|
context.lastRelease.gitTag === context.env.KTX_STABLE_RELEASE_FLOOR_TAG
|
|
);
|
|
}
|
|
|
|
function analyzeCommits(config, context) {
|
|
if (!isFirstStableReleaseFloor(context)) {
|
|
return undefined;
|
|
}
|
|
|
|
context.logger.log('Using temporary stable release floor to publish 0.1.0');
|
|
return 'minor';
|
|
}
|
|
|
|
function assertNoAutomaticMajorRelease(context, policyVersion) {
|
|
const policy = parseSemver(policyVersion);
|
|
const next = parseSemver(context.nextRelease.version);
|
|
if (next.major <= policy.major) {
|
|
return;
|
|
}
|
|
|
|
throw new Error(
|
|
[
|
|
`Refusing automatic major release ${context.nextRelease.version}.`,
|
|
`release-policy.json is still on major ${policy.major}.`,
|
|
'Update release-policy.json manually before publishing a new major version.',
|
|
].join(' '),
|
|
);
|
|
}
|
|
|
|
function assertStableReleaseFloorTarget(context, policyVersion) {
|
|
if (!isFirstStableReleaseFloor(context)) {
|
|
return;
|
|
}
|
|
|
|
const expectedVersion = stableBaseVersion(policyVersion);
|
|
if (context.nextRelease.version !== expectedVersion) {
|
|
throw new Error(
|
|
`Stable release floor expected ${expectedVersion}, got ${context.nextRelease.version}.`,
|
|
);
|
|
}
|
|
}
|
|
|
|
function verifyRelease(config, context) {
|
|
const policy = readReleasePolicy(context.cwd);
|
|
const policyVersion = policy.publicNpmPackageVersion;
|
|
|
|
assertNoAutomaticMajorRelease(context, policyVersion);
|
|
assertStableReleaseFloorTarget(context, policyVersion);
|
|
}
|
|
|
|
function prepare(config, context) {
|
|
const floorTag = context.env.KTX_STABLE_RELEASE_FLOOR_TAG;
|
|
if (!floorTag) {
|
|
return;
|
|
}
|
|
|
|
const { execFileSync } = require('node:child_process');
|
|
execFileSync('git', ['tag', '-d', floorTag], {
|
|
cwd: context.cwd,
|
|
stdio: 'ignore',
|
|
});
|
|
context.logger.log(`Deleted temporary stable release floor tag ${floorTag}`);
|
|
}
|
|
|
|
module.exports = {
|
|
FIRST_STABLE_RELEASE_FLOOR_VERSION,
|
|
analyzeCommits,
|
|
assertNoAutomaticMajorRelease,
|
|
assertStableReleaseFloorTarget,
|
|
isFirstStableReleaseFloor,
|
|
parseSemver,
|
|
prepare,
|
|
stableBaseVersion,
|
|
verifyRelease,
|
|
};
|