Skip to content

Commit

Permalink
Merge pull request #4548 from iclanton/per-project-cache-id
Browse files Browse the repository at this point in the history
[rush] Minor cleanup to the build cache code.
  • Loading branch information
iclanton authored Feb 28, 2024
2 parents 65d41b7 + 0d201ce commit f7fd624
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@microsoft/rush",
"comment": "",
"type": "none"
}
],
"packageName": "@microsoft/rush"
}
11 changes: 11 additions & 0 deletions libraries/rush-lib/src/api/BuildCacheConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ import schemaJson from '../schemas/build-cache.schema.json';
export interface IBaseBuildCacheJson {
buildCacheEnabled: boolean;
cacheProvider: string;
/**
* Used to specify the cache entry ID format. If this property is set, it must
* contain a `[hash]` token. It may also contain one of the following tokens:
* - `[projectName]`
* - `[projectName:normalize]`
* - `[phaseName]`
* - `[phaseName:normalize]`
* - `[phaseName:trimPrefix]`
* - `[os]`
* - `[arch]`
*/
cacheEntryNamePattern?: string;
}

Expand Down
53 changes: 35 additions & 18 deletions libraries/rush-lib/src/logic/buildCache/ProjectBuildCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,22 @@ export class ProjectBuildCache {
private _cacheId: string | undefined;

private constructor(cacheId: string | undefined, options: IProjectBuildCacheOptions) {
const { buildCacheConfiguration, project, projectOutputFolderNames, additionalProjectOutputFilePaths } =
options;
const {
buildCacheConfiguration: {
localCacheProvider,
cloudCacheProvider,
buildCacheEnabled,
cacheWriteEnabled
},
project,
projectOutputFolderNames,
additionalProjectOutputFilePaths
} = options;
this._project = project;
this._localBuildCacheProvider = buildCacheConfiguration.localCacheProvider;
this._cloudBuildCacheProvider = buildCacheConfiguration.cloudCacheProvider;
this._buildCacheEnabled = buildCacheConfiguration.buildCacheEnabled;
this._cacheWriteEnabled = buildCacheConfiguration.cacheWriteEnabled;
this._localBuildCacheProvider = localCacheProvider;
this._cloudBuildCacheProvider = cloudCacheProvider;
this._buildCacheEnabled = buildCacheEnabled;
this._cacheWriteEnabled = cacheWriteEnabled;
this._projectOutputFolderNames = projectOutputFolderNames || [];
this._additionalProjectOutputFilePaths = additionalProjectOutputFilePaths || [];
this._cacheId = cacheId;
Expand Down Expand Up @@ -366,7 +375,16 @@ export class ProjectBuildCache {
return path.join(this._project.projectRushTempFolder, `${this._cacheId}.${mode}.log`);
}

private static async _getCacheId(options: IProjectBuildCacheOptions): Promise<string | undefined> {
private static async _getCacheId({
projectChangeAnalyzer,
project,
terminal,
projectOutputFolderNames,
configHash,
additionalContext,
phaseName,
buildCacheConfiguration: { getCacheEntryId }
}: IProjectBuildCacheOptions): Promise<string | undefined> {
// The project state hash is calculated in the following method:
// - The current project's hash (see ProjectChangeAnalyzer.getProjectStateHash) is
// calculated and appended to an array
Expand All @@ -379,15 +397,14 @@ export class ProjectBuildCache {
// 3. Each dependency project hash (from the array constructed in previous steps),
// in sorted alphanumerical-sorted order
// - A hex digest of the hash is returned
const projectChangeAnalyzer: ProjectChangeAnalyzer = options.projectChangeAnalyzer;
const projectStates: string[] = [];
const projectsToProcess: Set<RushConfigurationProject> = new Set();
projectsToProcess.add(options.project);
projectsToProcess.add(project);

for (const projectToProcess of projectsToProcess) {
const projectState: string | undefined = await projectChangeAnalyzer._tryGetProjectStateHashAsync(
projectToProcess,
options.terminal
terminal
);
if (!projectState) {
// If we hit any projects with unknown state, return unknown cache ID
Expand All @@ -405,20 +422,20 @@ export class ProjectBuildCache {
// This value is used to force cache bust when the build cache algorithm changes
hash.update(`${RushConstants.buildCacheVersion}`);
hash.update(RushConstants.hashDelimiter);
const serializedOutputFolders: string = JSON.stringify(options.projectOutputFolderNames);
const serializedOutputFolders: string = JSON.stringify(projectOutputFolderNames);
hash.update(serializedOutputFolders);
hash.update(RushConstants.hashDelimiter);
hash.update(options.configHash);
hash.update(configHash);
hash.update(RushConstants.hashDelimiter);
if (options.additionalContext) {
for (const key of Object.keys(options.additionalContext).sort()) {
if (additionalContext) {
for (const key of Object.keys(additionalContext).sort()) {
// Add additional context keys and values.
//
// This choice (to modify the hash for every key regardless of whether a value is set) implies
// that just _adding_ an env var to the list of dependsOnEnvVars will modify its hash. This
// seems appropriate, because this behavior is consistent whether or not the env var happens
// to have a value.
hash.update(`${key}=${options.additionalContext[key]}`);
hash.update(`${key}=${additionalContext[key]}`);
hash.update(RushConstants.hashDelimiter);
}
}
Expand All @@ -429,10 +446,10 @@ export class ProjectBuildCache {

const projectStateHash: string = hash.digest('hex');

return options.buildCacheConfiguration.getCacheEntryId({
projectName: options.project.packageName,
return getCacheEntryId({
projectName: project.packageName,
projectStateHash,
phaseName: options.phaseName
phaseName
});
}
}
2 changes: 1 addition & 1 deletion libraries/rush-lib/src/schemas/build-cache.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
},
"cacheEntryNamePattern": {
"type": "string",
"description": "Setting this property overrides the cache entry ID. If this property is set, it must contain a [hash] token. It may also contain a [projectName] or a [projectName:normalize] token."
"description": "Setting this property overrides the cache entry ID. If this property is set, it must contain a [hash] token. It may also contain one of the following tokens: [projectName], [projectName:normalize], [phaseName], [phaseName:normalize], [phaseName:trimPrefix], [os], and [arch]."
},
"azureBlobStorageConfiguration": {
"type": "object",
Expand Down

0 comments on commit f7fd624

Please sign in to comment.