9705c336a7
Co-authored-by: blam <ben@blam.sh> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
188 lines
5.4 KiB
JavaScript
Executable File
188 lines
5.4 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
/* eslint-disable import/no-extraneous-dependencies */
|
|
/*
|
|
* Copyright 2022 The Backstage Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
const fs = require('fs-extra');
|
|
const semver = require('semver');
|
|
const { getPackages } = require('@manypkg/get-packages');
|
|
const path = require('path');
|
|
const { execFile: execFileCb } = require('child_process');
|
|
const { promisify } = require('util');
|
|
|
|
const execFile = promisify(execFileCb);
|
|
|
|
const DEPENDENCY_TYPES = [
|
|
'dependencies',
|
|
'devDependencies',
|
|
'optionalDependencies',
|
|
'peerDependencies',
|
|
];
|
|
|
|
/**
|
|
* Bumps up the versions of packages to account for
|
|
* the base versions that are set in .changeset/patched.json.
|
|
* This may be needed when we have made emergency releases.
|
|
*/
|
|
async function updatePatchVersions() {
|
|
const patchedJsonPath = path.resolve('.changeset', 'patched.json');
|
|
const { currentReleaseVersion } = await fs.readJson(patchedJsonPath);
|
|
if (Object.keys(currentReleaseVersion).length === 0) {
|
|
console.log('No currentReleaseVersion overrides found, skipping.');
|
|
return;
|
|
}
|
|
|
|
const { packages } = await getPackages(path.resolve('.'));
|
|
|
|
const pendingVersionBumps = new Map();
|
|
|
|
for (const [name, version] of Object.entries(currentReleaseVersion)) {
|
|
const pkg = packages.find(p => p.packageJson.name === name);
|
|
if (!pkg) {
|
|
throw new Error(`Package ${name} not found`);
|
|
}
|
|
|
|
if (!semver.valid(version)) {
|
|
throw new Error(`Invalid base version ${version} for package ${name}`);
|
|
}
|
|
|
|
const currentVersion = semver.parse(pkg.packageJson.version);
|
|
const targetVersion = semver.parse(version).inc('patch');
|
|
targetVersion.prerelease = currentVersion.prerelease;
|
|
|
|
const targetVersionString = targetVersion.format();
|
|
pendingVersionBumps.set(name, {
|
|
targetVersion: targetVersionString,
|
|
targetRange: `^${targetVersionString}`,
|
|
});
|
|
}
|
|
|
|
for (const { dir, packageJson } of packages) {
|
|
let hasChanges = false;
|
|
|
|
if (pendingVersionBumps.has(packageJson.name)) {
|
|
packageJson.version = pendingVersionBumps.get(
|
|
packageJson.name,
|
|
).targetVersion;
|
|
hasChanges = true;
|
|
}
|
|
|
|
for (const depType of DEPENDENCY_TYPES) {
|
|
const deps = packageJson[depType];
|
|
for (const depName of Object.keys(deps ?? {})) {
|
|
const currentRange = deps[depName];
|
|
if (currentRange === '*') {
|
|
continue;
|
|
}
|
|
|
|
if (pendingVersionBumps.has(depName)) {
|
|
const pendingBump = pendingVersionBumps.get(depName);
|
|
console.log(
|
|
`Replacing ${depName} ${currentRange} with ${pendingBump.targetRange} in ${depType} of ${packageJson.name}`,
|
|
);
|
|
deps[depName] = pendingBump.targetRange;
|
|
hasChanges = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hasChanges) {
|
|
await fs.writeJson(path.resolve(dir, 'package.json'), packageJson, {
|
|
spaces: 2,
|
|
encoding: 'utf8',
|
|
});
|
|
}
|
|
}
|
|
|
|
await fs.writeJSON(
|
|
patchedJsonPath,
|
|
{ currentReleaseVersion: {} },
|
|
{ spaces: 2, encoding: 'utf8' },
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns the mode and tag that is currently set
|
|
* in the .changeset/pre.json file
|
|
*/
|
|
async function getPreInfo(rootPath) {
|
|
const pre = path.join(rootPath, '.changeset', 'pre.json');
|
|
if (!(await fs.pathExists(pre))) {
|
|
return { mode: undefined, tag: undefined };
|
|
}
|
|
|
|
const { mode, tag } = await fs.readJson(pre);
|
|
return { mode, tag };
|
|
}
|
|
|
|
/**
|
|
* Bumps the release version in the root package.json.
|
|
*
|
|
* This takes into account whether we're in pre-release mode or on a patch branch.
|
|
*/
|
|
async function updateBackstageReleaseVersion() {
|
|
const rootPath = path.resolve(__dirname, '..');
|
|
const branchName = await execFile(
|
|
'git',
|
|
['rev-parse', '--abbrev-ref', 'HEAD'],
|
|
{ shell: true },
|
|
).then(({ stdout }) => stdout.trim());
|
|
const { mode: preMode, tag: preTag } = await getPreInfo(rootPath);
|
|
|
|
const packagePath = path.join(rootPath, 'package.json');
|
|
const package = await fs.readJson(packagePath);
|
|
const { version: currentVersion } = package;
|
|
|
|
let nextVersion;
|
|
if (branchName === 'master') {
|
|
if (preMode === 'pre') {
|
|
if (semver.prerelease(currentVersion)) {
|
|
nextVersion = semver.inc(currentVersion, 'pre', preTag);
|
|
} else {
|
|
nextVersion = semver.inc(currentVersion, 'preminor', preTag);
|
|
}
|
|
} else if (preMode === 'exit') {
|
|
nextVersion = semver.inc(currentVersion, 'patch');
|
|
} else {
|
|
nextVersion = semver.inc(currentVersion, 'minor');
|
|
}
|
|
} else {
|
|
if (preMode) {
|
|
throw new Error(`Unexpected pre mode ${preMode} on branch ${branchName}`);
|
|
}
|
|
nextVersion = semver.inc(currentVersion, 'patch');
|
|
}
|
|
|
|
await fs.writeJson(
|
|
packagePath,
|
|
{
|
|
...package,
|
|
version: nextVersion,
|
|
},
|
|
{ spaces: 2, encoding: 'utf8' },
|
|
);
|
|
}
|
|
|
|
async function main() {
|
|
await updatePatchVersions();
|
|
await updateBackstageReleaseVersion();
|
|
}
|
|
|
|
main().catch(error => {
|
|
console.error(error.stack);
|
|
process.exit(1);
|
|
});
|