@@ -11,6 +11,17 @@ import type { RushConfigurationProject } from '../api/RushConfigurationProject';
1111import { type LockStepVersionPolicy , VersionPolicyDefinitionName } from '../api/VersionPolicy' ;
1212import 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 ) {
0 commit comments