Skip to content

Commit

Permalink
Introduce a tool to bump cyclic depndencies.
Browse files Browse the repository at this point in the history
  • Loading branch information
iclanton committed May 5, 2022
1 parent 0b69813 commit ab20b89
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
99 changes: 99 additions & 0 deletions repo-scripts/repo-toolbox/src/BumpCyclicsAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See the @microsoft/rush package's LICENSE file for license information.

import { Async, ConsoleTerminalProvider, Executable, JsonFile, Terminal } from '@rushstack/node-core-library';
import { DependencyType, RushConfiguration } from '@microsoft/rush-lib';
import { CommandLineAction } from '@rushstack/ts-command-line';
import { ChildProcess } from 'child_process';

export class BumpCyclicsAction extends CommandLineAction {
public constructor() {
super({
actionName: 'bump-cyclic-dependencies',
summary: 'Updates cyclic dependencies inside the repo.',
documentation: ''
});
}

protected onDefineParameters(): void {}

protected async onExecute(): Promise<void> {
const terminal: Terminal = new Terminal(new ConsoleTerminalProvider());
const rushConfiguration: RushConfiguration = RushConfiguration.loadFromDefaultLocation({
startingFolder: process.cwd()
});

const cyclicDependencyNames: Set<string> = new Set<string>();

for (const project of rushConfiguration.projects) {
for (const cyclicDependencyProject of project.cyclicDependencyProjects) {
cyclicDependencyNames.add(cyclicDependencyProject);
}
}

const cyclicDependencyVersions: Map<string, string> = new Map<string, string>();
await Async.forEachAsync(
Array.from(cyclicDependencyNames),
async (cyclicDependencyName) => {
const version: string = await this._getLatestPublishedVersionAsync(terminal, cyclicDependencyName);
cyclicDependencyVersions.set(cyclicDependencyName, version);
},
{
concurrency: 10
}
);

terminal.writeLine();

for (const project of rushConfiguration.projects) {
for (const cyclicDependencyProject of project.cyclicDependencyProjects) {
const version: string = cyclicDependencyVersions.get(cyclicDependencyProject)!;
if (project.packageJsonEditor.tryGetDependency(cyclicDependencyProject)) {
project.packageJsonEditor.addOrUpdateDependency(
cyclicDependencyProject,
version,
DependencyType.Regular
);
}

if (project.packageJsonEditor.tryGetDevDependency(cyclicDependencyProject)) {
project.packageJsonEditor.addOrUpdateDependency(
cyclicDependencyProject,
version,
DependencyType.Dev
);
}
}

if (project.packageJsonEditor.saveIfModified()) {
terminal.writeLine(`Updated ${project.packageName}`);
}
}

terminal.writeLine();

// Update the Rush version in rush.json
const latestRushVersion: string = await this._getLatestPublishedVersionAsync(terminal, '@microsoft/rush');
const rushJson: { rushVersion: string } = await JsonFile.loadAsync(rushConfiguration.rushJsonFile);
rushJson.rushVersion = latestRushVersion;
await JsonFile.saveAsync(rushJson, rushConfiguration.rushJsonFile, { updateExistingFile: true });
terminal.writeLine(`Updated ${rushConfiguration.rushJsonFile}`);
}

private async _getLatestPublishedVersionAsync(terminal: Terminal, packageName: string): Promise<string> {
return await new Promise((resolve: (result: string) => void, reject: (error: Error) => void) => {
const childProcess: ChildProcess = Executable.spawn('npm', ['view', packageName, 'version']);
const stdoutBuffer: string[] = [];
childProcess.stdout!.on('data', (chunk) => stdoutBuffer.push(chunk));
childProcess.on('exit', (code: number) => {
if (code) {
reject(new Error(`Exited with ${code}`));
} else {
const version: string = stdoutBuffer.join('').trim();
terminal.writeLine(`Found version "${version}" for "${packageName}"`);
resolve(version);
}
});
});
}
}
2 changes: 2 additions & 0 deletions repo-scripts/repo-toolbox/src/ToolboxCommandLine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CommandLineParser } from '@rushstack/ts-command-line';

import { ReadmeAction } from './ReadmeAction';
import { RecordVersionsAction } from './RecordVersionsAction';
import { BumpCyclicsAction } from './BumpCyclicsAction';

export class ToolboxCommandLine extends CommandLineParser {
public constructor() {
Expand All @@ -15,6 +16,7 @@ export class ToolboxCommandLine extends CommandLineParser {

this.addAction(new ReadmeAction());
this.addAction(new RecordVersionsAction());
this.addAction(new BumpCyclicsAction());
}

protected onDefineParameters(): void {
Expand Down

0 comments on commit ab20b89

Please sign in to comment.