Skip to content

Commit 167851c

Browse files
committed
Add Rush reporter repository configuration
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
1 parent b2949c7 commit 167851c

11 files changed

Lines changed: 224 additions & 2 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@microsoft/rush",
5+
"comment": "Add repository configuration for opting into and configuring the experimental Rush reporter.",
6+
"type": "patch"
7+
}
8+
],
9+
"packageName": "@microsoft/rush",
10+
"email": "TheLarkInn@users.noreply.github.com"
11+
}

common/reviews/api/rush-lib.api.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ export interface IExperimentsJson {
498498
usePnpmLockfileOnlyThenFrozenLockfileForRushUpdate?: boolean;
499499
usePnpmPreferFrozenLockfileForRushUpdate?: boolean;
500500
usePnpmSyncForInjectedDependencies?: boolean;
501+
useRushReporter?: boolean;
501502
}
502503

503504
// @beta
@@ -972,6 +973,11 @@ export interface _IRushProjectJson {
972973
operationSettings?: IOperationSettings[];
973974
}
974975

976+
// @beta
977+
export interface IRushReportingConfiguration {
978+
readonly agentEnvironmentVariables: readonly string[];
979+
}
980+
975981
// @beta (undocumented)
976982
export interface IRushSessionOptions {
977983
// (undocumented)
@@ -1472,6 +1478,8 @@ export class RushConfiguration {
14721478
get projectsByName(): ReadonlyMap<string, RushConfigurationProject>;
14731479
// @beta
14741480
get projectsByTag(): ReadonlyMap<string, ReadonlySet<RushConfigurationProject>>;
1481+
// @beta
1482+
readonly reportingConfiguration: IRushReportingConfiguration;
14751483
readonly repositoryDefaultBranch: string;
14761484
get repositoryDefaultFullyQualifiedRemoteBranch(): string;
14771485
readonly repositoryDefaultRemote: string;

libraries/rush-lib/assets/rush-init/common/config/rush/experiments.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,11 @@
150150
* help prevent operation scripts from accidentally depending on Rush's own internal environment
151151
* variables.
152152
*/
153-
/*[LINE "HYPOTHETICAL"]*/ "trimRushEnvironmentVariablesForOperations": true
153+
/*[LINE "HYPOTHETICAL"]*/ "trimRushEnvironmentVariablesForOperations": true,
154+
155+
/**
156+
* If true, Rush may use the experimental Rush reporter system. If omitted or false,
157+
* Rush preserves the legacy reporting behavior.
158+
*/
159+
/*[LINE "HYPOTHETICAL"]*/ "useRushReporter": true
154160
}

libraries/rush-lib/assets/rush-init/rush.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,19 @@
316316
*/
317317
/*[LINE "HYPOTHETICAL"]*/ "telemetryEnabled": false,
318318

319+
/**
320+
* Configures repository settings used by the experimental Rush reporter system.
321+
*/
322+
/*[BEGIN "HYPOTHETICAL"]*/
323+
"reporting": {
324+
/**
325+
* Additional environment variable names that identify an agent environment.
326+
* The built-in COPILOT_CLI variable does not need to be listed here.
327+
*/
328+
"agentEnvironmentVariables": ["MY_AGENT_CLI", "ANOTHER_AGENT"]
329+
},
330+
/*[END "HYPOTHETICAL"]*/
331+
319332
/**
320333
* Allows creation of hotfix changes. This feature is experimental so it is disabled by default.
321334
* If this is set, 'rush change' only allows a 'hotfix' change type to be specified. This change type

libraries/rush-lib/src/api/ExperimentsConfiguration.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ export interface IExperimentsJson {
162162
* variables.
163163
*/
164164
trimRushEnvironmentVariablesForOperations?: boolean;
165+
166+
/**
167+
* If true, Rush may use the experimental Rush reporter system. If omitted or false,
168+
* Rush preserves the legacy reporting behavior.
169+
*/
170+
useRushReporter?: boolean;
165171
}
166172

167173
const _EXPERIMENTS_JSON_SCHEMA: JsonSchema = JsonSchema.fromLoadedObject(schemaJson);

libraries/rush-lib/src/api/RushConfiguration.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,21 @@ export interface IRushVariantOptionsJson {
154154
description: string;
155155
}
156156

