Merge pull request #9458 from backstage/rugvip/bumpmessage

cli: a couple of improvements to versions:bump
This commit is contained in:
Patrik Oldsberg
2022-02-11 14:27:34 +01:00
committed by GitHub
6 changed files with 126 additions and 25 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
The `versions:bump` command now filters out `npm_` environment configuration when running `yarn install`. This has the effect of allowing it to consider local configuration files within the repository, which is the behavior that one would expect.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
The `versions:bump` command now also considers the root `package.json` when searching for updates. It has also received updates to its output, including a link the [Backstage upgrade helper](https://backstage.github.io/upgrade-helper) and silenced `yarn install` output.
@@ -31,6 +31,7 @@ import { rest } from 'msw';
// Remove log coloring to simplify log matching
jest.mock('chalk', () => ({
red: (str: string) => str,
blue: (str: string) => str,
cyan: (str: string) => str,
green: (str: string) => str,
@@ -38,6 +39,18 @@ jest.mock('chalk', () => ({
yellow: (str: string) => str,
}));
jest.mock('ora', () => ({
__esModule: true,
default({ prefixText }: any) {
console.log(prefixText);
return {
start: () => ({
succeed: () => {},
}),
};
},
}));
const REGISTRY_VERSIONS: { [name: string]: string } = {
'@backstage/core': '1.0.6',
'@backstage/core-api': '1.0.7',
@@ -177,7 +190,11 @@ describe('bump', () => {
);
expect(runObj.run).toHaveBeenCalledTimes(1);
expect(runObj.run).toHaveBeenCalledWith('yarn', ['install']);
expect(runObj.run).toHaveBeenCalledWith(
'yarn',
['install'],
expect.any(Object),
);
const lockfileContents = await fs.readFile('/yarn.lock', 'utf8');
expect(lockfileContents).toBe(lockfileMockResult);
@@ -273,7 +290,7 @@ describe('bump', () => {
'unlocking @backstage/core-api@^1.0.6 ~> 1.0.7',
'unlocking @backstage/core-api@^1.0.3 ~> 1.0.7',
'bumping @backstage/theme in b to ^5.0.0',
'Creating backstage.json',
'Your project is now at version 0.0.1, which has been written to backstage.json',
'Running yarn install to install new versions',
'⚠️ The following packages may have breaking changes:',
' @backstage/theme : 1.0.0 ~> 5.0.0',
@@ -296,7 +313,11 @@ describe('bump', () => {
);
expect(runObj.run).toHaveBeenCalledTimes(1);
expect(runObj.run).toHaveBeenCalledWith('yarn', ['install']);
expect(runObj.run).toHaveBeenCalledWith(
'yarn',
['install'],
expect.any(Object),
);
const lockfileContents = await fs.readFile('/yarn.lock', 'utf8');
expect(lockfileContents).toBe(lockfileMockResult);
@@ -389,7 +410,7 @@ describe('bump', () => {
'Some packages are outdated, updating',
'bumping @backstage/core in a to ^5.0.0',
'bumping @backstage/core in b to ^5.0.0',
'Creating backstage.json',
'Your project is now at version 2.0.0, which has been written to backstage.json',
'Running yarn install to install new versions',
'⚠️ The following packages may have breaking changes:',
' @backstage/core : 1.0.3 ~> 5.0.0',
@@ -398,7 +419,11 @@ describe('bump', () => {
]);
expect(runObj.run).toHaveBeenCalledTimes(1);
expect(runObj.run).toHaveBeenCalledWith('yarn', ['install']);
expect(runObj.run).toHaveBeenCalledWith(
'yarn',
['install'],
expect.any(Object),
);
const packageA = await fs.readJson('/packages/a/package.json');
expect(packageA).toEqual({
@@ -512,7 +537,7 @@ describe('bump', () => {
'unlocking @backstage/core-api@^1.0.6 ~> 1.0.7',
'unlocking @backstage/core-api@^1.0.3 ~> 1.0.7',
'bumping @backstage/theme in b to ^5.0.0',
'Creating backstage.json',
'Your project is now at version 1.0.0, which has been written to backstage.json',
'Running yarn install to install new versions',
'⚠️ The following packages may have breaking changes:',
' @backstage/theme : 1.0.0 ~> 5.0.0',
@@ -645,7 +670,11 @@ describe('bump', () => {
);
expect(runObj.run).toHaveBeenCalledTimes(1);
expect(runObj.run).toHaveBeenCalledWith('yarn', ['install']);
expect(runObj.run).toHaveBeenCalledWith(
'yarn',
['install'],
expect.any(Object),
);
const lockfileContents = await fs.readFile('/yarn.lock', 'utf8');
expect(lockfileContents).toEqual(customLockfileMockResult);
@@ -765,8 +794,16 @@ describe('bumpBackstageJsonVersion', () => {
.spyOn(paths, 'resolveTargetRoot')
.mockImplementation((...path) => resolvePath('/', ...path));
await bumpBackstageJsonVersion('1.4.1');
const { log } = await withLogCollector(async () => {
await bumpBackstageJsonVersion('1.4.1');
});
expect(await fs.readJson('/backstage.json')).toEqual({ version: '1.4.1' });
expect(log).toEqual([
'Upgraded from release 0.0.1 to 1.4.1, please review these template changes:',
undefined,
' https://backstage.github.io/upgrade-helper/?from=0.0.1&to=1.4.1',
undefined,
]);
});
it("should create backstage.json if doesn't exist", async () => {
@@ -777,8 +814,13 @@ describe('bumpBackstageJsonVersion', () => {
.spyOn(paths, 'resolveTargetRoot')
.mockImplementation((...path) => resolvePath('/', ...path));
await bumpBackstageJsonVersion(latest);
const { log } = await withLogCollector(async () => {
await bumpBackstageJsonVersion(latest);
});
expect(await fs.readJson('/backstage.json')).toEqual({ version: latest });
expect(log).toEqual([
'Your project is now at version 1.4.1, which has been written to backstage.json',
]);
});
});
+60 -14
View File
@@ -16,6 +16,7 @@
import fs from 'fs-extra';
import chalk from 'chalk';
import ora from 'ora';
import semver from 'semver';
import minimatch from 'minimatch';
import { Command } from 'commander';
@@ -259,12 +260,8 @@ export default async (cmd: Command) => {
),
);
}
console.log();
console.log(
`Running ${chalk.blue('yarn install')} to install new versions`,
);
console.log();
await run('yarn', ['install']);
await runYarnInstall();
if (breakingUpdates.size > 0) {
console.log();
@@ -420,17 +417,34 @@ export async function bumpBackstageJsonVersion(version: string) {
throw e;
});
if (backstageJson?.version === version) {
const prevVersion = backstageJson?.version;
if (prevVersion === version) {
return;
}
console.log(
chalk.yellow(
typeof backstageJson === 'undefined'
? `Creating ${BACKSTAGE_JSON}`
: `Bumping version in ${BACKSTAGE_JSON}`,
),
);
const { yellow, cyan, green } = chalk;
if (prevVersion) {
const from = encodeURIComponent(prevVersion);
const to = encodeURIComponent(version);
const link = `https://backstage.github.io/upgrade-helper/?from=${from}&to=${to}`;
console.log(
yellow(
`Upgraded from release ${green(prevVersion)} to ${green(
version,
)}, please review these template changes:`,
),
);
console.log();
console.log(` ${cyan(link)}`);
console.log();
} else {
console.log(
yellow(
`Your project is now at version ${version}, which has been written to ${BACKSTAGE_JSON}`,
),
);
}
await fs.writeJson(
backstageJsonPath,
@@ -441,3 +455,35 @@ export async function bumpBackstageJsonVersion(version: string) {
},
);
}
async function runYarnInstall() {
const spinner = ora({
prefixText: `Running ${chalk.blue('yarn install')} to install new versions`,
spinner: 'arc',
color: 'green',
}).start();
const installOutput = new Array<Buffer>();
try {
await run('yarn', ['install'], {
env: {
FORCE_COLOR: 'true',
// We filter out all of the npm_* environment variables that are added when
// executing through yarn. This works around an issue where these variables
// incorrectly override local yarn or npm config in the project directory.
...Object.fromEntries(
Object.entries(process.env).map(([name, value]) =>
name.startsWith('npm_') ? [name, undefined] : [name, value],
),
),
},
stdoutLogFunc: data => installOutput.push(data),
stderrLogFunc: data => installOutput.push(data),
});
spinner.succeed();
} catch (error) {
spinner.fail();
process.stdout.write(Buffer.concat(installOutput));
throw error;
}
}
+1 -1
View File
@@ -14,7 +14,7 @@
* limitations under the License.
*/
export type LogFunc = (data: Buffer | string) => void;
export type LogFunc = (data: Buffer) => void;
export type LogPipe = (dst: NodeJS.WriteStream) => LogFunc;
export type LogOptions = {
+4 -1
View File
@@ -67,7 +67,10 @@ export async function mapDependencies(
targetDir: string,
pattern: string,
): Promise<Map<string, PkgVersionInfo[]>> {
const { packages } = await getPackages(targetDir);
const { packages, root } = await getPackages(targetDir);
// Include root package.json too
packages.push(root);
const dependencyMap = new Map<string, PkgVersionInfo[]>();
for (const pkg of packages) {