Merge pull request #3569 from github/henrymercer/overlay-no-trap-caching

Disable TRAP caching when overlay is enabled
This commit is contained in:
Henry Mercer
2026-03-19 10:12:30 +00:00
committed by GitHub
19 changed files with 3019 additions and 2859 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
## [UNRELEASED]
No user facing changes.
- Added an experimental change which disables TRAP caching when [improved incremental analysis](https://github.com/github/roadmap/issues/1158) is enabled, since improved incremental analysis supersedes TRAP caching. This will improve performance and reduce Actions cache usage. We expect to roll this change out to everyone in March. [#3569](https://github.com/github/codeql-action/pull/3569)
## 4.33.0 - 16 Mar 2026
+290 -288
View File
File diff suppressed because it is too large Load Diff
+208 -206
View File
File diff suppressed because it is too large Load Diff
+193 -191
View File
File diff suppressed because it is too large Load Diff
+317 -315
View File
File diff suppressed because it is too large Load Diff
+256 -258
View File
File diff suppressed because it is too large Load Diff
+189 -187
View File
File diff suppressed because it is too large Load Diff
+196 -192
View File
File diff suppressed because it is too large Load Diff
+288 -281
View File
File diff suppressed because it is too large Load Diff
+193 -184
View File
File diff suppressed because it is too large Load Diff
+180 -178
View File
File diff suppressed because it is too large Load Diff
+290 -281
View File
File diff suppressed because it is too large Load Diff
+199 -197
View File
File diff suppressed because it is too large Load Diff
+1 -20
View File
@@ -300,19 +300,6 @@ const GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19";
/** The CLI verbosity level to use for extraction in debug mode. */
const EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++";
/*
* Deprecated in favor of ToolsFeature.
*
* Versions of CodeQL that version-flag certain functionality in the Action.
* For convenience, please keep these in descending order. Once a version
* flag is older than the oldest supported version above, it may be removed.
*/
/**
* Versions 2.17.1+ of the CodeQL CLI support the `--cache-cleanup` option.
*/
const CODEQL_VERSION_CACHE_CLEANUP = "2.17.1";
/**
* Set up CodeQL CLI access.
*
@@ -891,19 +878,13 @@ async function getCodeQLForCmd(
config: Config,
cleanupLevel: CleanupLevel,
): Promise<void> {
const cacheCleanupFlag = (await util.codeQlVersionAtLeast(
this,
CODEQL_VERSION_CACHE_CLEANUP,
))
? "--cache-cleanup"
: "--mode";
for (const language of config.languages) {
const databasePath = util.getCodeQLDatabasePath(config, language);
const codeqlArgs = [
"database",
"cleanup",
databasePath,
`${cacheCleanupFlag}=${cleanupLevel}`,
`--cache-cleanup=${cleanupLevel}`,
...getExtraOptionsFromEnv(["database", "cleanup"]),
];
await runCli(cmd, codeqlArgs);
+127 -1
View File
@@ -26,6 +26,7 @@ import * as overlayStatus from "./overlay/status";
import { parseRepositoryNwo } from "./repository";
import {
setupTests,
setupActionsVars,
mockLanguagesInRepo as mockLanguagesInRepo,
createFeatures,
getRecordingLogger,
@@ -64,7 +65,6 @@ function createTestInitConfigInputs(
configInput: undefined,
buildModeInput: undefined,
ramInput: undefined,
trapCachingEnabled: false,
dependencyCachingEnabled: CachingKind.None,
debugMode: false,
debugArtifactName: "",
@@ -144,6 +144,8 @@ test.serial("load empty config", async (t) => {
const logger = getRunnerLogger(true);
const languages = "javascript,python";
setupActionsVars(tempDir, tempDir);
const codeql = createStubCodeQL({
async betterResolveLanguages() {
return {
@@ -185,6 +187,8 @@ test.serial("load code quality config", async (t) => {
const logger = getRunnerLogger(true);
const languages = "actions";
setupActionsVars(tempDir, tempDir);
const codeql = createStubCodeQL({
async betterResolveLanguages() {
return {
@@ -237,6 +241,8 @@ test.serial(
const logger = getRunnerLogger(true);
const languages = "javascript";
setupActionsVars(tempDir, tempDir);
const codeql = createStubCodeQL({
async betterResolveLanguages() {
return {
@@ -475,6 +481,8 @@ test.serial("load non-existent input", async (t) => {
test.serial("load non-empty input", async (t) => {
return await withTmpDir(async (tempDir) => {
setupActionsVars(tempDir, tempDir);
const codeql = createStubCodeQL({
async betterResolveLanguages() {
return {
@@ -2055,3 +2063,121 @@ test.serial("getPrimaryAnalysisConfig - Code Scanning + Code Quality", (t) => {
AnalysisKind.CodeScanning,
);
});
test.serial(
"isTrapCachingEnabled: explicit input true is respected",
async (t) => {
return await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
sinon
.stub(actionsUtil, "getOptionalInput")
.withArgs("trap-caching")
.returns("true");
t.true(
await configUtils.isTrapCachingEnabled(
createFeatures([]),
OverlayDatabaseMode.None,
),
);
});
},
);
test.serial(
"isTrapCachingEnabled: disabled on self-hosted runner by default",
async (t) => {
return await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
sinon
.stub(actionsUtil, "getOptionalInput")
.withArgs("trap-caching")
.returns(undefined);
t.false(
await configUtils.isTrapCachingEnabled(
createFeatures([]),
OverlayDatabaseMode.None,
),
);
});
},
);
test.serial(
"isTrapCachingEnabled: enabled on hosted runner by default",
async (t) => {
return await withTmpDir(async (tmpDir) => {
const hostedToolCache = path.join(tmpDir, "hostedtoolcache");
setupActionsVars(tmpDir, hostedToolCache);
sinon
.stub(actionsUtil, "getOptionalInput")
.withArgs("trap-caching")
.returns(undefined);
t.true(
await configUtils.isTrapCachingEnabled(
createFeatures([]),
OverlayDatabaseMode.None,
),
);
});
},
);
test.serial(
"isTrapCachingEnabled: enabled on hosted runner when overlay enabled but feature flag off",
async (t) => {
return await withTmpDir(async (tmpDir) => {
const hostedToolCache = path.join(tmpDir, "hostedtoolcache");
setupActionsVars(tmpDir, hostedToolCache);
sinon
.stub(actionsUtil, "getOptionalInput")
.withArgs("trap-caching")
.returns(undefined);
t.true(
await configUtils.isTrapCachingEnabled(
createFeatures([]),
OverlayDatabaseMode.Overlay,
),
);
});
},
);
test.serial(
"isTrapCachingEnabled: disabled on hosted runner when overlay enabled and feature flag on",
async (t) => {
return await withTmpDir(async (tmpDir) => {
const hostedToolCache = path.join(tmpDir, "hostedtoolcache");
setupActionsVars(tmpDir, hostedToolCache);
sinon
.stub(actionsUtil, "getOptionalInput")
.withArgs("trap-caching")
.returns(undefined);
t.false(
await configUtils.isTrapCachingEnabled(
createFeatures([Feature.OverlayAnalysisDisableTrapCaching]),
OverlayDatabaseMode.Overlay,
),
);
});
},
);
test.serial(
"isTrapCachingEnabled: enabled on hosted runner when overlay is None even with feature flag on",
async (t) => {
return await withTmpDir(async (tmpDir) => {
const hostedToolCache = path.join(tmpDir, "hostedtoolcache");
setupActionsVars(tmpDir, hostedToolCache);
sinon
.stub(actionsUtil, "getOptionalInput")
.withArgs("trap-caching")
.returns(undefined);
t.true(
await configUtils.isTrapCachingEnabled(
createFeatures([Feature.OverlayAnalysisDisableTrapCaching]),
OverlayDatabaseMode.None,
),
);
});
},
);
+65 -19
View File
@@ -2,10 +2,12 @@ import * as fs from "fs";
import * as path from "path";
import { performance } from "perf_hooks";
import * as core from "@actions/core";
import * as yaml from "js-yaml";
import {
getActionVersion,
getOptionalInput,
isAnalyzingPullRequest,
isDynamicWorkflow,
} from "./actions-util";
@@ -72,6 +74,7 @@ import {
Result,
Success,
Failure,
isHostedRunner,
} from "./util";
/**
@@ -452,7 +455,6 @@ export interface InitConfigInputs {
configInput: string | undefined;
buildModeInput: string | undefined;
ramInput: string | undefined;
trapCachingEnabled: boolean;
dependencyCachingEnabled: string | undefined;
debugMode: boolean;
debugArtifactName: string;
@@ -482,7 +484,6 @@ export async function initActionState(
packsInput,
buildModeInput,
dbLocation,
trapCachingEnabled,
dependencyCachingEnabled,
debugMode,
debugArtifactName,
@@ -540,13 +541,6 @@ export async function initActionState(
};
}
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(
trapCachingEnabled,
codeql,
languages,
logger,
);
// Compute the full Code Scanning configuration that combines the configuration from the
// configuration file / `config` input with other inputs, such as `queries`.
const computedConfig = generateCodeScanningConfig(
@@ -569,8 +563,8 @@ export async function initActionState(
debugMode,
debugArtifactName,
debugDatabaseName,
trapCaches,
trapCacheDownloadTime,
trapCaches: {},
trapCacheDownloadTime: 0,
dependencyCachingEnabled: getCachingKind(dependencyCachingEnabled),
dependencyCachingRestoredKeys: [],
extraQueryExclusions: [],
@@ -582,7 +576,6 @@ export async function initActionState(
}
async function downloadCacheWithTime(
trapCachingEnabled: boolean,
codeQL: CodeQL,
languages: Language[],
logger: Logger,
@@ -590,13 +583,9 @@ async function downloadCacheWithTime(
trapCaches: { [language: string]: string };
trapCacheDownloadTime: number;
}> {
let trapCaches: { [language: string]: string } = {};
let trapCacheDownloadTime = 0;
if (trapCachingEnabled) {
const start = performance.now();
trapCaches = await downloadTrapCaches(codeQL, languages, logger);
trapCacheDownloadTime = performance.now() - start;
}
const start = performance.now();
const trapCaches = await downloadTrapCaches(codeQL, languages, logger);
const trapCacheDownloadTime = performance.now() - start;
return { trapCaches, trapCacheDownloadTime };
}
@@ -1009,6 +998,50 @@ async function validateOverlayDatabaseMode(
});
}
export async function isTrapCachingEnabled(
features: FeatureEnablement,
overlayDatabaseMode: OverlayDatabaseMode,
): Promise<boolean> {
// If the workflow specified something, always respect that.
const trapCaching = getOptionalInput("trap-caching");
if (trapCaching !== undefined) return trapCaching === "true";
// On self-hosted runners which may have slow network access, disable TRAP caching by default.
if (!isHostedRunner()) return false;
// If overlay analysis is enabled, then disable TRAP caching since overlay analysis supersedes it.
// This change is gated behind a feature flag.
if (
overlayDatabaseMode !== OverlayDatabaseMode.None &&
(await features.getValue(Feature.OverlayAnalysisDisableTrapCaching))
) {
return false;
}
// Otherwise, enable TRAP caching.
return true;
}
async function setCppTrapCachingEnvironmentVariables(
config: Config,
logger: Logger,
): Promise<void> {
if (config.languages.includes(KnownLanguage.cpp)) {
const envVar = "CODEQL_EXTRACTOR_CPP_TRAP_CACHING";
if (process.env[envVar]) {
logger.info(
`Environment variable ${envVar} already set, leaving it unchanged.`,
);
} else if (config.trapCaches[KnownLanguage.cpp]) {
logger.info("Enabling TRAP caching for C/C++.");
core.exportVariable(envVar, "true");
} else {
logger.debug(`Disabling TRAP caching for C/C++.`);
core.exportVariable(envVar, "false");
}
}
}
function dbLocationOrDefault(
dbLocation: string | undefined,
tempDir: string,
@@ -1199,6 +1232,19 @@ export async function initConfig(
exclude: { tags: "exclude-from-incremental" },
});
}
if (await isTrapCachingEnabled(features, config.overlayDatabaseMode)) {
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(
inputs.codeql,
config.languages,
logger,
);
config.trapCaches = trapCaches;
config.trapCacheDownloadTime = trapCacheDownloadTime;
}
await setCppTrapCachingEnvironmentVariables(config, logger);
return config;
}
+25 -17
View File
@@ -64,11 +64,9 @@ export enum Feature {
OverlayAnalysisCodeScanningPython = "overlay_analysis_code_scanning_python",
OverlayAnalysisCodeScanningRuby = "overlay_analysis_code_scanning_ruby",
OverlayAnalysisCsharp = "overlay_analysis_csharp",
/** Disable TRAP caching when overlay analysis is enabled. */
OverlayAnalysisDisableTrapCaching = "overlay_analysis_disable_trap_caching",
OverlayAnalysisGo = "overlay_analysis_go",
/** Controls whether the Actions cache is checked for overlay build outcomes. */
OverlayAnalysisStatusCheck = "overlay_analysis_status_check",
/** Controls whether overlay build failures on are stored in the Actions cache. */
OverlayAnalysisStatusSave = "overlay_analysis_status_save",
OverlayAnalysisJava = "overlay_analysis_java",
OverlayAnalysisJavascript = "overlay_analysis_javascript",
OverlayAnalysisPython = "overlay_analysis_python",
@@ -80,6 +78,10 @@ export enum Feature {
OverlayAnalysisRuby = "overlay_analysis_ruby",
/** Controls whether hardware checks are skipped for overlay analysis. */
OverlayAnalysisSkipResourceChecks = "overlay_analysis_skip_resource_checks",
/** Controls whether the Actions cache is checked for overlay build outcomes. */
OverlayAnalysisStatusCheck = "overlay_analysis_status_check",
/** Controls whether overlay build failures on the default branch are stored in the Actions cache. */
OverlayAnalysisStatusSave = "overlay_analysis_status_save",
PythonDefaultIsToNotExtractStdlib = "python_default_is_to_not_extract_stdlib",
QaTelemetryEnabled = "qa_telemetry_enabled",
/** Note that this currently only disables baseline file coverage information. */
@@ -237,16 +239,6 @@ export const featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_GO",
minimumVersion: CODEQL_OVERLAY_MINIMUM_VERSION_GO,
},
[Feature.OverlayAnalysisStatusCheck]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisStatusSave]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_SAVE",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisJava]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_JAVA",
@@ -262,15 +254,31 @@ export const featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_PYTHON",
minimumVersion: CODEQL_OVERLAY_MINIMUM_VERSION_PYTHON,
},
[Feature.OverlayAnalysisRuby]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUBY",
minimumVersion: CODEQL_OVERLAY_MINIMUM_VERSION_RUBY,
},
// Other overlay-related feature flags
[Feature.OverlayAnalysisDisableTrapCaching]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_DISABLE_TRAP_CACHING",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisResourceChecksV2]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisRuby]: {
[Feature.OverlayAnalysisStatusCheck]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUBY",
minimumVersion: CODEQL_OVERLAY_MINIMUM_VERSION_RUBY,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisStatusSave]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_SAVE",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisSkipResourceChecks]: {
defaultValue: false,
-43
View File
@@ -88,7 +88,6 @@ import {
getRequiredEnvParam,
getThreadsFlagValue,
initializeEnvironment,
isHostedRunner,
ConfigurationError,
wrapError,
checkActionVersion,
@@ -362,7 +361,6 @@ async function run(startedAt: Date) {
configFile,
dbLocation: getOptionalInput("db-location"),
configInput: getOptionalInput("config"),
trapCachingEnabled: getTrapCachingEnabled(),
dependencyCachingEnabled: getDependencyCachingEnabled(),
// Debug mode is enabled if:
// - The `init` Action is passed `debug: true`.
@@ -613,24 +611,6 @@ async function run(startedAt: Date) {
core.exportVariable(kotlinLimitVar, "2.1.20");
}
if (config.languages.includes(KnownLanguage.cpp)) {
const envVar = "CODEQL_EXTRACTOR_CPP_TRAP_CACHING";
if (process.env[envVar]) {
logger.info(
`Environment variable ${envVar} already set. Not en/disabling CodeQL C++ TRAP caching support`,
);
} else if (
getTrapCachingEnabled() &&
(await codeQlVersionAtLeast(codeql, "2.17.5"))
) {
logger.info("Enabling CodeQL C++ TRAP caching support");
core.exportVariable(envVar, "true");
} else {
logger.info("Disabling CodeQL C++ TRAP caching support");
core.exportVariable(envVar, "false");
}
}
// Restore dependency cache(s), if they exist.
if (shouldRestoreCache(config.dependencyCachingEnabled)) {
const dependencyCachingResult = await downloadDependencyCaches(
@@ -644,17 +624,6 @@ async function run(startedAt: Date) {
dependencyCachingResult.restoredKeys;
}
// Suppress warnings about disabled Python library extraction.
if (await codeQlVersionAtLeast(codeql, "2.17.1")) {
// disabled by default, no warning
} else {
// disabled by default, prints warning if environment variable is not set
core.exportVariable(
"CODEQL_EXTRACTOR_PYTHON_DISABLE_LIBRARY_EXTRACTION",
"true",
);
}
if (getOptionalInput("setup-python-dependencies") !== undefined) {
logger.warning(
"The setup-python-dependencies input is deprecated and no longer has any effect. We recommend removing any references from your workflows. See https://github.blog/changelog/2024-01-23-codeql-2-16-python-dependency-installation-disabled-new-queries-and-bug-fixes/ for more information.",
@@ -864,18 +833,6 @@ async function loadRepositoryProperties(
}
}
function getTrapCachingEnabled(): boolean {
// If the workflow specified something always respect that
const trapCaching = getOptionalInput("trap-caching");
if (trapCaching !== undefined) return trapCaching === "true";
// On self-hosted runners which may have slow network access, disable TRAP caching by default
if (!isHostedRunner()) return false;
// On hosted runners, enable TRAP caching by default
return true;
}
async function recordZstdAvailability(
config: configUtils.Config,
zstdAvailability: ZstdAvailability,
+1
View File
@@ -156,6 +156,7 @@ export const DEFAULT_ACTIONS_VARS = {
GITHUB_SERVER_URL: "https://github.com",
GITHUB_SHA: "0".repeat(40),
GITHUB_WORKFLOW: "test-workflow",
RUNNER_NAME: "my-runner",
RUNNER_OS: "Linux",
} as const satisfies Record<string, string>;