@@ -8,7 +8,11 @@ import {
88 getWorkflowRunAttempt ,
99 getWorkflowRunID ,
1010} from "../actions-util" ;
11- import { getAutomationID , listActionsCaches } from "../api-client" ;
11+ import {
12+ type ActionsCacheItem ,
13+ getAutomationID ,
14+ listActionsCaches ,
15+ } from "../api-client" ;
1216import { createCacheKeyHash } from "../caching-utils" ;
1317import { type CodeQL } from "../codeql" ;
1418import { type Config } from "../config-utils" ;
@@ -48,6 +52,12 @@ const OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES =
4852const CACHE_VERSION = 1 ;
4953const CACHE_PREFIX = "codeql-overlay-base-database" ;
5054
55+ // The Actions cache evicts entries that have not been accessed in the past 7
56+ // days. We conservatively set a limit of 6 days to avoid using a cached base DB
57+ // that may be evicted before we can download it.
58+ const CACHE_ENTRY_MAX_AGE_DAYS = 6 ;
59+ const CACHE_ENTRY_MAX_AGE_MS = CACHE_ENTRY_MAX_AGE_DAYS * 24 * 60 * 60 * 1000 ;
60+
5161// The purpose of this ten-minute limit is to guard against the possibility
5262// that the cache service is unresponsive, which would otherwise cause the
5363// entire action to hang. Normally we expect cache operations to complete
@@ -435,6 +445,39 @@ async function getCacheKeyPrefixBase(
435445 return `${ CACHE_PREFIX } -${ CACHE_VERSION } -${ componentsHash } -${ languagesComponent } -` ;
436446}
437447
448+ /**
449+ * Lists overlay-base database cache entries with the given key prefix, ignoring entries that are
450+ * old enough that they may be evicted by the Actions cache before we attempt to download them.
451+ */
452+ async function listRecentOverlayBaseDatabaseCaches (
453+ cacheKeyPrefix : string ,
454+ logger : Logger ,
455+ ) : Promise < ActionsCacheItem [ ] > {
456+ const allCaches = await listActionsCaches ( cacheKeyPrefix ) ;
457+
458+ if ( allCaches . length === 0 ) {
459+ logger . info ( "No overlay-base databases found in Actions cache." ) ;
460+ return [ ] ;
461+ }
462+
463+ const cutoffMs = Date . now ( ) - CACHE_ENTRY_MAX_AGE_MS ;
464+ const recentCaches = allCaches . filter ( ( cache ) => {
465+ if ( ! cache . last_accessed_at ) return true ;
466+ const lastAccessedMs = Date . parse ( cache . last_accessed_at ) ;
467+ return Number . isNaN ( lastAccessedMs ) || lastAccessedMs >= cutoffMs ;
468+ } ) ;
469+ const numTooOldDatabases = allCaches . length - recentCaches . length ;
470+ const tooOldSuffix =
471+ numTooOldDatabases > 0
472+ ? ` (ignoring ${ numTooOldDatabases } that may be evicted soon)`
473+ : "" ;
474+ logger . info (
475+ `Found ${ allCaches . length } overlay-base ${ allCaches . length === 1 ? "database" : "databases" } in the Actions cache${ tooOldSuffix } .` ,
476+ ) ;
477+
478+ return recentCaches ;
479+ }
480+
438481/**
439482 * Searches the GitHub Actions cache for overlay-base databases matching the given languages, and
440483 * returns all stable CodeQL versions found across matching cache entries.
@@ -448,7 +491,7 @@ export async function getCodeQlVersionsForOverlayBaseDatabases(
448491) : Promise < string [ ] | undefined > {
449492 const languages = rawLanguages . map ( parseBuiltInLanguage ) ;
450493 if ( languages . includes ( undefined ) ) {
451- logger . warning (
494+ logger . info (
452495 "One or more provided languages are not recognized as built-in languages. " +
453496 "Skipping searching for overlay-base databases in cache." ,
454497 ) ;
@@ -463,22 +506,19 @@ export async function getCodeQlVersionsForOverlayBaseDatabases(
463506 `prefix ${ cacheKeyPrefix } ` ,
464507 ) ;
465508
466- const caches = await listActionsCaches ( cacheKeyPrefix ) ;
509+ const caches = await listRecentOverlayBaseDatabaseCaches (
510+ cacheKeyPrefix ,
511+ logger ,
512+ ) ;
467513
468514 if ( caches . length === 0 ) {
469- logger . info ( "No overlay-base databases found in Actions cache." ) ;
470515 return [ ] ;
471516 }
472517
473- logger . info (
474- `Found ${ caches . length } overlay-base ` +
475- `${ caches . length === 1 ? "database" : "databases" } in the Actions cache.` ,
476- ) ;
477-
478518 // Parse CodeQL versions from cache keys, matching only stable releases.
479519 //
480- // After the prefix, the remaining key format starts with `${codeQlVersion}-`. Nightlies will have
481- // a suffix like `+202604201548` that will break the match.
520+ // After the prefix, the remaining key format starts with `${codeQlVersion}-`. Nightlies have a
521+ // suffix like `+202604201548` that will prevent a match.
482522 //
483523 // Caveat: this relies on the fact that we haven't released any CodeQL bundles with the
484524 // `x.y.z-<pre-release>` semver format which does not interact well with the current overlay base
@@ -506,7 +546,7 @@ export async function getCodeQlVersionsForOverlayBaseDatabases(
506546 const versions = [ ...versionSet ] . sort ( semver . rcompare ) ;
507547
508548 logger . info (
509- `Found overlay databases for the following CodeQL versions in the Actions cache: ${ versions . join ( ", " ) } ` ,
549+ `Found overlay-base databases for the following CodeQL versions in the Actions cache: ${ versions . join ( ", " ) } ` ,
510550 ) ;
511551
512552 return versions ;
0 commit comments