From 1a7b87e3d1ff559edb5823aad696a7b281d15f07 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 15 Oct 2026 21:45:10 +0100 Subject: [PATCH 1/9] Remove TRAP cache cleanup Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 103 +--------------------------------- src/analyze-action.ts | 21 +------ src/api-client.ts | 15 ----- src/doc-url.ts | 1 - src/feature-flags.ts | 6 -- src/trap-caching.test.ts | 86 ---------------------------- src/trap-caching.ts | 118 +-------------------------------------- 7 files changed, 3 insertions(+), 347 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 1a99a4442..fb4ca4736 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -170867,14 +170867,6 @@ async function listActionsCaches(keyPrefix, ref) { } ); } -async function deleteActionsCache(id) { - const repositoryNwo = getRepositoryNwo(); - await getApiClient().rest.actions.deleteActionsCacheById({ - owner: repositoryNwo.owner, - repo: repositoryNwo.repo, - cache_id: id - }); -} async function getRepositoryProperties(repositoryNwo) { return getApiClient().request("GET /repos/:owner/:repo/properties/values", { owner: repositoryNwo.owner, @@ -171932,11 +171924,6 @@ var featureConfig = { envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS", minimumVersion: void 0 }, - ["cleanup_trap_caches" /* CleanupTrapCaches */]: { - defaultValue: false, - envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", - minimumVersion: void 0 - }, ["config_file_repository_property" /* ConfigFileRepositoryProperty */]: { defaultValue: false, envVar: "CODEQL_ACTION_CONFIG_FILE_REPOSITORY_PROPERTY", @@ -174250,83 +174237,6 @@ async function uploadTrapCaches(codeql, config, logger2) { } return true; } -async function cleanupTrapCaches(config, features, logger2) { - const env = getEnv(); - if (!await features.getValue("cleanup_trap_caches" /* CleanupTrapCaches */)) { - return { - trap_cache_cleanup_skipped_because: "feature disabled" - }; - } - logger2.warning( - "TRAP cache cleanup is deprecated and will be removed in May 2026. We recommend instead disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action." - ); - if (!await isAnalyzingDefaultBranch(env, config.repositoryRoot)) { - return { - trap_cache_cleanup_skipped_because: "not analyzing default branch" - }; - } - try { - let totalBytesCleanedUp = 0; - const allCaches = await listActionsCaches( - CODEQL_TRAP_CACHE_PREFIX, - await getRef(env, config.repositoryRoot) - ); - for (const language of config.languages) { - if (config.trapCaches[language]) { - const cachesToRemove = await getTrapCachesForLanguage( - allCaches, - language, - logger2 - ); - cachesToRemove.sort((a, b) => a.created_at.localeCompare(b.created_at)); - const mostRecentCache = cachesToRemove.pop(); - logger2.debug( - `Keeping most recent TRAP cache (${JSON.stringify(mostRecentCache)})` - ); - if (cachesToRemove.length === 0) { - logger2.info(`No TRAP caches to clean up for ${language}.`); - continue; - } - for (const cache of cachesToRemove) { - logger2.debug(`Cleaning up TRAP cache (${JSON.stringify(cache)})`); - await deleteActionsCache(cache.id); - } - const bytesCleanedUp = cachesToRemove.reduce( - (acc, item) => acc + item.size_in_bytes, - 0 - ); - totalBytesCleanedUp += bytesCleanedUp; - const megabytesCleanedUp = (bytesCleanedUp / (1024 * 1024)).toFixed(2); - logger2.info( - `Cleaned up ${megabytesCleanedUp} MiB of old TRAP caches for ${language}.` - ); - } - } - return { trap_cache_cleanup_size_bytes: totalBytesCleanedUp }; - } catch (e) { - if (asHTTPError(e)?.status === 403) { - logger2.warning( - `Could not cleanup TRAP caches as the token did not have the required permissions. To clean up TRAP caches, ensure the token has the "actions:write" permission. See ${"https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs" /* ASSIGNING_PERMISSIONS_TO_JOBS */} for more information.` - ); - } else { - logger2.info(`Failed to cleanup TRAP caches, continuing. Details: ${e}`); - } - return { trap_cache_cleanup_error: getErrorMessage(e) }; - } -} -async function getTrapCachesForLanguage(allCaches, language, logger2) { - logger2.debug(`Listing TRAP caches for ${language}`); - for (const cache of allCaches) { - if (!cache.created_at || !cache.id || !cache.key || !cache.size_in_bytes) { - throw new Error( - `An unexpected cache item was returned from the API that was missing one or more required fields: ${JSON.stringify(cache)}` - ); - } - } - return allCaches.filter((cache) => { - return cache.key?.includes(`-${language}-`); - }); -} async function getLanguagesSupportingCaching(codeql, languages, logger2) { const result = []; const resolveResult = await codeql.resolveLanguages(); @@ -180651,7 +180561,7 @@ async function postProcessAndUploadSarif(logger2, features, uploadKind, checkout } // src/analyze-action.ts -async function sendStatusReport2(startedAt, config, stats, error3, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, trapCacheCleanup, dependencyCacheResults, databaseUploadResults, logger2) { +async function sendStatusReport2(startedAt, config, stats, error3, trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, dependencyCacheResults, databaseUploadResults, logger2) { const status = getActionsStatus(error3, stats?.analyze_failure_language); const statusReportBase = await createStatusReportBase( "finish" /* Analyze */, @@ -180668,7 +180578,6 @@ async function sendStatusReport2(startedAt, config, stats, error3, trapCacheUplo ...statusReportBase, ...stats || {}, ...dbCreationTimings || {}, - ...trapCacheCleanup || {}, dependency_caching_upload_results: dependencyCacheResults, database_upload_results: databaseUploadResults }; @@ -180752,7 +180661,6 @@ async function run(action) { let uploadResults = void 0; let runStats = void 0; let config = void 0; - let trapCacheCleanupTelemetry = void 0; let trapCacheUploadTime = void 0; let dbCreationTimings = void 0; let didUploadTrapCaches = false; @@ -180896,11 +180804,6 @@ async function run(action) { const trapCacheUploadStartTime = import_perf_hooks6.performance.now(); didUploadTrapCaches = await uploadTrapCaches(codeql, config, logger2); trapCacheUploadTime = import_perf_hooks6.performance.now() - trapCacheUploadStartTime; - trapCacheCleanupTelemetry = await cleanupTrapCaches( - config, - features, - logger2 - ); if (shouldStoreCache(config.dependencyCachingEnabled)) { dependencyCacheResults = await uploadDependencyCaches( codeql, @@ -180937,7 +180840,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 @@ -180956,7 +180858,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 @@ -180970,7 +180871,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 @@ -180984,7 +180884,6 @@ async function run(action) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger2 diff --git a/src/analyze-action.ts b/src/analyze-action.ts index 9efbb529b..5478d818e 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -49,11 +49,7 @@ import { getActionsStatus, StatusReportBase, } from "./status-report"; -import { - cleanupTrapCaches, - TrapCacheCleanupStatusReport, - uploadTrapCaches, -} from "./trap-caching"; +import { uploadTrapCaches } from "./trap-caching"; import * as uploadLib from "./upload-lib"; import { UploadResult } from "./upload-lib"; import { postProcessAndUploadSarif } from "./upload-sarif"; @@ -86,7 +82,6 @@ async function sendStatusReport( trapCacheUploadTime: number | undefined, dbCreationTimings: DatabaseCreationTimings | undefined, didUploadTrapCaches: boolean, - trapCacheCleanup: TrapCacheCleanupStatusReport | undefined, dependencyCacheResults: DependencyCacheUploadStatusReport | undefined, databaseUploadResults: DatabaseUploadResult[], logger: Logger, @@ -107,7 +102,6 @@ async function sendStatusReport( ...statusReportBase, ...(stats || {}), ...(dbCreationTimings || {}), - ...(trapCacheCleanup || {}), dependency_caching_upload_results: dependencyCacheResults, database_upload_results: databaseUploadResults, }; @@ -229,8 +223,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { | undefined = undefined; let runStats: QueriesStatusReport | undefined = undefined; let config: Config | undefined = undefined; - let trapCacheCleanupTelemetry: TrapCacheCleanupStatusReport | undefined = - undefined; let trapCacheUploadTime: number | undefined = undefined; let dbCreationTimings: DatabaseCreationTimings | undefined = undefined; let didUploadTrapCaches = false; @@ -415,13 +407,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { didUploadTrapCaches = await uploadTrapCaches(codeql, config, logger); trapCacheUploadTime = performance.now() - trapCacheUploadStartTime; - // Clean up TRAP caches - trapCacheCleanupTelemetry = await cleanupTrapCaches( - config, - features, - logger, - ); - // Store dependency cache(s) if dependency caching is enabled. if (shouldStoreCache(config.dependencyCachingEnabled)) { dependencyCacheResults = await uploadDependencyCaches( @@ -471,7 +456,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, @@ -494,7 +478,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, @@ -508,7 +491,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, @@ -522,7 +504,6 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { trapCacheUploadTime, dbCreationTimings, didUploadTrapCaches, - trapCacheCleanupTelemetry, dependencyCacheResults, databaseUploadResults, logger, diff --git a/src/api-client.ts b/src/api-client.ts index 7aa4d61d7..8a456c169 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -401,21 +401,6 @@ export async function listActionsCaches( ); } -/** - * Delete an Actions cache item by its ID. - * - * See https://docs.github.com/en/rest/actions/cache#delete-a-github-actions-cache-for-a-repository-using-a-cache-id. - */ -export async function deleteActionsCache(id: number) { - const repositoryNwo = getRepositoryNwo(); - - await getApiClient().rest.actions.deleteActionsCacheById({ - owner: repositoryNwo.owner, - repo: repositoryNwo.repo, - cache_id: id, - }); -} - /** * Retrieve all custom repository properties. * diff --git a/src/doc-url.ts b/src/doc-url.ts index c624817e9..97f5451d8 100644 --- a/src/doc-url.ts +++ b/src/doc-url.ts @@ -3,7 +3,6 @@ */ export enum DocUrl { - ASSIGNING_PERMISSIONS_TO_JOBS = "https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs", AUTOMATIC_BUILD_FAILED = "https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed", CODEQL_BUILD_MODES = "https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#codeql-build-modes", DEFINE_ENV_VARIABLES = "https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow", diff --git a/src/feature-flags.ts b/src/feature-flags.ts index 5cf7c7414..8b8e1027a 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -74,7 +74,6 @@ export enum Feature { AllowMergeConfigFiles = "allow_merge_config_files", /** Controls whether we allow multiple values for the `analysis-kinds` input. */ AllowMultipleAnalysisKinds = "allow_multiple_analysis_kinds", - CleanupTrapCaches = "cleanup_trap_caches", /** Whether to allow the `config-file` input to be specified via a repository property. */ ConfigFileRepositoryProperty = "config_file_repository_property", CppDependencyInstallation = "cpp_dependency_installation_enabled", @@ -216,11 +215,6 @@ export const featureConfig = { envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS", minimumVersion: undefined, }, - [Feature.CleanupTrapCaches]: { - defaultValue: false, - envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", - minimumVersion: undefined, - }, [Feature.ConfigFileRepositoryProperty]: { defaultValue: false, envVar: "CODEQL_ACTION_CONFIG_FILE_REPOSITORY_PROPERTY", diff --git a/src/trap-caching.test.ts b/src/trap-caching.test.ts index 15ab49481..6ec3d5aba 100644 --- a/src/trap-caching.test.ts +++ b/src/trap-caching.test.ts @@ -6,26 +6,21 @@ import test from "ava"; import * as sinon from "sinon"; import * as actionsUtil from "./actions-util"; -import * as apiClient from "./api-client"; import { getTrapCachingExtractorConfigArgs, getTrapCachingExtractorConfigArgsForLang, createStubCodeQL, } from "./codeql"; import * as configUtils from "./config-utils"; -import { Feature } from "./feature-flags"; import * as gitUtils from "./git-utils"; import { BuiltInLanguage } from "./languages"; -import { getRunnerLogger } from "./logging"; import { - createFeatures, createTestConfig, getRecordingLogger, makeVersionInfo, setupTests, } from "./testing-utils"; import { - cleanupTrapCaches, downloadTrapCaches, getLanguagesSupportingCaching, uploadTrapCaches, @@ -199,84 +194,3 @@ test.serial( }); }, ); - -test.serial("cleanup removes only old CodeQL TRAP caches", async (t) => { - await util.withTmpDir(async (tmpDir) => { - // This config specifies that we are analyzing JavaScript and Ruby, but not Swift. - const config = getTestConfigWithTempDir(tmpDir); - - sinon.stub(gitUtils, "getRef").resolves("refs/heads/main"); - sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true); - const listStub = sinon.stub(apiClient, "listActionsCaches").resolves([ - // Should be kept, since it's not relevant to CodeQL. In reality, the API shouldn't return - // this in the first place, but this is a defensive check. - { - id: 1, - key: "some-other-key", - created_at: "2024-05-23T14:25:00Z", - size_in_bytes: 100 * 1024 * 1024, - }, - // Should be kept, since it's the newest TRAP cache for JavaScript - { - id: 2, - key: "codeql-trap-1-2.0.0-javascript-newest", - created_at: "2024-04-23T14:25:00Z", - size_in_bytes: 50 * 1024 * 1024, - }, - // Should be cleaned up - { - id: 3, - key: "codeql-trap-1-2.0.0-javascript-older", - created_at: "2024-03-22T14:25:00Z", - size_in_bytes: 200 * 1024 * 1024, - }, - // Should be cleaned up - { - id: 4, - key: "codeql-trap-1-2.0.0-javascript-oldest", - created_at: "2024-02-21T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - // Should be kept, since it's the newest TRAP cache for Ruby - { - id: 5, - key: "codeql-trap-1-2.0.0-ruby-newest", - created_at: "2024-02-20T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - // Should be kept, since we aren't analyzing Swift - { - id: 6, - key: "codeql-trap-1-2.0.0-swift-newest", - created_at: "2024-02-22T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - // Should be kept, since we aren't analyzing Swift - { - id: 7, - key: "codeql-trap-1-2.0.0-swift-older", - created_at: "2024-02-21T14:25:00Z", - size_in_bytes: 300 * 1024 * 1024, - }, - ]); - - const deleteStub = sinon.stub(apiClient, "deleteActionsCache").resolves(); - - const statusReport = await cleanupTrapCaches( - config, - createFeatures([Feature.CleanupTrapCaches]), - getRunnerLogger(true), - ); - - t.is(listStub.callCount, 1); - t.assert(listStub.calledWithExactly("codeql-trap", "refs/heads/main")); - - t.deepEqual(statusReport, { - trap_cache_cleanup_size_bytes: 500 * 1024 * 1024, - }); - - t.is(deleteStub.callCount, 2); - t.assert(deleteStub.calledWithExactly(3)); - t.assert(deleteStub.calledWithExactly(4)); - }); -}); diff --git a/src/trap-caching.ts b/src/trap-caching.ts index d93936832..fd920600b 100644 --- a/src/trap-caching.ts +++ b/src/trap-caching.ts @@ -4,21 +4,12 @@ import * as path from "path"; import * as actionsCache from "@actions/cache"; import * as actionsUtil from "./actions-util"; -import * as apiClient from "./api-client"; import { type CodeQL } from "./codeql"; import { type Config } from "./config-utils"; -import { DocUrl } from "./doc-url"; -import { Feature, FeatureEnablement } from "./feature-flags"; import * as gitUtils from "./git-utils"; import { Language } from "./languages"; import { Logger } from "./logging"; -import { - asHTTPError, - getEnv, - getErrorMessage, - tryGetFolderBytes, - waitForResultWithTimeLimit, -} from "./util"; +import { getEnv, tryGetFolderBytes, waitForResultWithTimeLimit } from "./util"; // This constant should be bumped if we make a breaking change // to how the CodeQL Action stores or retrieves the TRAP cache, @@ -178,113 +169,6 @@ export async function uploadTrapCaches( return true; } -export interface TrapCacheCleanupStatusReport { - trap_cache_cleanup_error?: string; - trap_cache_cleanup_size_bytes?: number; - trap_cache_cleanup_skipped_because?: string; -} - -export async function cleanupTrapCaches( - config: Config, - features: FeatureEnablement, - logger: Logger, -): Promise { - const env = getEnv(); - - if (!(await features.getValue(Feature.CleanupTrapCaches))) { - return { - trap_cache_cleanup_skipped_because: "feature disabled", - }; - } - logger.warning( - "TRAP cache cleanup is deprecated and will be removed in May 2026. " + - "We recommend instead disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action.", - ); - if (!(await gitUtils.isAnalyzingDefaultBranch(env, config.repositoryRoot))) { - return { - trap_cache_cleanup_skipped_because: "not analyzing default branch", - }; - } - - try { - let totalBytesCleanedUp = 0; - - const allCaches = await apiClient.listActionsCaches( - CODEQL_TRAP_CACHE_PREFIX, - await gitUtils.getRef(env, config.repositoryRoot), - ); - - for (const language of config.languages) { - if (config.trapCaches[language]) { - const cachesToRemove = await getTrapCachesForLanguage( - allCaches, - language, - logger, - ); - // Dates returned by the API are in ISO 8601 format, so we can sort them lexicographically - cachesToRemove.sort((a, b) => a.created_at.localeCompare(b.created_at)); - // Keep the most recent cache - const mostRecentCache = cachesToRemove.pop(); - logger.debug( - `Keeping most recent TRAP cache (${JSON.stringify(mostRecentCache)})`, - ); - - if (cachesToRemove.length === 0) { - logger.info(`No TRAP caches to clean up for ${language}.`); - continue; - } - - for (const cache of cachesToRemove) { - logger.debug(`Cleaning up TRAP cache (${JSON.stringify(cache)})`); - await apiClient.deleteActionsCache(cache.id); - } - const bytesCleanedUp = cachesToRemove.reduce( - (acc, item) => acc + item.size_in_bytes, - 0, - ); - totalBytesCleanedUp += bytesCleanedUp; - const megabytesCleanedUp = (bytesCleanedUp / (1024 * 1024)).toFixed(2); - logger.info( - `Cleaned up ${megabytesCleanedUp} MiB of old TRAP caches for ${language}.`, - ); - } - } - return { trap_cache_cleanup_size_bytes: totalBytesCleanedUp }; - } catch (e) { - if (asHTTPError(e)?.status === 403) { - logger.warning( - "Could not cleanup TRAP caches as the token did not have the required permissions. " + - 'To clean up TRAP caches, ensure the token has the "actions:write" permission. ' + - `See ${DocUrl.ASSIGNING_PERMISSIONS_TO_JOBS} for more information.`, - ); - } else { - logger.info(`Failed to cleanup TRAP caches, continuing. Details: ${e}`); - } - return { trap_cache_cleanup_error: getErrorMessage(e) }; - } -} - -async function getTrapCachesForLanguage( - allCaches: apiClient.ActionsCacheItem[], - language: Language, - logger: Logger, -): Promise>> { - logger.debug(`Listing TRAP caches for ${language}`); - - for (const cache of allCaches) { - if (!cache.created_at || !cache.id || !cache.key || !cache.size_in_bytes) { - throw new Error( - "An unexpected cache item was returned from the API that was missing one or " + - `more required fields: ${JSON.stringify(cache)}`, - ); - } - } - - return allCaches.filter((cache) => { - return cache.key?.includes(`-${language}-`); - }) as Array>; -} - export async function getLanguagesSupportingCaching( codeql: CodeQL, languages: Language[], From 9b5d335b995d625719d424b7041ad3331c3f4cf9 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 15 Oct 2026 21:48:34 +0100 Subject: [PATCH 2/9] Warn when `CODEQL_ACTION_CLEANUP_TRAP_CACHES` is set Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 11 +++++++++++ src/analyze-action.ts | 7 ++++++- src/trap-caching.test.ts | 27 +++++++++++++++++++++++++++ src/trap-caching.ts | 20 ++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index fb4ca4736..180ce0bff 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -174237,6 +174237,16 @@ async function uploadTrapCaches(codeql, config, logger2) { } return true; } +function warnIfTrapCacheCleanupEnvVarIsSet({ + env, + logger: logger2 +}) { + if (env.getOptional("CODEQL_ACTION_CLEANUP_TRAP_CACHES") !== void 0) { + logger2.warning( + "TRAP cache cleanup has been removed, so the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable no longer has any effect and can be removed from your workflow. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching instead by passing the `trap-caching: false` input to the `init` Action." + ); + } +} async function getLanguagesSupportingCaching(codeql, languages, logger2) { const result = []; const resolveResult = await codeql.resolveLanguages(); @@ -180697,6 +180707,7 @@ async function run(action) { "The 'cleanup-level' input is ignored since the CodeQL Action now automatically manages database cleanup. This input can safely be removed from your workflow." ); } + warnIfTrapCacheCleanupEnvVarIsSet(action); const apiDetails = getApiDetails(); const outputDir = getRequiredInput("output"); action.env.export("CODEQL_ACTION_SARIF_RESULTS_OUTPUT_DIR" /* SARIF_RESULTS_OUTPUT_DIR */, outputDir); diff --git a/src/analyze-action.ts b/src/analyze-action.ts index 5478d818e..f273dbbd8 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -49,7 +49,10 @@ import { getActionsStatus, StatusReportBase, } from "./status-report"; -import { uploadTrapCaches } from "./trap-caching"; +import { + uploadTrapCaches, + warnIfTrapCacheCleanupEnvVarIsSet, +} from "./trap-caching"; import * as uploadLib from "./upload-lib"; import { UploadResult } from "./upload-lib"; import { postProcessAndUploadSarif } from "./upload-sarif"; @@ -270,6 +273,8 @@ async function run(action: ActionState<["Base", "Logger", "Env", "Actions"]>) { ); } + warnIfTrapCacheCleanupEnvVarIsSet(action); + const apiDetails = getApiDetails(); const outputDir = actionsUtil.getRequiredInput("output"); action.env.export(EnvVar.SARIF_RESULTS_OUTPUT_DIR, outputDir); diff --git a/src/trap-caching.test.ts b/src/trap-caching.test.ts index 6ec3d5aba..99dc59706 100644 --- a/src/trap-caching.test.ts +++ b/src/trap-caching.test.ts @@ -15,6 +15,7 @@ import * as configUtils from "./config-utils"; import * as gitUtils from "./git-utils"; import { BuiltInLanguage } from "./languages"; import { + callee, createTestConfig, getRecordingLogger, makeVersionInfo, @@ -24,6 +25,7 @@ import { downloadTrapCaches, getLanguagesSupportingCaching, uploadTrapCaches, + warnIfTrapCacheCleanupEnvVarIsSet, } from "./trap-caching"; import * as util from "./util"; @@ -194,3 +196,28 @@ test.serial( }); }, ); + +// `CODEQL_ACTION_CLEANUP_TRAP_CACHES` has no effect with either value, so we warn even when it's +// set to `false`. +for (const value of ["true", "false"]) { + test(`warnIfTrapCacheCleanupEnvVarIsSet warns when CODEQL_ACTION_CLEANUP_TRAP_CACHES is '${value}'`, async (t) => { + const target = callee(warnIfTrapCacheCleanupEnvVarIsSet) + .withEnv((env) => env.set("CODEQL_ACTION_CLEANUP_TRAP_CACHES", value)) + .withArgs() + .logs( + t, + "CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable no longer has any effect", + ); + await target.passes(t.is, undefined); + t.deepEqual( + target.getLogger().messages.map((m) => m.type), + ["warning"], + ); + }); +} + +test("warnIfTrapCacheCleanupEnvVarIsSet doesn't warn when CODEQL_ACTION_CLEANUP_TRAP_CACHES is unset", async (t) => { + const target = callee(warnIfTrapCacheCleanupEnvVarIsSet).withArgs(); + await target.passes(t.is, undefined); + t.deepEqual(target.getLogger().messages, []); +}); diff --git a/src/trap-caching.ts b/src/trap-caching.ts index fd920600b..58d96890f 100644 --- a/src/trap-caching.ts +++ b/src/trap-caching.ts @@ -3,6 +3,7 @@ import * as path from "path"; import * as actionsCache from "@actions/cache"; +import { type ActionState } from "./action-common"; import * as actionsUtil from "./actions-util"; import { type CodeQL } from "./codeql"; import { type Config } from "./config-utils"; @@ -169,6 +170,25 @@ export async function uploadTrapCaches( return true; } +/** + * Warns if the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable is set to a non-empty + * value. That variable controlled the removed TRAP cache cleanup feature, so setting it has no + * effect. + */ +export function warnIfTrapCacheCleanupEnvVarIsSet({ + env, + logger, +}: ActionState<["Logger", "ReadOnlyEnv"]>): void { + if (env.getOptional("CODEQL_ACTION_CLEANUP_TRAP_CACHES") !== undefined) { + logger.warning( + "TRAP cache cleanup has been removed, so the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment " + + "variable no longer has any effect and can be removed from your workflow. If you used TRAP " + + "cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching instead by " + + "passing the `trap-caching: false` input to the `init` Action.", + ); + } +} + export async function getLanguagesSupportingCaching( codeql: CodeQL, languages: Language[], From ba6f82195bbe4ce1dc3726b3b0fff7d82747452c Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 16 Oct 2026 14:02:16 +0100 Subject: [PATCH 3/9] Add change note Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- unreleased-change-notes/remove-trap-cache-cleanup.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 unreleased-change-notes/remove-trap-cache-cleanup.md diff --git a/unreleased-change-notes/remove-trap-cache-cleanup.md b/unreleased-change-notes/remove-trap-cache-cleanup.md new file mode 100644 index 000000000..f63b7bebd --- /dev/null +++ b/unreleased-change-notes/remove-trap-cache-cleanup.md @@ -0,0 +1 @@ +- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243) From 734778abbe5ad6cffe44e04de30b0746864bddfc Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Fri, 16 Oct 2026 16:13:47 +0100 Subject: [PATCH 4/9] Improve changelog note Co-authored-by: Michael B. Gale --- unreleased-change-notes/remove-trap-cache-cleanup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unreleased-change-notes/remove-trap-cache-cleanup.md b/unreleased-change-notes/remove-trap-cache-cleanup.md index f63b7bebd..b3cb822b8 100644 --- a/unreleased-change-notes/remove-trap-cache-cleanup.md +++ b/unreleased-change-notes/remove-trap-cache-cleanup.md @@ -1 +1 @@ -- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243) +- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in the release notes for CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243) From 20f5ec39109073afe1789b098456b2be0164f4ee Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 14:20:41 +0000 Subject: [PATCH 5/9] Update changelog for v4.39.1 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b88dff6aa..ec85da14e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. -## [UNRELEASED] +## 4.39.1 - 21 Oct 2026 - Update default CodeQL bundle version to [2.27.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3). [#4256](https://github.com/github/codeql-action/pull/4256) From b5e1ed9574dcfa81c88c318140f3b3e5c199bfb3 Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Wed, 21 Oct 2026 10:05:32 -0500 Subject: [PATCH 6/9] Trigger workflows From 33f58aa90d0a355774a25beaff09a8c0ec561ba9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 15:48:42 +0000 Subject: [PATCH 7/9] Update changelog and version after v4.39.1 --- CHANGELOG.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec85da14e..8a96e0a9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. +## [UNRELEASED] + +No user facing changes. + ## 4.39.1 - 21 Oct 2026 - Update default CodeQL bundle version to [2.27.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3). [#4256](https://github.com/github/codeql-action/pull/4256) diff --git a/package-lock.json b/package-lock.json index d702b0f6f..cfc9b231f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codeql", - "version": "4.39.1", + "version": "4.39.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codeql", - "version": "4.39.1", + "version": "4.39.2", "license": "MIT", "workspaces": [ "pr-checks" diff --git a/package.json b/package.json index 209ded679..9bfd79222 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codeql", - "version": "4.39.1", + "version": "4.39.2", "private": true, "description": "CodeQL action", "scripts": { From 4cf32242898ad79d69aed5bc5bca8d94f1a902ae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 15:48:52 +0000 Subject: [PATCH 8/9] Rebuild --- lib/entry-points.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 98c7f0488..0b7e6c4e3 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -170161,7 +170161,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) { return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME); } function getActionVersion() { - return "4.39.1"; + return "4.39.2"; } function getWorkflowEventName(env = getEnv()) { return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */); From 0fcd0abe85818a2728c270830d8d51c86241810c Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Wed, 21 Oct 2026 11:10:30 -0500 Subject: [PATCH 9/9] Trigger workflows