157+
interface IRushReportingConfigurationJson {
158+
agentEnvironmentVariables?: string[];
159+
}
160+
161+
/**
162+
* Repository settings used by the Rush reporter system.
163+
* @beta
164+
*/
165+
export interface IRushReportingConfiguration {
166+
/**
167+
* Additional environment variable names that identify an agent environment.
168+
*/
169+
readonly agentEnvironmentVariables: readonly string[];
170+
}
171+
157172
/**
158173
* This represents the JSON data structure for the "rush.json" configuration file.
159174
* See rush.schema.json for documentation.
@@ -184,6 +199,7 @@ export interface IRushConfigurationJson {
184199
yarnOptions?: IYarnOptionsJson;
185200
ensureConsistentVersions?: boolean;
186201
variants?: IRushVariantOptionsJson[];
202+
reporting?: IRushReportingConfigurationJson;
187203
}
188204

189205
/**
@@ -523,6 +539,12 @@ export class RushConfiguration {
523539
*/
524540
public readonly telemetryEnabled: boolean;
525541

542+
/**
543+
* Repository settings used by the Rush reporter system.
544+
* @beta
545+
*/
546+
public readonly reportingConfiguration: IRushReportingConfiguration;
547+
526548
/**
527549
* {@inheritDoc NpmOptionsConfiguration}
528550
*/
@@ -853,6 +875,9 @@ export class RushConfiguration {
853875
}
854876

855877
this.telemetryEnabled = !!rushConfigurationJson.telemetryEnabled;
878+
this.reportingConfiguration = {
879+
agentEnvironmentVariables: rushConfigurationJson.reporting?.agentEnvironmentVariables || []
880+
};
856881
this.eventHooks = new EventHooks(rushConfigurationJson.eventHooks || {});
857882

