Skip to content

Commit 22d75a3

Browse files
committed
Refactor ChangeFiles API.
1 parent 523f4b9 commit 22d75a3

10 files changed

Lines changed: 210 additions & 129 deletions

File tree

libraries/rush-lib/src/cli/actions/ChangeAction.ts

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -382,32 +382,31 @@ export class ChangeAction extends BaseRushAction {
382382
}
383383

384384
private async _verifyAsync(): Promise<void> {
385-
const changedPackages: string[] = await this._getChangedProjectNamesAsync();
386-
const strictValidation: boolean =
387-
!!this.rushConfiguration.experimentsConfiguration.configuration.strictChangefileValidation;
385+
const changedProjectNames: string[] = await this._getChangedProjectNamesAsync();
386+
const strictValidation: boolean | undefined =
387+
this.rushConfiguration.experimentsConfiguration.configuration.strictChangefileValidation;
388388

389389
// When strict validation is enabled, validate ALL change files to catch references to
390390
// deleted or nonexistent projects. Otherwise, only validate change files added on this branch.
391+
const changeFilesInstance: ChangeFiles = new ChangeFiles(this.rushConfiguration);
391392
let filesToValidate: string[];
392393
if (strictValidation) {
393-
const changeFilesInstance: ChangeFiles = new ChangeFiles(this.rushConfiguration.changesFolder);
394-
filesToValidate = await changeFilesInstance.getFilesAsync();
394+
filesToValidate = await changeFilesInstance.getAllChangeFilesAsync();
395395
} else {
396396
filesToValidate = await this._getChangeFilesAsync();
397397
}
398398

399-
if (changedPackages.length > 0 || filesToValidate.length > 0) {
399+
if (changedProjectNames.length > 0 || filesToValidate.length > 0) {
400400
const deletedProjectNames: Set<string> | undefined = strictValidation
401401
? await this._getDeletedProjectNamesAsync()
402402
: undefined;
403403

404-
await ChangeFiles.validateAsync(
405-
this.terminal,
404+
await changeFilesInstance.validateAsync({
405+
terminal: this.terminal,
406406
filesToValidate,
407-
changedPackages,
408-
this.rushConfiguration,
407+
changedProjectNames,
409408
deletedProjectNames
410-
);
409+
});
411410
} else {
412411
this._logNoChangeFileRequired();
413412
}
@@ -460,16 +459,15 @@ export class ChangeAction extends BaseRushAction {
460459
);
461460
}
462461

463-
const changeFiles: ChangeFiles = new ChangeFiles(this.rushConfiguration.changesFolder);
464-
const allChangeFiles: string[] = await changeFiles.getFilesAsync();
462+
const changeFiles: ChangeFiles = new ChangeFiles(this.rushConfiguration);
463+
const allChangeFiles: string[] = await changeFiles.getAllChangeFilesAsync();
465464
const deletedProjectNames: Set<string> = await this._getDeletedProjectNamesAsync();
466-
await ChangeFiles.validateAsync(
467-
this.terminal,
468-
allChangeFiles,
469-
[],
470-
this.rushConfiguration,
465+
await changeFiles.validateAsync({
466+
terminal: this.terminal,
467+
filesToValidate: allChangeFiles,
468+
changedProjectNames: [],
471469
deletedProjectNames
472-
);
470+
});
473471
}
474472

