22// See LICENSE in the project root for license information.
33
44import { createHash } from 'node:crypto' ;
5- import * as path from 'path' ;
65
76import {
87 JsonFile ,
@@ -18,7 +17,7 @@ import { FileSystemBuildCacheProvider } from '../logic/buildCache/FileSystemBuil
1817import { RushConstants } from '../logic/RushConstants' ;
1918import type { ICloudBuildCacheProvider } from '../logic/buildCache/ICloudBuildCacheProvider' ;
2019import { RushUserConfiguration } from './RushUserConfiguration' ;
21- import { EnvironmentConfiguration } from './EnvironmentConfiguration' ;
20+ import { EnvironmentConfiguration , EnvironmentVariableNames } from './EnvironmentConfiguration' ;
2221import {
2322 CacheEntryId ,
2423 type IGenerateCacheEntryIdOptions ,
@@ -83,14 +82,14 @@ interface IBuildCacheConfigurationOptions {
8382 cloudCacheProvider : ICloudBuildCacheProvider | undefined ;
8483}
8584
85+ const BUILD_CACHE_JSON_SCHEMA : JsonSchema = JsonSchema . fromLoadedObject ( schemaJson ) ;
86+
8687/**
8788 * Use this class to load and save the "common/config/rush/build-cache.json" config file.
8889 * This file provides configuration options for cached project build output.
8990 * @beta
9091 */
9192export class BuildCacheConfiguration {
92- private static _jsonSchema : JsonSchema = JsonSchema . fromLoadedObject ( schemaJson ) ;
93-
9493 /**
9594 * Indicates whether the build cache feature is enabled.
9695 * Typically it is enabled in the build-cache.json config file.
@@ -146,11 +145,12 @@ export class BuildCacheConfiguration {
146145 rushConfiguration : RushConfiguration ,
147146 rushSession : RushSession
148147 ) : Promise < BuildCacheConfiguration | undefined > {
149- const jsonFilePath : string = BuildCacheConfiguration . getBuildCacheConfigFilePath ( rushConfiguration ) ;
150- if ( ! FileSystem . exists ( jsonFilePath ) ) {
151- return undefined ;
152- }
153- return await BuildCacheConfiguration . _loadAsync ( jsonFilePath , terminal , rushConfiguration , rushSession ) ;
148+ const { buildCacheConfiguration } = await BuildCacheConfiguration . _tryLoadInternalAsync (
149+ terminal ,
150+ rushConfiguration ,
151+ rushSession
152+ ) ;
153+ return buildCacheConfiguration ;
154154 }
155155
156156 /**
@@ -162,51 +162,85 @@ export class BuildCacheConfiguration {
162162 rushConfiguration : RushConfiguration ,
163163 rushSession : RushSession
164164 ) : Promise < BuildCacheConfiguration > {
165- const jsonFilePath : string = BuildCacheConfiguration . getBuildCacheConfigFilePath ( rushConfiguration ) ;
166- if ( ! FileSystem . exists ( jsonFilePath ) ) {
165+ const { buildCacheConfiguration, jsonFilePath } = await BuildCacheConfiguration . _tryLoadInternalAsync (
166+ terminal ,
167+ rushConfiguration ,
168+ rushSession
169+ ) ;
170+
171+ if ( ! buildCacheConfiguration ) {
167172 terminal . writeErrorLine (
168173 `The build cache feature is not enabled. This config file is missing:\n` + jsonFilePath
169174 ) ;
170175 terminal . writeLine ( `\nThe Rush website documentation has instructions for enabling the build cache.` ) ;
171176 throw new AlreadyReportedError ( ) ;
172177 }
173178
174- const buildCacheConfiguration : BuildCacheConfiguration = await BuildCacheConfiguration . _loadAsync (
175- jsonFilePath ,
176- terminal ,
177- rushConfiguration ,
178- rushSession
179- ) ;
180-
181179 if ( ! buildCacheConfiguration . buildCacheEnabled ) {
182180 terminal . writeErrorLine (
183181 `The build cache feature is not enabled. You can enable it by editing this config file:\n` +
184182 jsonFilePath
185183 ) ;
186184 throw new AlreadyReportedError ( ) ;
187185 }
186+
188187 return buildCacheConfiguration ;
189188 }
190189
191190 /**
192191 * Gets the absolute path to the build-cache.json file in the specified rush workspace.
193192 */
194193 public static getBuildCacheConfigFilePath ( rushConfiguration : RushConfiguration ) : string {
195- return path . resolve ( rushConfiguration . commonRushConfigFolder , RushConstants . buildCacheFilename ) ;
194+ return `${ rushConfiguration . commonRushConfigFolder } /${ RushConstants . buildCacheFilename } ` ;
195+ }
196+
197+ private static async _tryLoadInternalAsync (
198+ terminal : ITerminal ,
199+ rushConfiguration : RushConfiguration ,
200+ rushSession : RushSession
201+ ) : Promise < { buildCacheConfiguration : BuildCacheConfiguration | undefined ; jsonFilePath : string } > {
202+ const jsonFilePath : string = BuildCacheConfiguration . getBuildCacheConfigFilePath ( rushConfiguration ) ;
203+ const buildCacheConfiguration : BuildCacheConfiguration | undefined =
204+ await BuildCacheConfiguration . _tryLoadAsync ( jsonFilePath , terminal , rushConfiguration , rushSession ) ;
205+ return { buildCacheConfiguration, jsonFilePath } ;
196206 }
197207
198- private static async _loadAsync (
208+ private static async _tryLoadAsync (
199209 jsonFilePath : string ,
200210 terminal : ITerminal ,
201211 rushConfiguration : RushConfiguration ,
202212 rushSession : RushSession
203- ) : Promise < BuildCacheConfiguration > {
204- const buildCacheJson : IBuildCacheJson = await JsonFile . loadAndValidateAsync (
205- jsonFilePath ,
206- BuildCacheConfiguration . _jsonSchema
207- ) ;
208- const rushUserConfiguration : RushUserConfiguration = await RushUserConfiguration . initializeAsync ( ) ;
213+ ) : Promise < BuildCacheConfiguration | undefined > {
214+ let buildCacheJson : IBuildCacheJson ;
215+ const buildCacheOverrideJson : string | undefined = EnvironmentConfiguration . buildCacheOverrideJson ;
216+ if ( buildCacheOverrideJson ) {
217+ buildCacheJson = JsonFile . parseString ( buildCacheOverrideJson ) ;
218+ BUILD_CACHE_JSON_SCHEMA . validateObject (
219+ buildCacheJson ,
220+ `${ EnvironmentVariableNames . RUSH_BUILD_CACHE_OVERRIDE_JSON } environment variable`
221+ ) ;
222+ } else {
223+ const buildCacheOverrideJsonFilePath : string | undefined =
224+ EnvironmentConfiguration . buildCacheOverrideJsonFilePath ;
225+ if ( buildCacheOverrideJsonFilePath ) {
226+ buildCacheJson = await JsonFile . loadAndValidateAsync (
227+ buildCacheOverrideJsonFilePath ,
228+ BUILD_CACHE_JSON_SCHEMA
229+ ) ;
230+ } else {
231+ try {
232+ buildCacheJson = await JsonFile . loadAndValidateAsync ( jsonFilePath , BUILD_CACHE_JSON_SCHEMA ) ;
233+ } catch ( e ) {
234+ if ( ! FileSystem . isNotExistError ( e ) ) {
235+ throw e ;
236+ } else {
237+ return undefined ;
238+ }
239+ }
240+ }
241+ }
209242
243+ const rushUserConfiguration : RushUserConfiguration = await RushUserConfiguration . initializeAsync ( ) ;
210244 let innerGetCacheEntryId : GetCacheEntryIdFunction ;
211245 try {
212246 innerGetCacheEntryId = CacheEntryId . parsePattern ( buildCacheJson . cacheEntryNamePattern ) ;
@@ -218,7 +252,9 @@ export class BuildCacheConfiguration {
218252 }
219253
220254 const { cacheHashSalt = '' , cacheProvider } = buildCacheJson ;
221- const salt : string = `${ RushConstants . buildCacheVersion } ${ cacheHashSalt ? `${ RushConstants . hashDelimiter } ${ cacheHashSalt } ` : '' } ` ;
255+ const salt : string = `${ RushConstants . buildCacheVersion } ${
256+ cacheHashSalt ? `${ RushConstants . hashDelimiter } ${ cacheHashSalt } ` : ''
257+ } `;
222258 // Extend the cache entry id with to salt the hash
223259 // This facilitates forcing cache invalidation either when the build cache version changes (new version of Rush)
224260 // or when the user-side salt changes (need to purge bad cache entries, plugins including additional files)
0 commit comments