858883
this.versionPolicyConfigurationFilePath = path.join(
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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 path from 'node:path';
5+
6+
import { FileSystem, JsonFile } from '@rushstack/node-core-library';
7+
8+
import { ExperimentsConfiguration } from '../ExperimentsConfiguration';
9+
10+
const TEMP_FOLDER: string = path.join(__dirname, 'temp', ExperimentsConfiguration.name);
11+
const EXPERIMENTS_JSON_PATH: string = path.join(TEMP_FOLDER, 'experiments.json');
12+
13+
describe(ExperimentsConfiguration.name, () => {
14+
beforeEach(() => {
15+
FileSystem.ensureEmptyFolder(TEMP_FOLDER);
16+
});
17+
18+
afterEach(() => {
19+
FileSystem.ensureEmptyFolder(TEMP_FOLDER);
20+
});
21+
22+
it('preserves legacy reporting behavior when the experiment file is absent', () => {
23+
const experimentsConfiguration: ExperimentsConfiguration = new ExperimentsConfiguration(
24+
EXPERIMENTS_JSON_PATH
25+
);
26+
27+
expect(experimentsConfiguration.configuration.useRushReporter).toBeUndefined();
28+
});
29+
30+
it('loads the Rush reporter opt-in', () => {
31+
JsonFile.save({ useRushReporter: true }, EXPERIMENTS_JSON_PATH);
32+
33+
const experimentsConfiguration: ExperimentsConfiguration = new ExperimentsConfiguration(
34+
EXPERIMENTS_JSON_PATH
35+
);
36+
37+
expect(experimentsConfiguration.configuration.useRushReporter).toBe(true);
38+
});
39+
40+
it('keeps an explicit false value disabled', () => {
41+
JsonFile.save({ useRushReporter: false }, EXPERIMENTS_JSON_PATH);
42+
43+
const experimentsConfiguration: ExperimentsConfiguration = new ExperimentsConfiguration(
44+
EXPERIMENTS_JSON_PATH
45+
);
46+
47+
expect(experimentsConfiguration.configuration.useRushReporter).toBe(false);
48+
});
49+
50+
it('rejects a non-boolean Rush reporter opt-in', () => {
51+
JsonFile.save({ useRushReporter: 'yes' }, EXPERIMENTS_JSON_PATH);
52+
53+
expect(() => new ExperimentsConfiguration(EXPERIMENTS_JSON_PATH)).toThrow(/useRushReporter/);
54+
});
55+
});
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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 path from 'node:path';
5+
6+
import { FileSystem, JsonFile } from '@rushstack/node-core-library';
7+
8+
import { Rush } from '../Rush';
9+
import { RushConfiguration } from '../RushConfiguration';
10+
11+
const TEMP_FOLDER: string = path.join(__dirname, 'temp', 'RushConfigurationReporting');
12+
const RUSH_JSON_PATH: string = path.join(TEMP_FOLDER, 'rush.json');
13+
14+
function writeRushJson(reporting?: unknown): void {
15+
JsonFile.save(
16+
{
17+
rushVersion: Rush.version,
18+
pnpmVersion: '10.0.0',
19+
projects: [],
20+
...(reporting === undefined ? {} : { reporting })
21+
},
22+
RUSH_JSON_PATH
23+
);
24+
}
25+
26+
describe('RushConfiguration reporting configuration', () => {
27+
beforeEach(() => {
28+
FileSystem.ensureEmptyFolder(TEMP_FOLDER);
29+
});
30+
31+
afterEach(() => {
32+
FileSystem.ensureEmptyFolder(TEMP_FOLDER);
33+
});
34+
35+
it('defaults agent environment variables to an empty array', () => {
36+
writeRushJson();
37+
38+
const rushConfiguration: RushConfiguration = RushConfiguration.loadFromConfigurationFile(RUSH_JSON_PATH);
39+
40+
expect(rushConfiguration.reportingConfiguration.agentEnvironmentVariables).toEqual([]);
41+
});
42+
43+
it('loads configured agent environment variables', () => {
44+
writeRushJson({
45+
agentEnvironmentVariables: ['MY_AGENT_CLI', 'ANOTHER_AGENT']
46+
});
47+
48+
const rushConfiguration: RushConfiguration = RushConfiguration.loadFromConfigurationFile(RUSH_JSON_PATH);
49+
50+
expect(rushConfiguration.reportingConfiguration.agentEnvironmentVariables).toEqual([
51+
'MY_AGENT_CLI',
52+
'ANOTHER_AGENT'
53+
]);
54+
});
55+
56+
it('rejects invalid agent environment variables', () => {
57+
writeRushJson({
58+
agentEnvironmentVariables: ['MY_AGENT_CLI', 123]
59+
});
60+
61+
expect(() => RushConfiguration.loadFromConfigurationFile(RUSH_JSON_PATH)).toThrow(
62+
/agentEnvironmentVariables/
63+
);
64+
});
65+
66+
it('rejects unsupported reporting settings', () => {
67+
writeRushJson({
68+
agentEnvironmentVariables: [],
69+
defaultReporter: 'ai'
70+
});
71+
72+
expect(() => RushConfiguration.loadFromConfigurationFile(RUSH_JSON_PATH)).toThrow(/defaultReporter/);
73+
});
74+
});

libraries/rush-lib/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ export {
2020

2121
export { ApprovedPackagesPolicy } from './api/ApprovedPackagesPolicy';
2222

23-
export { RushConfiguration, type ITryFindRushJsonLocationOptions } from './api/RushConfiguration';
23+
export {
24+
RushConfiguration,
25+
type IRushReportingConfiguration,
26+
type ITryFindRushJsonLocationOptions
27+
} from './api/RushConfiguration';
2428

2529
export { Subspace } from './api/Subspace';
2630
export { SubspacesConfiguration } from './api/SubspacesConfiguration';

libraries/rush-lib/src/schemas/experiments.schema.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@
9797
"trimRushEnvironmentVariablesForOperations": {
9898
"description": "By default, Rush forwards its entire process environment (minus a small denylist) to the shell commands it invokes for operations (e.g. 'build', 'test'). If true, environment variables whose names begin with `RUSH_` will additionally be omitted from that forwarded environment. This can help prevent operation scripts from accidentally depending on Rush's own internal environment variables.",
9999
"type": "boolean"
100+
},
101+
"useRushReporter": {
102+
"description": "If true, Rush may use the experimental Rush reporter system. If omitted or false, Rush preserves the legacy reporting behavior.",
103+
"type": "boolean"
100104
}
101105
},
102106
"additionalProperties": false

0 commit comments

Comments
 (0)