475473
/**

libraries/rush-lib/src/cli/actions/PublishAction.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -281,11 +281,7 @@ export class PublishAction extends BaseRushAction {
281281
allPackages: ReadonlyMap<string, RushConfigurationProject>
282282
): Promise<void> {
283283
const changeManager: ChangeManager = new ChangeManager(this.rushConfiguration);
284-
await changeManager.loadAsync(
285-
this.rushConfiguration.changesFolder,
286-
this._prereleaseToken,
287-
this._addCommitDetails.value
288-
);
284+
await changeManager.loadAsync(this._prereleaseToken, this._addCommitDetails.value);
289285

290286
if (changeManager.hasChanges()) {
291287
const orderedChanges: IChangeInfo[] = changeManager.packageChanges;

libraries/rush-lib/src/logic/ChangeFiles.ts

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ import type { RushConfigurationProject } from '../api/RushConfigurationProject';
1111
import { type LockStepVersionPolicy, VersionPolicyDefinitionName } from '../api/VersionPolicy';
1212
import schemaJson from '../schemas/change-file.schema.json';
1313

14+
export interface IValidateOptions {
15+
terminal: ITerminal;
16+
filesToValidate: Iterable<string>;
17+
changedProjectNames: Iterable<string>;
18+
/**
19+
* Optional set of project names that were removed from rush.json.
20+
* When provided, produces a more specific error message for these projects.
21+
*/
22+
deletedProjectNames?: ReadonlySet<string>;
23+
}
24+
1425
/**
1526
* This class represents the collection of change files existing in the repo and provides operations
1627
* for those change files.
@@ -20,37 +31,38 @@ export class ChangeFiles {
2031
* Change file path relative to changes folder.
2132
*/
2233
private _files: string[] | undefined;
23-
private _changesPath: string;
34+
private readonly _rushConfiguration: RushConfiguration;
35+
private readonly _changesPath: string;
2436

