@@ -6,11 +6,11 @@ import * as glob from "@actions/glob";
66
77import { getTemporaryDirectory } from "./actions-util" ;
88import { listActionsCaches } from "./api-client" ;
9- import { getTotalCacheSize } from "./caching-utils" ;
9+ import { createCacheKeyHash , getTotalCacheSize } from "./caching-utils" ;
1010import { CodeQL } from "./codeql" ;
1111import { Config } from "./config-utils" ;
1212import { EnvVar } from "./environment" ;
13- import { Feature , Features } from "./feature-flags" ;
13+ import { Feature , FeatureEnablement , Features } from "./feature-flags" ;
1414import { KnownLanguage , Language } from "./languages" ;
1515import { Logger } from "./logging" ;
1616import { getErrorMessage , getRequiredEnvParam } from "./util" ;
@@ -442,6 +442,56 @@ async function cacheKey(
442442 return `${ await cachePrefix ( codeql , features , language ) } ${ hash } ` ;
443443}
444444
445+ /**
446+ * If experimental features which the cache contents depend on are enabled for the current language,
447+ * this function returns a prefix that uniquely identifies the set of enabled features. The purpose of
448+ * this is to avoid restoring caches whose contents depended on experimental features, if those
449+ * experimental features are later disabled.
450+ *
451+ * @param codeql The CodeQL instance.
452+ * @param features Information about enabled features.
453+ * @param language The language we are creating the key for.
454+ *
455+ * @returns A cache key prefix identifying the enabled, experimental features that the cache depends on.
456+ */
457+ export async function getFeaturePrefix (
458+ codeql : CodeQL ,
459+ features : FeatureEnablement ,
460+ language : Language ,
461+ ) : Promise < string > {
462+ const enabledFeatures : Feature [ ] = [ ] ;
463+
464+ const addFeatureIfEnabled = async ( feature : Feature ) => {
465+ if ( await features . getValue ( feature , codeql ) ) {
466+ enabledFeatures . push ( feature ) ;
467+ }
468+ } ;
469+
470+ if ( language === KnownLanguage . java ) {
471+ // To ensure a safe rollout of JAR minimization, we change the key when the feature is enabled.
472+ const minimizeJavaJars = await features . getValue (
473+ Feature . JavaMinimizeDependencyJars ,
474+ codeql ,
475+ ) ;
476+
477+ // To maintain backwards compatibility with this, we return "minify-" instead of a hash.
478+ if ( minimizeJavaJars ) {
479+ return "minify-" ;
480+ }
481+ } else if ( language === KnownLanguage . csharp ) {
482+ await addFeatureIfEnabled ( Feature . CsharpNewCacheKey ) ;
483+ }
484+
485+ // If any features that affect the cache are enabled, return a feature prefix by
486+ // computing a hash of the feature array.
487+ if ( enabledFeatures . length > 0 ) {
488+ return `${ createCacheKeyHash ( enabledFeatures ) } -` ;
489+ }
490+
491+ // No feature prefix.
492+ return "" ;
493+ }
494+
445495/**
446496 * Constructs a prefix for the cache key, comprised of a CodeQL-specific prefix, a version number that
447497 * can be changed to invalidate old caches, the runner's operating system, and the specified language name.
@@ -464,16 +514,12 @@ async function cachePrefix(
464514 prefix = `${ prefix } -${ customPrefix } ` ;
465515 }
466516
467- // To ensure a safe rollout of JAR minimization, we change the key when the feature is enabled.
468- const minimizeJavaJars = await features . getValue (
469- Feature . JavaMinimizeDependencyJars ,
470- codeql ,
471- ) ;
472- if ( language === KnownLanguage . java && minimizeJavaJars ) {
473- prefix = `minify-${ prefix } ` ;
474- }
517+ // Calculate the feature prefix for the cache, if any. This is a hash that identifies
518+ // experimental features that affect the cache contents.
519+ const featurePrefix = await getFeaturePrefix ( codeql , features , language ) ;
475520
476- return `${ prefix } -${ CODEQL_DEPENDENCY_CACHE_VERSION } -${ runnerOs } -${ language } -` ;
521+ // Assemble the cache key.
522+ return `${ featurePrefix } ${ prefix } -${ CODEQL_DEPENDENCY_CACHE_VERSION } -${ runnerOs } -${ language } -` ;
477523}
478524
479525/** Represents information about our overall cache usage for CodeQL dependency caches. */
0 commit comments