diff --git a/common/changes/@microsoft/rush/add-rush-quiet-mode_2026-03-12-20-51.json b/common/changes/@microsoft/rush/add-rush-quiet-mode_2026-03-12-20-51.json new file mode 100644 index 00000000000..dc6f3446651 --- /dev/null +++ b/common/changes/@microsoft/rush/add-rush-quiet-mode_2026-03-12-20-51.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/rush", + "comment": "Add RUSH_QUIET_MODE environment variable that, when set to `1` or `true`, is equivalent to passing `--quiet` for `rush`, `rushx`, and `install-run-rush.ts`", + "type": "minor" + } + ], + "packageName": "@microsoft/rush" +} diff --git a/common/reviews/api/rush-lib.api.md b/common/reviews/api/rush-lib.api.md index e7004ddbbc2..14063d1543e 100644 --- a/common/reviews/api/rush-lib.api.md +++ b/common/reviews/api/rush-lib.api.md @@ -239,6 +239,7 @@ export class EnvironmentConfiguration { static parseBooleanEnvironmentVariable(name: string, value: string | undefined): boolean | undefined; static get pnpmStorePathOverride(): string | undefined; static get pnpmVerifyStoreIntegrity(): boolean | undefined; + static get quietMode(): boolean; static reset(): void; static get rushGlobalFolderOverride(): string | undefined; static get rushTempFolderOverride(): string | undefined; @@ -273,6 +274,7 @@ export const EnvironmentVariableNames: { readonly _RUSH_LIB_PATH: "_RUSH_LIB_PATH"; readonly RUSH_INVOKED_FOLDER: "RUSH_INVOKED_FOLDER"; readonly RUSH_INVOKED_ARGS: "RUSH_INVOKED_ARGS"; + readonly RUSH_QUIET_MODE: "RUSH_QUIET_MODE"; }; // @beta diff --git a/libraries/rush-lib/src/api/EnvironmentConfiguration.ts b/libraries/rush-lib/src/api/EnvironmentConfiguration.ts index f7a00179197..de8c8d2d2ff 100644 --- a/libraries/rush-lib/src/api/EnvironmentConfiguration.ts +++ b/libraries/rush-lib/src/api/EnvironmentConfiguration.ts @@ -245,7 +245,14 @@ export const EnvironmentVariableNames = { * Other lifecycle scripts should not make assumptions about Rush's command line syntax * if Rush did not explicitly pass along command-line parameters to their process. */ - RUSH_INVOKED_ARGS: 'RUSH_INVOKED_ARGS' + RUSH_INVOKED_ARGS: 'RUSH_INVOKED_ARGS', + + /** + * When set to `1` or `true`, this environment variable is equivalent to passing the `--quiet` flag + * to `rush`, `rushx`, and `install-run-rush.ts`. It suppresses informational startup messages + * while preserving error output. + */ + RUSH_QUIET_MODE: 'RUSH_QUIET_MODE' } as const; /** @@ -293,6 +300,8 @@ export class EnvironmentConfiguration { private static _tarBinaryPath: string | undefined; + private static _quietMode: boolean = false; + /** * If true, the environment configuration has been validated and initialized. */ @@ -456,6 +465,15 @@ export class EnvironmentConfiguration { return EnvironmentConfiguration._tarBinaryPath; } + /** + * If `true`, Rush will suppress informational startup messages, equivalent to passing `--quiet`. + * See {@link EnvironmentVariableNames.RUSH_QUIET_MODE} + */ + public static get quietMode(): boolean { + EnvironmentConfiguration._ensureValidated(); + return EnvironmentConfiguration._quietMode; + } + /** * The front-end RushVersionSelector relies on `RUSH_GLOBAL_FOLDER`, so its value must be read before * `EnvironmentConfiguration` is initialized (and actually before the correct version of `EnvironmentConfiguration` @@ -606,6 +624,20 @@ export class EnvironmentConfiguration { break; } + case EnvironmentVariableNames.RUSH_QUIET_MODE: { + // Accept both "true"/"false" string values and the standard "1"/"0" values + if (value === 'true' || value === 'false') { + EnvironmentConfiguration._quietMode = value === 'true'; + } else { + EnvironmentConfiguration._quietMode = + EnvironmentConfiguration.parseBooleanEnvironmentVariable( + EnvironmentVariableNames.RUSH_QUIET_MODE, + value + ) ?? false; + } + break; + } + case EnvironmentVariableNames.RUSH_PARALLELISM: case EnvironmentVariableNames.RUSH_PREVIEW_VERSION: case EnvironmentVariableNames.RUSH_VARIANT: @@ -661,7 +693,9 @@ export class EnvironmentConfiguration { */ public static reset(): void { EnvironmentConfiguration._rushTempFolderOverride = undefined; - + EnvironmentConfiguration._quietMode = false; + EnvironmentConfiguration._gitBinaryPath = undefined; + EnvironmentConfiguration._tarBinaryPath = undefined; EnvironmentConfiguration._hasBeenValidated = false; } diff --git a/libraries/rush-lib/src/cli/RushCommandLineParser.ts b/libraries/rush-lib/src/cli/RushCommandLineParser.ts index 7828eb1e90d..cce1a59d91c 100644 --- a/libraries/rush-lib/src/cli/RushCommandLineParser.ts +++ b/libraries/rush-lib/src/cli/RushCommandLineParser.ts @@ -63,6 +63,7 @@ import { InitSubspaceAction } from './actions/InitSubspaceAction'; import { RushAlerts } from '../utilities/RushAlerts'; import { initializeDotEnv } from '../logic/dotenv'; import { measureAsyncFn } from '../utilities/performance'; +import { EnvironmentVariableNames } from '../api/EnvironmentConfiguration'; /** * Options for `RushCommandLineParser`. @@ -220,6 +221,12 @@ export class RushCommandLineParser extends CommandLineParser { } } + const quietModeValue: string | undefined = + process.env[EnvironmentVariableNames.RUSH_QUIET_MODE]; + if (quietModeValue === '1' || quietModeValue === 'true') { + return true; + } + return false; } diff --git a/libraries/rush-lib/src/cli/RushXCommandLine.ts b/libraries/rush-lib/src/cli/RushXCommandLine.ts index 03648e831b8..20a856b1f7b 100644 --- a/libraries/rush-lib/src/cli/RushXCommandLine.ts +++ b/libraries/rush-lib/src/cli/RushXCommandLine.ts @@ -295,6 +295,12 @@ export class RushXCommandLine { } } + const quietModeValue: string | undefined = + process.env[EnvironmentVariableNames.RUSH_QUIET_MODE]; + if (quietModeValue === '1' || quietModeValue === 'true') { + quiet = true; + } + if (!commandName) { help = true; } diff --git a/libraries/rush-lib/src/scripts/install-run-rush.ts b/libraries/rush-lib/src/scripts/install-run-rush.ts index bfb986d46e4..6fa7e8b21b5 100644 --- a/libraries/rush-lib/src/scripts/install-run-rush.ts +++ b/libraries/rush-lib/src/scripts/install-run-rush.ts @@ -16,6 +16,7 @@ import type { ILogger } from '../utilities/npmrcUtilities'; const PACKAGE_NAME: string = '@microsoft/rush'; const RUSH_PREVIEW_VERSION: string = 'RUSH_PREVIEW_VERSION'; +const RUSH_QUIET_MODE: string = 'RUSH_QUIET_MODE'; const INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE: 'INSTALL_RUN_RUSH_LOCKFILE_PATH' = 'INSTALL_RUN_RUSH_LOCKFILE_PATH'; @@ -72,7 +73,9 @@ function _run(): void { } let commandFound: boolean = false; - let logger: ILogger = { info: console.log, error: console.error }; + + const quietModeEnvValue: string | undefined = process.env[RUSH_QUIET_MODE]; + let quiet: boolean = quietModeEnvValue === '1' || quietModeEnvValue === 'true'; for (const arg of packageBinArgs) { if (arg === '-q' || arg === '--quiet') { @@ -82,10 +85,7 @@ function _run(): void { // To maintain the same user experience, the install-run* scripts pass along this // flag but also use it to suppress any diagnostic information normally printed // to stdout. - logger = { - info: () => {}, - error: console.error - }; + quiet = true; } else if (!arg.startsWith('-') || arg === '-h' || arg === '--help') { // We either found something that looks like a command (i.e. - doesn't start with a "-"), // or we found the -h/--help flag, which can be run without a command @@ -105,6 +105,10 @@ function _run(): void { process.exit(1); } + const logger: ILogger = quiet + ? { info: () => {}, error: console.error } + : { info: console.log, error: console.error }; + runWithErrorAndStatusCode(logger, () => { const version: string = _getRushVersion(logger); logger.info(`The ${RUSH_JSON_FILENAME} configuration requests Rush version ${version}`);