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[],