Skip to content

Commit b09f550

Browse files
authored
Merge pull request microsoft#770 from Microsoft/pgonzal/rush-network-concurrency
[rush] Add a --network-concurrency option for troubleshooting network issues
2 parents 8f4706d + 491c61b commit b09f550

File tree

6 files changed

+67
-16
lines changed

6 files changed

+67
-16
lines changed

apps/rush-lib/src/cli/actions/BaseInstallAction.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import * as colors from 'colors';
55
import * as os from 'os';
66

7-
import { CommandLineFlagParameter } from '@microsoft/ts-command-line';
7+
import { CommandLineFlagParameter, CommandLineIntegerParameter } from '@microsoft/ts-command-line';
88

99
import { BaseRushAction } from './BaseRushAction';
1010
import { Event } from '../../api/EventHooks';
@@ -21,6 +21,7 @@ export abstract class BaseInstallAction extends BaseRushAction {
2121
protected _purgeParameter: CommandLineFlagParameter;
2222
protected _bypassPolicyParameter: CommandLineFlagParameter;
2323
protected _noLinkParameter: CommandLineFlagParameter;
24+
protected _networkConcurrencyParameter: CommandLineIntegerParameter;
2425
protected _debugPackageManagerParameter: CommandLineFlagParameter;
2526

2627
protected onDefineParameters(): void {
@@ -40,6 +41,12 @@ export abstract class BaseInstallAction extends BaseRushAction {
4041
+ ' This flag is useful for automated builds that want to report stages individually'
4142
+ ' or perform extra operations in between the two stages.'
4243
});
44+
this._networkConcurrencyParameter = this.defineIntegerParameter({
45+
parameterLongName: '--network-concurrency',
46+
argumentName: 'COUNT',
47+
description: 'If specified, limits the maximum number of concurrent network requests.'
48+
+ ' This is useful when troubleshooting network failures.'
49+
});
4350
this._debugPackageManagerParameter = this.defineFlagParameter({
4451
parameterLongName: '--debug-package-manager',
4552
description: 'Activates verbose logging for the package manager. You will probably want to pipe'
@@ -71,6 +78,13 @@ export abstract class BaseInstallAction extends BaseRushAction {
7178
console.log('');
7279
}
7380

81+
if (this._networkConcurrencyParameter.value) {
82+
if (this.rushConfiguration.packageManager !== 'pnpm') {
83+
throw new Error(`The "${this._networkConcurrencyParameter.longName}" parameter is`
84+
+ ` only supported when using the PNPM package manager.`);
85+
}
86+
}
87+
7488
const installManagerOptions: IInstallManagerOptions = this.buildInstallOptions();
7589

7690
return installManager.doInstall(installManagerOptions)

apps/rush-lib/src/cli/actions/InstallAction.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export class InstallAction extends BaseInstallAction {
3232
noLink: this._noLinkParameter.value!,
3333
fullUpgrade: false,
3434
recheckShrinkwrap: false,
35+
networkConcurrency: this._networkConcurrencyParameter.value,
3536
collectLogFile: this._debugPackageManagerParameter.value!
3637
};
3738
}

apps/rush-lib/src/cli/actions/UpdateAction.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export class UpdateAction extends BaseInstallAction {
5959
noLink: this._noLinkParameter.value!,
6060
fullUpgrade: this._fullParameter.value!,
6161
recheckShrinkwrap: this._recheckParameter.value!,
62+
networkConcurrency: this._networkConcurrencyParameter.value,
6263
collectLogFile: this._debugPackageManagerParameter.value!
6364
};
6465
}

apps/rush-lib/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ Optional arguments:
188188
189189
exports[`CommandLineHelp prints the help for "rush install" 1`] = `
190190
"usage: rush install [-h] [-p] [--bypass-policy] [--no-link]
191-
[--debug-package-manager]
191+
[--network-concurrency COUNT] [--debug-package-manager]
192192
193193
194194
The \\"rush install\\" command installs package dependencies for all your
@@ -214,6 +214,10 @@ Optional arguments:
214214
is useful for automated builds that want to report
215215
stages individually or perform extra operations in
216216
between the two stages.
217+
--network-concurrency COUNT
218+
If specified, limits the maximum number of concurrent
219+
network requests. This is useful when troubleshooting
220+
network failures.
217221
--debug-package-manager
218222
Activates verbose logging for the package manager.
219223
You will probably want to pipe the output of Rush to
@@ -396,7 +400,8 @@ Optional arguments:
396400
397401
exports[`CommandLineHelp prints the help for "rush update" 1`] = `
398402
"usage: rush update [-h] [-p] [--bypass-policy] [--no-link]
399-
[--debug-package-manager] [--full] [--recheck]
403+
[--network-concurrency COUNT] [--debug-package-manager]
404+
[--full] [--recheck]
400405
401406
402407
The \\"rush update\\" command installs the dependencies described in your package.
@@ -421,6 +426,10 @@ Optional arguments:
421426
is useful for automated builds that want to report
422427
stages individually or perform extra operations in
423428
between the two stages.
429+
--network-concurrency COUNT
430+
If specified, limits the maximum number of concurrent
431+
network requests. This is useful when troubleshooting
432+
network failures.
424433
--debug-package-manager
425434
Activates verbose logging for the package manager.
426435
You will probably want to pipe the output of Rush to

apps/rush-lib/src/logic/InstallManager.ts

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ export interface IInstallManagerOptions {
7979
* (pnpmfile.js script logic, registry changes, etc).
8080
*/
8181
recheckShrinkwrap: boolean;
82+
83+
/**
84+
* The value of the "--network-concurrency" command-line parameter, which
85+
* is a diagnostic option used to troubleshoot network failures.
86+
*
87+
* Currently only supported for PNPM.
88+
*/
89+
networkConcurrency: number | undefined;
90+
8291
/**
8392
* Whether or not to collect verbose logs from the package manager.
8493
* If specified when using PNPM, the logs will be in /common/temp/pnpm.log
@@ -239,8 +248,7 @@ export class InstallManager {
239248
}
240249
}
241250

242-
return this._installCommonModules(shrinkwrapIsUpToDate,
243-
options.allowShrinkwrapUpdates, options.collectLogFile)
251+
return this._installCommonModules(shrinkwrapIsUpToDate, options)
244252
.then(() => {
245253
if (!options.noLink) {
246254
const linkManager: BaseLinkManager = LinkManagerFactory.getLinkManager(this._rushConfiguration);
@@ -616,10 +624,7 @@ export class InstallManager {
616624
/**
617625
* Runs "npm install" in the common folder.
618626
*/
619-
private _installCommonModules(
620-
shrinkwrapIsUpToDate: boolean,
621-
allowShrinkwrapUpdates: boolean,
622-
collectLogFile: boolean): Promise<void> {
627+
private _installCommonModules(shrinkwrapIsUpToDate: boolean, options: IInstallManagerOptions): Promise<void> {
623628
return Promise.resolve().then(() => {
624629
console.log(os.EOL + colors.bold('Checking node_modules in ' + this._rushConfiguration.commonTempFolder)
625630
+ os.EOL);
@@ -726,7 +731,7 @@ export class InstallManager {
726731
console.log(`Running "${this._rushConfiguration.packageManager} prune"`
727732
+ ` in ${this._rushConfiguration.commonTempFolder}`);
728733
const args: string[] = ['prune'];
729-
this._pushConfigurationArgs(args, collectLogFile);
734+
this._pushConfigurationArgs(args, options);
730735

731736
Utilities.executeCommandWithRetry(MAX_INSTALL_ATTEMPTS, packageManagerFilename, args,
732737
this._rushConfiguration.commonTempFolder);
@@ -771,11 +776,17 @@ export class InstallManager {
771776
// people would have different node_modules based on their system.
772777

773778
const installArgs: string[] = ['install', '--no-optional'];
774-
this._pushConfigurationArgs(installArgs, collectLogFile);
779+
this._pushConfigurationArgs(installArgs, options);
775780

776781
console.log(os.EOL + colors.bold(`Running "${this._rushConfiguration.packageManager} install" in`
777782
+ ` ${this._rushConfiguration.commonTempFolder}`) + os.EOL);
778783

784+
if (options.collectLogFile || options.networkConcurrency) {
785+
// Show the full command-line when diagnostic options are specified
786+
console.log(os.EOL + colors.green('Invoking package manager: ')
787+
+ FileSystem.getRealPath(packageManagerFilename) + ' ' + installArgs.join(' ') + os.EOL);
788+
}
789+
779790
Utilities.executeCommandWithRetry(MAX_INSTALL_ATTEMPTS, packageManagerFilename,
780791
installArgs,
781792
this._rushConfiguration.commonTempFolder,
@@ -799,15 +810,15 @@ export class InstallManager {
799810

800811
console.log(os.EOL + colors.bold('Running "npm shrinkwrap"...'));
801812
const npmArgs: string[] = ['shrinkwrap'];
802-
this._pushConfigurationArgs(npmArgs, collectLogFile);
813+
this._pushConfigurationArgs(npmArgs, options);
803814
Utilities.executeCommand(this._rushConfiguration.packageManagerToolFilename,
804815
npmArgs, this._rushConfiguration.commonTempFolder);
805816
console.log('"npm shrinkwrap" completed' + os.EOL);
806817

807818
this._fixupNpm5Regression();
808819
}
809820

810-
if (allowShrinkwrapUpdates && !shrinkwrapIsUpToDate) {
821+
if (options.allowShrinkwrapUpdates && !shrinkwrapIsUpToDate) {
811822
// Copy (or delete) common\temp\shrinkwrap.yaml --> common\config\rush\shrinkwrap.yaml
812823
this._syncFile(this._rushConfiguration.tempShrinkwrapFilename,
813824
this._rushConfiguration.committedShrinkwrapFilename);
@@ -939,12 +950,12 @@ export class InstallManager {
939950
* Used when invoking the NPM tool. Appends the common configuration options
940951
* to the command-line.
941952
*/
942-
private _pushConfigurationArgs(args: string[], collectLogFile: boolean): void {
953+
private _pushConfigurationArgs(args: string[], options: IInstallManagerOptions): void {
943954
if (this._rushConfiguration.packageManager === 'npm') {
944955
args.push('--cache', this._rushConfiguration.npmCacheFolder);
945956
args.push('--tmp', this._rushConfiguration.npmTmpFolder);
946957

947-
if (collectLogFile) {
958+
if (options.collectLogFile) {
948959
args.push('--verbose');
949960
}
950961
} else if (this._rushConfiguration.packageManager === 'pnpm') {
@@ -957,9 +968,13 @@ export class InstallManager {
957968
// last install flag, which encapsulates the entire installation
958969
args.push('--no-lock');
959970

960-
if (collectLogFile) {
971+
if (options.collectLogFile) {
961972
args.push('--reporter', 'ndjson');
962973
}
974+
975+
if (options.networkConcurrency) {
976+
args.push('--network-concurrency', options.networkConcurrency.toString());
977+
}
963978
}
964979
}
965980

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "Add a \"--network-concurrency\" command-line option to help troubleshoot the ECONNRESET error that people occasionally have reported ( https://github.com/pnpm/pnpm/issues/1230 )",
5+
"packageName": "@microsoft/rush",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@microsoft/rush",
10+
"email": "pgonzal@users.noreply.github.com"
11+
}

0 commit comments

Comments
 (0)