Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@microsoft/rush",
"comment": "Add a \"dependsOnEnvVars\" configuration option to operations in rush-project.json. The variables specified in this option are included in the cache key hash calculation.",
"type": "none"
}
],
"packageName": "@microsoft/rush"
}
25 changes: 22 additions & 3 deletions libraries/rush-lib/src/api/RushProjectConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ export interface IOperationSettings {
* the build scripts to be compatible with caching.
*/
disableBuildCacheForOperation?: boolean;

/**
* An optional list of environment variables that can affect this operation. The values of
* these environment variables will become part of the hash when reading and writing the build cache.
*
* Note: generally speaking, all environment variables available to Rush are also available to any
* operations performed -- Rush assumes that environment variables do not affect build outputs unless
* you list them here.
*/
dependsOnEnvVars?: string[];
}

interface IOldRushProjectJson {
Expand All @@ -89,7 +99,7 @@ const RUSH_PROJECT_CONFIGURATION_FILE: ConfigurationFile<IRushProjectJson> =
} else if (!parent) {
return child;
} else {
// Merge the outputFolderNames arrays
// Merge any properties that need to be merged
const resultOperationSettingsByOperationName: Map<string, IOperationSettings> = new Map();
for (const parentOperationSettings of parent) {
resultOperationSettingsByOperationName.set(
Expand Down Expand Up @@ -117,7 +127,7 @@ const RUSH_PROJECT_CONFIGURATION_FILE: ConfigurationFile<IRushProjectJson> =
let mergedOperationSettings: IOperationSettings | undefined =
resultOperationSettingsByOperationName.get(operationName);
if (mergedOperationSettings) {
// The parent operation settings object already exists, so append to the outputFolderNames
// The parent operation settings object already exists
const outputFolderNames: string[] | undefined =
mergedOperationSettings.outputFolderNames && childOperationSettings.outputFolderNames
? [
Expand All @@ -126,10 +136,19 @@ const RUSH_PROJECT_CONFIGURATION_FILE: ConfigurationFile<IRushProjectJson> =
]
: mergedOperationSettings.outputFolderNames || childOperationSettings.outputFolderNames;

const dependsOnEnvVars: string[] | undefined =
mergedOperationSettings.dependsOnEnvVars && childOperationSettings.dependsOnEnvVars
? [
...mergedOperationSettings.dependsOnEnvVars,
...childOperationSettings.dependsOnEnvVars
]
: mergedOperationSettings.dependsOnEnvVars || childOperationSettings.dependsOnEnvVars;

mergedOperationSettings = {
...mergedOperationSettings,
...childOperationSettings,
outputFolderNames
...(outputFolderNames ? { outputFolderNames } : {}),
...(dependsOnEnvVars ? { dependsOnEnvVars } : {})
};
resultOperationSettingsByOperationName.set(operationName, mergedOperationSettings);
} else {
Expand Down
13 changes: 13 additions & 0 deletions libraries/rush-lib/src/logic/buildCache/ProjectBuildCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface IProjectBuildCacheOptions {
projectConfiguration: RushProjectConfiguration;
projectOutputFolderNames: ReadonlyArray<string>;
additionalProjectOutputFilePaths?: ReadonlyArray<string>;
additionalContext?: Record<string, string>;
command: string;
trackedProjectFiles: string[] | undefined;
projectChangeAnalyzer: ProjectChangeAnalyzer;
Expand Down Expand Up @@ -447,6 +448,18 @@ export class ProjectBuildCache {
hash.update(RushConstants.hashDelimiter);
hash.update(options.command);
hash.update(RushConstants.hashDelimiter);
if (options.additionalContext) {
for (const key of Object.keys(options.additionalContext).sort()) {
// Add additional context keys and values.
//
// This choice (to modiy 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(RushConstants.hashDelimiter);
}
}
for (const projectHash of sortedProjectStates) {
hash.update(projectHash);
hash.update(RushConstants.hashDelimiter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -444,10 +444,17 @@ export class ShellOperationRunner implements IOperationRunner {
const additionalProjectOutputFilePaths: ReadonlyArray<string> = [
OperationStateFile.getFilenameRelativeToProjectRoot(this._phase)
];
const additionalContext: Record<string, string> = {};
if (operationSettings.dependsOnEnvVars) {
for (const varName of operationSettings.dependsOnEnvVars) {
additionalContext['$' + varName] = process.env[varName] || '';
Comment thread
iclanton marked this conversation as resolved.
}
}
this._projectBuildCache = await ProjectBuildCache.tryGetProjectBuildCache({
projectConfiguration,
projectOutputFolderNames,
additionalProjectOutputFilePaths,
additionalContext,
buildCacheConfiguration: this._buildCacheConfiguration,
terminal,
command: this._commandToRun,
Expand Down
9 changes: 9 additions & 0 deletions libraries/rush-lib/src/schemas/rush-project.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@
"uniqueItems": true
},

"dependsOnEnvVars": {
"type": "array",
"description": "Specify a list of environment variables that affect the output of this operation. If provided, the values of these variables will become part of the hash when reading and writing from cache.",
"items": {
"type": "string"
},
"uniqueItems": true
},

"disableBuildCacheForOperation": {
"description": "Disable caching for this operation. The operation will never be restored from cache. This may be useful if this operation affects state outside of its folder.",
"type": "boolean"
Expand Down