mirror of
https://github.com/github/codeql-action.git
synced 2026-10-21 02:01:27 +00:00
Remove TRAP cache cleanup
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
103
lib/entry-points.js
generated
103
lib/entry-points.js
generated
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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<TrapCacheCleanupStatusReport> {
|
||||
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<Array<Required<apiClient.ActionsCacheItem>>> {
|
||||
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<Required<apiClient.ActionsCacheItem>>;
|
||||
}
|
||||
|
||||
export async function getLanguagesSupportingCaching(
|
||||
codeql: CodeQL,
|
||||
languages: Language[],
|
||||
|
||||
Reference in New Issue
Block a user