25-
public constructor(changesPath: string) {
26-
this._changesPath = changesPath;
37+
public constructor(rushConfiguration: RushConfiguration) {
38+
this._rushConfiguration = rushConfiguration;
39+
this._changesPath = rushConfiguration.changesFolder;
2740
}
2841

2942
/**
3043
* Validate if the newly added change files match the changed packages.
31-
*
32-
* @param deletedProjectNames - Optional set of project names that were removed from rush.json.
33-
* When provided, produces a more specific error message for these projects.
3444
*/
35-
public static async validateAsync(
36-
terminal: ITerminal,
37-
newChangeFilePaths: string[],
38-
changedPackages: string[],
39-
rushConfiguration: RushConfiguration,
40-
deletedProjectNames?: ReadonlySet<string>
41-
): Promise<void> {
45+
public async validateAsync(options: IValidateOptions): Promise<void> {
46+
const { terminal, filesToValidate, changedProjectNames, deletedProjectNames } = options;
4247
const schema: JsonSchema = JsonSchema.fromLoadedObject(schemaJson);
48+
const rushConfiguration: RushConfiguration = this._rushConfiguration;
49+
const {
50+
hotfixChangeEnabled,
51+
experimentsConfiguration: {
52+
configuration: { strictChangefileValidation }
53+
}
54+
} = rushConfiguration;
4355

4456
const projectsWithChangeDescriptions: Set<string> = new Set();
4557
const changefilesByProjectName: Map<string, string[]> = new Map();
4658
await Async.forEachAsync(
47-
newChangeFilePaths,
59+
filesToValidate,
4860
async (filePath) => {
4961
terminal.writeLine(`Found change file: ${filePath}`);
5062

5163
const changeFile: IChangeInfo = JsonFile.loadAndValidate(filePath, schema);
5264

53-
if (rushConfiguration.hotfixChangeEnabled) {
65+
if (hotfixChangeEnabled) {
5466
if (changeFile && changeFile.changes) {
5567
for (const change of changeFile.changes) {
5668
if (change.type !== 'none' && change.type !== 'hotfix') {
@@ -81,7 +93,7 @@ export class ChangeFiles {
8193
{ concurrency: 50 }
8294
);
8395

84-
if (rushConfiguration.experimentsConfiguration.configuration.strictChangefileValidation) {
96+
if (strictChangefileValidation) {
8597
const errors: string[] = [];
8698

8799
for (const packageName of projectsWithChangeDescriptions) {
@@ -121,7 +133,7 @@ export class ChangeFiles {
121133
}
122134
}
123135

124-
const projectsMissingChangeDescriptions: Set<string> = new Set(changedPackages);
136+
const projectsMissingChangeDescriptions: Set<string> = new Set(changedProjectNames);
125137
for (const name of projectsWithChangeDescriptions) {
126138
projectsMissingChangeDescriptions.delete(name);
127139
}
@@ -167,7 +179,7 @@ export class ChangeFiles {
167179
/**
168180
* Get the array of absolute paths of change files.
169181
*/
170-
public async getFilesAsync(): Promise<string[]> {
182+
public async getAllChangeFilesAsync(): Promise<string[]> {
171183
if (!this._files) {
172184
const { default: glob } = await import('fast-glob');
173185
this._files = (await glob('**/*.json', { cwd: this._changesPath, absolute: true })) || [];
@@ -198,7 +210,7 @@ export class ChangeFiles {
198210
packagesToInclude.add(changelog.name);
199211
});
200212

201-
const files: string[] = await this.getFilesAsync();
213+
const files: string[] = await this.getAllChangeFilesAsync();
202214
const filesToDelete: string[] = [];
203215
await Async.forEachAsync(
204216
files,
@@ -222,7 +234,7 @@ export class ChangeFiles {
222234
return await this._deleteFilesAsync(terminal, filesToDelete, shouldDelete);
223235
} else {
224236
// Delete all change files.
225-
const files: string[] = await this.getFilesAsync();
237+
const files: string[] = await this.getAllChangeFilesAsync();
226238
return await this._deleteFilesAsync(terminal, files, shouldDelete);
227239
}
228240
}
@@ -238,7 +250,7 @@ export class ChangeFiles {
238250
);
239251

240252
await Async.forEachAsync(
241-
files,
253+
files.sort(),
242254
async (filePath) => {
243255
terminal.writeLine(` - ${filePath}`);
244256
if (shouldDelete) {

libraries/rush-lib/src/logic/ChangeManager.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,18 @@ export class ChangeManager {
3434

3535
/**
3636
* Load changes from change files
37-
* @param changesPath - location of change files
3837
* @param prereleaseToken - prerelease token
3938
* @param includeCommitDetails - whether commit details need to be included in changes
4039
*/
4140
public async loadAsync(
42-
changesPath: string,
4341
prereleaseToken: PrereleaseToken = new PrereleaseToken(),
4442
includeCommitDetails: boolean = false
4543
): Promise<void> {
4644
this._allPackages = this._rushConfiguration.projectsByName;
4745

4846
this._prereleaseToken = prereleaseToken;
4947

50-
this._changeFiles = new ChangeFiles(changesPath);
48+
this._changeFiles = new ChangeFiles(this._rushConfiguration);
5149
this._allChanges = await PublishUtilities.findChangeRequestsAsync(
5250
this._allPackages,
5351
this._rushConfiguration,

libraries/rush-lib/src/logic/PublishUtilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export class PublishUtilities {
7878
// eslint-disable-next-line no-console
7979
console.log(`Finding changes in: ${changeFiles.getChangesPath()}`);
8080

81-
const files: string[] = await changeFiles.getFilesAsync();
81+
const files: string[] = await changeFiles.getAllChangeFilesAsync();
8282

8383
// Add the minimum changes defined by the change descriptions.
8484
for (const changeFilePath of files) {

libraries/rush-lib/src/logic/VersionManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export class VersionManager {
9090
this._getManuallyVersionedProjects()
9191
);
9292

93-
await changeManager.loadAsync(this._rushConfiguration.changesFolder);
93+
await changeManager.loadAsync();
9494
if (changeManager.hasChanges()) {
9595
changeManager.validateChanges(this._versionPolicyConfiguration);
9696
changeManager.apply(!!shouldCommit)!.forEach((packageJson) => {

0 commit comments

Comments
 (0)