Skip to content

Commit

Permalink
Update the functionality that runs external lifecycle processes to be…
Browse files Browse the repository at this point in the history
… async.
  • Loading branch information
iclanton committed Mar 30, 2024
1 parent 323fddb commit a16f097
Show file tree
Hide file tree
Showing 22 changed files with 350 additions and 280 deletions.
2 changes: 1 addition & 1 deletion apps/rush/src/RushVersionSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class RushVersionSelector {
if (installMarker.isValid()) {
console.log('Another process performed the installation.');
} else {
Utilities.installPackageInDirectory({
await Utilities.installPackageInDirectoryAsync({
directory: expectedRushPath,
packageName: isLegacyRushVersion ? '@microsoft/rush' : '@microsoft/rush-lib',
version: version,
Expand Down
10 changes: 10 additions & 0 deletions common/changes/@microsoft/rush/main_2023-09-24-06-11.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@microsoft/rush",
"comment": "Update the functionality that runs external lifecycle processes to be async.",
"type": "none"
}
],
"packageName": "@microsoft/rush"
}
56 changes: 34 additions & 22 deletions libraries/rush-lib/src/cli/actions/ChangeAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,9 @@ export class ChangeAction extends BaseRushAction {
}

public async runAsync(): Promise<void> {
const targetBranch: string = await this._getTargetBranchAsync();
// eslint-disable-next-line no-console
console.log(`The target branch is ${this._targetBranch}`);
console.log(`The target branch is ${targetBranch}`);

if (this._verifyParameter.value) {
const errors: string[] = [
Expand Down Expand Up @@ -197,11 +198,11 @@ export class ChangeAction extends BaseRushAction {
const sortedProjectList: string[] = (await this._getChangedProjectNamesAsync()).sort();
if (sortedProjectList.length === 0) {
this._logNoChangeFileRequired();
this._warnUnstagedChanges();
await this._warnUnstagedChangesAsync();
return;
}

this._warnUnstagedChanges();
await this._warnUnstagedChangesAsync();

const inquirer: typeof InquirerType = await import('inquirer');
const promptModule: InquirerType.PromptModule = inquirer.createPromptModule();
Expand Down Expand Up @@ -277,7 +278,7 @@ export class ChangeAction extends BaseRushAction {
interactiveMode = true;

const existingChangeComments: Map<string, string[]> = ChangeFiles.getChangeComments(
this._getChangeFiles()
await this._getChangeFilesAsync()
);
changeFileData = await this._promptForChangeFileData(
promptModule,
Expand Down Expand Up @@ -310,7 +311,7 @@ export class ChangeAction extends BaseRushAction {
}
if (this._commitChangesFlagParameter.value || this._commitChangesMessageStringParameter.value) {
if (changefiles && changefiles.length !== 0) {
this._stageAndCommitGitChanges(
await this._stageAndCommitGitChangesAsync(
changefiles,
this._commitChangesMessageStringParameter.value ||
this.rushConfiguration.gitChangefilesCommitMessage ||
Expand Down Expand Up @@ -340,15 +341,16 @@ export class ChangeAction extends BaseRushAction {
private async _verifyAsync(): Promise<void> {
const changedPackages: string[] = await this._getChangedProjectNamesAsync();
if (changedPackages.length > 0) {
this._validateChangeFile(changedPackages);
await this._validateChangeFileAsync(changedPackages);
} else {
this._logNoChangeFileRequired();
}
}

private get _targetBranch(): string {
private async _getTargetBranchAsync(): Promise<string> {
if (!this._targetBranchName) {
this._targetBranchName = this._targetBranchParameter.value || this._git.getRemoteDefaultBranch();
this._targetBranchName =
this._targetBranchParameter.value || (await this._git.getRemoteDefaultBranch());
}

return this._targetBranchName;
Expand All @@ -358,7 +360,7 @@ export class ChangeAction extends BaseRushAction {
const projectChangeAnalyzer: ProjectChangeAnalyzer = new ProjectChangeAnalyzer(this.rushConfiguration);
const changedProjects: Set<RushConfigurationProject> =
await projectChangeAnalyzer.getChangedProjectsAsync({
targetBranchName: this._targetBranch,
targetBranchName: await this._getTargetBranchAsync(),
terminal: this._terminal,
shouldFetch: !this._noFetchParameter.value,
// Lockfile evaluation will expand the set of projects that request change files
Expand All @@ -382,19 +384,28 @@ export class ChangeAction extends BaseRushAction {
return Array.from(changedProjectNames);
}

private _validateChangeFile(changedPackages: string[]): void {
const files: string[] = this._getChangeFiles();
private async _validateChangeFileAsync(changedPackages: string[]): Promise<void> {
const files: string[] = await this._getChangeFilesAsync();
ChangeFiles.validate(files, changedPackages, this.rushConfiguration);
}

private _getChangeFiles(): string[] {
private async _getChangeFilesAsync(): Promise<string[]> {
const repoRoot: string = getRepoRoot(this.rushConfiguration.rushJsonFolder);
const relativeChangesFolder: string = path.relative(repoRoot, this.rushConfiguration.changesFolder);
return this._git
.getChangedFiles(this._targetBranch, this._terminal, true, relativeChangesFolder)
.map((relativePath) => {
return path.join(repoRoot, relativePath);
});
const targetBranch: string = await this._getTargetBranchAsync();
const changedFiles: string[] = await this._git.getChangedFilesAsync(
targetBranch,
this._terminal,
true,
relativeChangesFolder
);

const result: string[] = [];
for (const changedFile of changedFiles) {
result.push(path.join(repoRoot, changedFile));
}

return result;
}

/**
Expand Down Expand Up @@ -625,9 +636,10 @@ export class ChangeAction extends BaseRushAction {
return email;
}

private _warnUnstagedChanges(): void {
private async _warnUnstagedChangesAsync(): Promise<void> {
try {
if (this._git.hasUnstagedChanges()) {
const hasUnstagedChanges: boolean = await this._git.hasUnstagedChangesAsync();
if (hasUnstagedChanges) {
// eslint-disable-next-line no-console
console.log(
'\n' +
Expand Down Expand Up @@ -733,14 +745,14 @@ export class ChangeAction extends BaseRushAction {
console.log('No changes were detected to relevant packages on this branch. Nothing to do.');
}

private _stageAndCommitGitChanges(pattern: string[], message: string): void {
private async _stageAndCommitGitChangesAsync(pattern: string[], message: string): Promise<void> {
try {
Utilities.executeCommand({
await Utilities.executeCommandAsync({
command: 'git',
args: ['add', ...pattern],
workingDirectory: this.rushConfiguration.changesFolder
});
Utilities.executeCommand({
await Utilities.executeCommandAsync({
command: 'git',
args: ['commit', ...pattern, '-m', message],
workingDirectory: this.rushConfiguration.changesFolder
Expand Down
77 changes: 40 additions & 37 deletions libraries/rush-lib/src/cli/actions/PublishAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export class PublishAction extends BaseRushAction {
const git: Git = new Git(this.rushConfiguration);
const publishGit: PublishGit = new PublishGit(git, this._targetBranch.value);
if (this._includeAll.value) {
this._publishAll(publishGit, allPackages);
await this._publishAllAsync(publishGit, allPackages);
} else {
this._prereleaseToken = new PrereleaseToken(
this._prereleaseName.value,
Expand Down Expand Up @@ -287,7 +287,7 @@ export class PublishAction extends BaseRushAction {
const tempBranchName: string = `publish-${Date.now()}`;

// Make changes in temp branch.
publishGit.checkout(tempBranchName, true);
await publishGit.checkoutAsync(tempBranchName, true);

this._setDependenciesBeforePublish();

Expand All @@ -297,14 +297,14 @@ export class PublishAction extends BaseRushAction {

this._setDependenciesBeforeCommit();

if (git.hasUncommittedChanges()) {
if (await git.hasUncommittedChangesAsync()) {
// Stage, commit, and push the changes to remote temp branch.
publishGit.addChanges(':/*');
publishGit.commit(
await publishGit.addChangesAsync(':/*');
await publishGit.commitAsync(
this.rushConfiguration.gitVersionBumpCommitMessage || DEFAULT_PACKAGE_UPDATE_MESSAGE,
!this._ignoreGitHooksParameter.value
);
publishGit.push(tempBranchName, !this._ignoreGitHooksParameter.value);
await publishGit.pushAsync(tempBranchName, !this._ignoreGitHooksParameter.value);

this._setDependenciesBeforePublish();

Expand All @@ -321,8 +321,8 @@ export class PublishAction extends BaseRushAction {
if (change.changeType && change.changeType > ChangeType.dependency) {
const project: RushConfigurationProject | undefined = allPackages.get(change.packageName);
if (project) {
if (!this._packageExists(project)) {
this._npmPublish(change.packageName, project.publishFolder);
if (!(await this._packageExistsAsync(project))) {
await this._npmPublishAsync(change.packageName, project.publishFolder);
} else {
// eslint-disable-next-line no-console
console.log(`Skip ${change.packageName}. Package exists.`);
Expand All @@ -337,50 +337,53 @@ export class PublishAction extends BaseRushAction {
this._setDependenciesBeforeCommit();

// Create and push appropriate Git tags.
this._gitAddTags(publishGit, orderedChanges);
publishGit.push(tempBranchName, !this._ignoreGitHooksParameter.value);
await this._gitAddTagsAsync(publishGit, orderedChanges);
await publishGit.pushAsync(tempBranchName, !this._ignoreGitHooksParameter.value);

// Now merge to target branch.
publishGit.checkout(this._targetBranch.value!);
publishGit.pull(!this._ignoreGitHooksParameter.value);
publishGit.merge(tempBranchName, !this._ignoreGitHooksParameter.value);
publishGit.push(this._targetBranch.value!, !this._ignoreGitHooksParameter.value);
publishGit.deleteBranch(tempBranchName, true, !this._ignoreGitHooksParameter.value);
await publishGit.checkoutAsync(this._targetBranch.value!);
await publishGit.pullAsync(!this._ignoreGitHooksParameter.value);
await publishGit.mergeAsync(tempBranchName, !this._ignoreGitHooksParameter.value);
await publishGit.pushAsync(this._targetBranch.value!, !this._ignoreGitHooksParameter.value);
await publishGit.deleteBranchAsync(tempBranchName, true, !this._ignoreGitHooksParameter.value);
} else {
publishGit.checkout(this._targetBranch.value!);
publishGit.deleteBranch(tempBranchName, false, !this._ignoreGitHooksParameter.value);
await publishGit.checkoutAsync(this._targetBranch.value!);
await publishGit.deleteBranchAsync(tempBranchName, false, !this._ignoreGitHooksParameter.value);
}
}
}

private _publishAll(git: PublishGit, allPackages: ReadonlyMap<string, RushConfigurationProject>): void {
private async _publishAllAsync(
git: PublishGit,
allPackages: ReadonlyMap<string, RushConfigurationProject>
): Promise<void> {
// eslint-disable-next-line no-console
console.log(`Rush publish starts with includeAll and version policy ${this._versionPolicy.value}`);

let updated: boolean = false;

allPackages.forEach((packageConfig, packageName) => {
for (const [packageName, packageConfig] of allPackages) {
if (
packageConfig.shouldPublish &&
(!this._versionPolicy.value || this._versionPolicy.value === packageConfig.versionPolicyName)
) {
const applyTag: (apply: boolean) => void = (apply: boolean): void => {
const applyTagAsync: (apply: boolean) => Promise<void> = async (apply: boolean): Promise<void> => {
if (!apply) {
return;
}

const packageVersion: string = packageConfig.packageJson.version;

// Do not create a new tag if one already exists, this will result in a fatal error
if (git.hasTag(packageConfig)) {
if (await git.hasTagAsync(packageConfig)) {
// eslint-disable-next-line no-console
console.log(
`Not tagging ${packageName}@${packageVersion}. A tag already exists for this version.`
);
return;
}

git.addTag(
await git.addTagAsync(
!!this._publish.value,
packageName,
packageVersion,
Expand All @@ -392,32 +395,32 @@ export class PublishAction extends BaseRushAction {

if (this._pack.value) {
// packs to tarball instead of publishing to NPM repository
this._npmPack(packageName, packageConfig);
applyTag(this._applyGitTagsOnPack.value);
} else if (this._force.value || !this._packageExists(packageConfig)) {
await this._npmPackAsync(packageName, packageConfig);
await applyTagAsync(this._applyGitTagsOnPack.value);
} else if (this._force.value || !(await this._packageExistsAsync(packageConfig))) {
// Publish to npm repository
this._npmPublish(packageName, packageConfig.publishFolder);
applyTag(true);
await this._npmPublishAsync(packageName, packageConfig.publishFolder);
await applyTagAsync(true);
} else {
// eslint-disable-next-line no-console
console.log(`Skip ${packageName}. Not updated.`);
}
}
});
}

if (updated) {
git.push(this._targetBranch.value!, !this._ignoreGitHooksParameter.value);
await git.pushAsync(this._targetBranch.value!, !this._ignoreGitHooksParameter.value);
}
}

private _gitAddTags(git: PublishGit, orderedChanges: IChangeInfo[]): void {
private async _gitAddTagsAsync(git: PublishGit, orderedChanges: IChangeInfo[]): Promise<void> {
for (const change of orderedChanges) {
if (
change.changeType &&
change.changeType > ChangeType.dependency &&
this.rushConfiguration.projectsByName.get(change.packageName)!.shouldPublish
) {
git.addTag(
await git.addTagAsync(
!!this._publish.value && !this._registryUrl.value,
change.packageName,
change.newVersion!,
Expand All @@ -428,7 +431,7 @@ export class PublishAction extends BaseRushAction {
}
}

private _npmPublish(packageName: string, packagePath: string): void {
private async _npmPublishAsync(packageName: string, packagePath: string): Promise<void> {
const env: { [key: string]: string | undefined } = PublishUtilities.getEnvArgs();
const args: string[] = ['publish'];

Expand Down Expand Up @@ -466,7 +469,7 @@ export class PublishAction extends BaseRushAction {
// If the auth token was specified via the command line, avoid printing it on the console
const secretSubstring: string | undefined = this._npmAuthToken.value;

PublishUtilities.execCommand(
await PublishUtilities.execCommandAsync(
!!this._publish.value,
packageManagerToolFilename,
args,
Expand All @@ -477,12 +480,12 @@ export class PublishAction extends BaseRushAction {
}
}

private _packageExists(packageConfig: RushConfigurationProject): boolean {
private async _packageExistsAsync(packageConfig: RushConfigurationProject): Promise<boolean> {
const env: { [key: string]: string | undefined } = PublishUtilities.getEnvArgs();
const args: string[] = [];
this._addSharedNpmConfig(env, args);

const publishedVersions: string[] = Npm.publishedVersions(
const publishedVersions: string[] = await Npm.getPublishedVersionsAsync(
packageConfig.packageName,
packageConfig.publishFolder,
env,
Expand Down Expand Up @@ -511,11 +514,11 @@ export class PublishAction extends BaseRushAction {
return publishedVersions.indexOf(normalizedVersion) >= 0;
}

private _npmPack(packageName: string, project: RushConfigurationProject): void {
private async _npmPackAsync(packageName: string, project: RushConfigurationProject): Promise<void> {
const args: string[] = ['pack'];
const env: { [key: string]: string | undefined } = PublishUtilities.getEnvArgs();

PublishUtilities.execCommand(
await PublishUtilities.execCommandAsync(
!!this._publish.value,
this.rushConfiguration.packageManagerToolFilename,
args,
Expand Down

0 comments on commit a16f097

Please sign in to comment.