Skip to content

Commit b0cfe9a

Browse files
committed
Clean up warning code.
1 parent 625a48a commit b0cfe9a

9 files changed

Lines changed: 149 additions & 148 deletions

File tree

apps/rush-lib/src/api/Rush.ts

Lines changed: 14 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ import { RushCommandLineParser } from '../cli/RushCommandLineParser';
1010
import { RushConstants } from '../logic/RushConstants';
1111
import { RushXCommandLine } from '../cli/RushXCommandLine';
1212
import { CommandLineMigrationAdvisor } from '../cli/CommandLineMigrationAdvisor';
13-
import { RushConfiguration } from './RushConfiguration';
13+
import { NodeJsCompatibility } from '../logic/NodeJsCompatibility';
1414

1515
/**
1616
* Options to pass to the rush "launch" functions.
17+
*
18+
* @public
1719
*/
1820
export interface ILaunchOptions {
1921
/**
@@ -30,12 +32,6 @@ export interface ILaunchOptions {
3032
alreadyReportedNodeTooNewError?: boolean;
3133
}
3234

33-
interface IExtendedNodeProcess extends NodeJS.Process {
34-
release: {
35-
lts?: string;
36-
};
37-
}
38-
3935
/**
4036
* General operations for the Rush engine.
4137
*
@@ -48,15 +44,20 @@ export class Rush {
4844
* and start a new Node.js process.
4945
*
5046
* @param launcherVersion - The version of the `@microsoft/rush` wrapper used to call invoke the CLI.
47+
*
48+
* @remarks
49+
* Earlier versions of the rush frontend used a different API contract. In the old contract,
50+
* the second argument was the `isManaged` value of the {@see ILaunchOptions} object.
51+
*
52+
* Even though this API isn't documented, it is still supported for legacy compatibility.
5153
*/
5254
public static launch(launcherVersion: string, arg: ILaunchOptions): void {
5355
const options: ILaunchOptions = Rush._normalizeLaunchOptions(arg);
5456

5557
Rush._printStartupBanner(options.isManaged);
5658

57-
const rushConfiguration: RushConfiguration | undefined = Rush._tryGetRushConfiguration();
5859
if (!options.alreadyReportedNodeTooNewError) {
59-
Rush._warnAboutNodeVersion(rushConfiguration);
60+
NodeJsCompatibility.warnAboutVersionTooNew(true);
6061
}
6162

6263
if (!CommandLineMigrationAdvisor.checkArgv(process.argv)) {
@@ -65,7 +66,7 @@ export class Rush {
6566
return;
6667
}
6768

68-
const parser: RushCommandLineParser = new RushCommandLineParser({ rushConfiguration });
69+
const parser: RushCommandLineParser = new RushCommandLineParser();
6970
parser.execute().catch(console.error); // CommandLineParser.execute() should never reject the promise
7071
}
7172

@@ -81,18 +82,11 @@ export class Rush {
8182

8283
Rush._printStartupBanner(options.isManaged);
8384

84-
const rushConfiguration: RushConfiguration | undefined = Rush._tryGetRushConfiguration();
8585
if (!options.alreadyReportedNodeTooNewError) {
86-
Rush._warnAboutNodeVersion(rushConfiguration);
86+
NodeJsCompatibility.warnAboutVersionTooNew(true);
8787
}
8888

89-
RushXCommandLine._launchRushXInternal(
90-
launcherVersion,
91-
{
92-
isManaged: options.isManaged,
93-
rushConfiguration: rushConfiguration
94-
}
95-
);
89+
RushXCommandLine.launchRushX(launcherVersion, options.isManaged);
9690
}
9791

9892
/**
@@ -103,18 +97,6 @@ export class Rush {
10397
return PackageJsonLookup.loadOwnPackageJson(__dirname).version;
10498
}
10599

106-
private static _tryGetRushConfiguration(): RushConfiguration | undefined {
107-
try {
108-
if (RushConfiguration.tryFindRushJsonLocation()) {
109-
return RushConfiguration.loadFromDefaultLocation({ showVerbose: true });
110-
}
111-
} catch (e) {
112-
// ignore
113-
}
114-
115-
return undefined;
116-
}
117-
118100
/**
119101
* This function normalizes legacy options to the current {@see ILaunchOptions} object.
120102
*/
@@ -128,7 +110,7 @@ export class Rush {
128110
const nodeVersion: string = process.versions.node;
129111
const nodeMajorVersion: number = semver.major(nodeVersion);
130112
const nodeReleaseLabel: string = (nodeMajorVersion % 2 === 0)
131-
? (!!(process as IExtendedNodeProcess).release.lts ? 'LTS' : 'pre-LTS')
113+
? (NodeJsCompatibility.isLtsVersion ? 'LTS' : 'pre-LTS')
132114
: 'unstable';
133115

134116
console.log(
@@ -140,30 +122,4 @@ export class Rush {
140122
EOL
141123
);
142124
}
143-
144-
private static _warnAboutNodeVersion(rushConfiguration: RushConfiguration | undefined): void {
145-
const nodeVersion: string = process.versions.node;
146-
147-
if (semver.satisfies(nodeVersion, '>= 11.0.0')) {
148-
console.log();
149-
console.warn(colors.yellow(
150-
`Your version of Node.js (${nodeVersion}) has not been tested with this release` +
151-
`of the Rush engine. Please consider upgrading the "rushVersion" setting in rush.json, ` +
152-
`or downgrading Node.js.`
153-
));
154-
console.log();
155-
} else if (
156-
rushConfiguration &&
157-
!rushConfiguration.suppressNodeLtsWarning &&
158-
!(process as IExtendedNodeProcess).release.lts
159-
) {
160-
console.log();
161-
console.warn(colors.yellow(
162-
`Your version of Node.js (${nodeVersion}) has an odd major version number. ` +
163-
`These releases frequently have bugs. Please consider installing a Long Term Support (LTS) ` +
164-
`version instead.`
165-
));
166-
console.log();
167-
}
168-
}
169125
}

apps/rush-lib/src/cli/RushCommandLineParser.ts

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,19 @@ import { GlobalScriptAction } from './scriptActions/GlobalScriptAction';
3535
import { Telemetry } from '../logic/Telemetry';
3636
import { AlreadyReportedError } from '../utilities/AlreadyReportedError';
3737
import { RushGlobalFolder } from '../api/RushGlobalFolder';
38+
import { NodeJsCompatibility } from '../logic/NodeJsCompatibility';
3839

3940
/**
4041
* Options for `RushCommandLineParser`.
4142
*/
4243
export interface IRushCommandLineParserOptions {
4344
cwd?: string; // Defaults to `cwd`
44-
rushConfiguration: RushConfiguration | undefined;
4545
}
4646

4747
export class RushCommandLineParser extends CommandLineParser {
4848
public telemetry: Telemetry | undefined;
4949
public rushGlobalFolder: RushGlobalFolder;
50+
public rushConfiguration: RushConfiguration;
5051

5152
private _debugParameter: CommandLineFlagParameter;
5253
private _rushOptions: IRushCommandLineParserOptions;
@@ -65,11 +66,20 @@ export class RushCommandLineParser extends CommandLineParser {
6566
});
6667

6768
this._rushOptions = this._normalizeOptions(options || {});
68-
this._populateActions();
69-
}
7069

71-
public get rushConfiguration(): RushConfiguration | undefined {
72-
return this._rushOptions.rushConfiguration;
70+
try {
71+
const rushJsonFilename: string | undefined = RushConfiguration.tryFindRushJsonLocation({
72+
startingFolder: this._rushOptions.cwd,
73+
showVerbose: true
74+
});
75+
if (rushJsonFilename) {
76+
this.rushConfiguration = RushConfiguration.loadFromConfigurationFile(rushJsonFilename);
77+
}
78+
} catch (error) {
79+
this._reportErrorAndSetExitCode(error);
80+
}
81+
82+
this._populateActions();
7383
}
7484

7585
public get isDebug(): boolean {
@@ -102,6 +112,8 @@ export class RushCommandLineParser extends CommandLineParser {
102112
InternalError.breakInDebugger = true;
103113
}
104114

115+
NodeJsCompatibility.warnAboutNonLtsVersion(this.rushConfiguration);
116+
105117
return this._wrapOnExecute().catch((error: Error) => {
106118
this._reportErrorAndSetExitCode(error);
107119
}).then(() => {
@@ -112,27 +124,13 @@ export class RushCommandLineParser extends CommandLineParser {
112124

113125
private _normalizeOptions(options: Partial<IRushCommandLineParserOptions>): IRushCommandLineParserOptions {
114126
const cwd: string = options.cwd || process.cwd();
115-
let rushConfiguration: RushConfiguration | undefined = options.rushConfiguration;
116-
117-
try {
118-
const rushJsonFilename: string | undefined = RushConfiguration.tryFindRushJsonLocation({
119-
startingFolder: cwd,
120-
showVerbose: true
121-
});
122-
if (rushJsonFilename) {
123-
rushConfiguration = RushConfiguration.loadFromConfigurationFile(rushJsonFilename);
124-
}
125-
} catch (error) {
126-
this._reportErrorAndSetExitCode(error);
127-
}
128-
129-
return { cwd, rushConfiguration };
127+
return { cwd };
130128
}
131129

132130
private _wrapOnExecute(): Promise<void> {
133131
try {
134-
if (this._rushOptions.rushConfiguration) {
135-
this.telemetry = new Telemetry(this._rushOptions.rushConfiguration);
132+
if (this.rushConfiguration) {
133+
this.telemetry = new Telemetry(this.rushConfiguration);
136134
}
137135
return super.onExecute().then(() => {
138136
if (this.telemetry) {
@@ -174,9 +172,9 @@ export class RushCommandLineParser extends CommandLineParser {
174172

175173
// If there is not a rush.json file, we still want "build" and "rebuild" to appear in the
176174
// command-line help
177-
if (this._rushOptions.rushConfiguration) {
175+
if (this.rushConfiguration) {
178176
const commandLineConfigFile: string = path.join(
179-
this._rushOptions.rushConfiguration.commonRushConfigFolder,
177+
this.rushConfiguration.commonRushConfigFolder,
180178
RushConstants.commandLineFilename
181179
);
182180

apps/rush-lib/src/cli/RushXCommandLine.ts

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,10 @@ import {
1313
import { Utilities } from '../utilities/Utilities';
1414
import { ProjectCommandSet } from '../logic/ProjectCommandSet';
1515
import { RushConfiguration } from '../api/RushConfiguration';
16-
17-
/**
18-
* @internal
19-
*/
20-
export interface ILaunchRushXInternalOptions {
21-
rushConfiguration: RushConfiguration | undefined;
22-
isManaged: boolean;
23-
}
16+
import { NodeJsCompatibility } from '../logic/NodeJsCompatibility';
2417

2518
export class RushXCommandLine {
2619
public static launchRushX(launcherVersion: string, isManaged: boolean): void {
27-
// Are we in a Rush repo?
28-
let rushConfiguration: RushConfiguration | undefined = undefined;
29-
if (RushConfiguration.tryFindRushJsonLocation()) {
30-
rushConfiguration = RushConfiguration.loadFromDefaultLocation({ showVerbose: true });
31-
}
32-
33-
RushXCommandLine._launchRushXInternal(
34-
launcherVersion,
35-
{ isManaged, rushConfiguration }
36-
);
37-
}
38-
39-
/**
40-
* @internal
41-
*/
42-
public static _launchRushXInternal(launcherVersion: string, options: ILaunchRushXInternalOptions): void {
4320
// Node.js can sometimes accidentally terminate with a zero exit code (e.g. for an uncaught
4421
// promise exception), so we start with the assumption that the exit code is 1
4522
// and set it to 0 only on success.
@@ -91,18 +68,26 @@ export class RushXCommandLine {
9168
return;
9269
}
9370

71+
// Are we in a Rush repo?
72+
let rushConfiguration: RushConfiguration | undefined = undefined;
73+
if (RushConfiguration.tryFindRushJsonLocation()) {
74+
rushConfiguration = RushConfiguration.loadFromDefaultLocation({ showVerbose: true });
75+
}
76+
77+
NodeJsCompatibility.warnAboutNonLtsVersion(rushConfiguration);
78+
9479
console.log('Executing: ' + JSON.stringify(scriptBody) + os.EOL);
9580

9681
const packageFolder: string = path.dirname(packageJsonFilePath);
9782

9883
const exitCode: number = Utilities.executeLifecycleCommand(
9984
scriptBody,
10085
{
101-
rushConfiguration: options.rushConfiguration,
86+
rushConfiguration,
10287
workingDirectory: packageFolder,
10388
// If there is a rush.json then use its .npmrc from the temp folder.
10489
// Otherwise look for npmrc in the project folder.
105-
initCwd: options.rushConfiguration ? options.rushConfiguration.commonTempFolder : packageFolder,
90+
initCwd: rushConfiguration ? rushConfiguration.commonTempFolder : packageFolder,
10691
handleOutput: false,
10792
environmentPathOptions: {
10893
includeProjectBin: true

apps/rush-lib/src/cli/test/RushCommandLineParser.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ function getCommandLineParserInstance(repoName: string, taskName: string): IPars
5252
// to exit and clear the Rush file lock. So running multiple `it` or `describe` test blocks over the same test
5353
// repo will fail due to contention over the same lock which is kept until the test runner process
5454
// ends.
55-
const parser: RushCommandLineParser = new RushCommandLineParser({ cwd: startPath, rushConfiguration: undefined });
55+
const parser: RushCommandLineParser = new RushCommandLineParser({ cwd: startPath });
5656

5757
// Mock the command
5858
process.argv = ['pretend-this-is-node.exe', 'pretend-this-is-rush', taskName];
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2+
// See LICENSE in the project root for license information.
3+
4+
import * as colors from 'colors';
5+
import * as semver from 'semver';
6+
7+
import { RushConfiguration } from '../api/RushConfiguration';
8+
9+
/**
10+
* This constant is the major version of the next LTS node Node.js release. This constant should be updated when
11+
* a new LTS version is added to Rush's support matrix.
12+
*/
13+
const UPCOMING_NODE_LTS_VERSION: number = 12;
14+
const nodeVersion: string = process.versions.node;
15+
16+
/**
17+
* This class provides useful functions for warning if the current Node.js runtime isn't supported.
18+
*
19+
* @internal
20+
*/
21+
export class NodeJsCompatibility {
22+
public static warnAboutVersionTooOld(): boolean {
23+
if (semver.satisfies(nodeVersion, '< 8.9.0')) {
24+
// We are on an ancient version of Node.js that is known not to work with Rush
25+
console.error(colors.red(
26+
`Your version of Node.js (${nodeVersion}) is very old and incompatible with Rush. ` +
27+
`Please upgrade to the latest Long-Term Support (LTS) version.`
28+
));
29+
30+
return true;
31+
} else {
32+
return false;
33+
}
34+
}
35+
36+
public static warnAboutVersionTooNew(isRushLib: boolean): boolean {
37+
if (semver.satisfies(nodeVersion, `>= ${UPCOMING_NODE_LTS_VERSION + 1}.0.0`)) {
38+
// We are on a much newer release than we have tested and support
39+
if (isRushLib) {
40+
console.warn(colors.yellow(
41+
`Your version of Node.js (${nodeVersion}) has not been tested with this release` +
42+
`of the Rush engine. Please consider upgrading the "rushVersion" setting in rush.json, ` +
43+
`or downgrading Node.js.`
44+
));
45+
} else {
46+
console.warn(colors.yellow(
47+
`Your version of Node.js (${nodeVersion}) has not been tested with this release ` +
48+
`of Rush. Please consider installing a newer version of the "@microsoft/rush" ` +
49+
`package, or downgrading Node.js.`
50+
));
51+
}
52+
53+
return true;
54+
} else {
55+
return false;
56+
}
57+
}
58+
59+
public static warnAboutNonLtsVersion(rushConfiguration: RushConfiguration | undefined): boolean {
60+
if (
61+
rushConfiguration &&
62+
!rushConfiguration.suppressNodeLtsWarning &&
63+
!NodeJsCompatibility.isLtsVersion
64+
) {
65+
console.warn(colors.yellow(
66+
`Your version of Node.js (${nodeVersion}) is an odd-numbered release. ` +
67+
`These releases frequently have bugs. Please consider installing a Long Term Support (LTS) ` +
68+
`version instead.`
69+
));
70+
71+
return true;
72+
} else {
73+
return false;
74+
}
75+
}
76+
77+
public static get isLtsVersion(): boolean {
78+
interface IExtendedNodeProcess extends NodeJS.Process {
79+
release: {
80+
lts?: string;
81+
};
82+
}
83+
84+
return !!(process as IExtendedNodeProcess).release.lts;
85+
}
86+
}

0 commit comments

Comments
 (0)