2021-11-17 13:31:22 +03:00
import * as cache from '@actions/cache' ;
import * as core from '@actions/core' ;
2026-07-15 22:10:44 +05:30
import { getOSInfo , IS_LINUX } from '../utils.js' ;
import { CACHE_DEPENDENCY_BACKUP_PATH } from './constants.js' ;
2021-11-17 13:31:22 +03:00
export enum State {
STATE_CACHE_PRIMARY_KEY = 'cache-primary-key' ,
CACHE_MATCHED_KEY = 'cache-matched-key' ,
CACHE_PATHS = 'cache-paths'
}
abstract class CacheDistributor {
protected CACHE_KEY_PREFIX = 'setup-python' ;
constructor (
protected packageManager : string ,
protected cacheDependencyPath : string
) {}
protected abstract getCacheGlobalDirectories () : Promise < string [] >;
protected abstract computeKeys () : Promise < {
primaryKey : string ;
restoreKey : string [] | undefined ;
} > ;
2023-01-03 18:13:00 +02:00
protected async handleLoadedCache() { }
2021-11-17 13:31:22 +03:00
2026-06-19 05:17:28 +05:30
/**
* Builds the Linux distro portion of a cache key (e.g. `-26.04-Ubuntu`, `-9-rhel`).
* RHEL is keyed by major version since it ships one ABI-stable artifact per major.
*/
protected async getLinuxInfoKeySegment () : Promise < string > {
if ( ! IS_LINUX ) {
return '' ;
}
const osInfo = await getOSInfo ();
if ( ! osInfo ) {
return '' ;
}
// lsb_release reports RHEL as "RedHatEnterpriseLinux" while /etc/os-release
// reports it as "rhel"; normalize both to "rhel" so the key is consistent.
const normalizedName = osInfo . osName . toLowerCase ();
const isRhel =
normalizedName === 'rhel' || normalizedName . includes ( 'redhat' );
const osName = isRhel ? 'rhel' : osInfo . osName ;
const osVersion = isRhel
? osInfo . osVersion . split ( '.' )[ 0 ]
: osInfo . osVersion ;
return `- ${ osVersion } - ${ osName } ` ;
}
2021-11-17 13:31:22 +03:00
public async restoreCache() {
const { primaryKey , restoreKey } = await this . computeKeys ();
if ( primaryKey . endsWith ( '-' )) {
2023-02-20 13:36:57 +01:00
const file =
this . packageManager === 'pip'
? ` ${ this . cacheDependencyPath
. split ( '\n' )
. join ( ',' ) } or ${ CACHE_DEPENDENCY_BACKUP_PATH } `
: this . cacheDependencyPath . split ( '\n' ). join ( ',' );
2021-11-17 13:31:22 +03:00
throw new Error (
2026-08-20 22:17:16 +05:30
`No file in ${ process . cwd () } matched to [ ${ file } ] for ${ this . packageManager } . Make sure you have checked out the target repository, or consider removing the cache step if there are no dependencies to cache.`
2021-11-17 13:31:22 +03:00
);
}
const cachePath = await this . getCacheGlobalDirectories ();
core . saveState ( State . CACHE_PATHS , cachePath );
2023-03-10 12:15:18 +01:00
let matchedKey : string | undefined ;
try {
matchedKey = await cache . restoreCache ( cachePath , primaryKey , restoreKey );
} catch ( err ) {
const message = ( err as Error ). message ;
core . info ( `[warning] ${ message } ` );
core . setOutput ( 'cache-hit' , false );
return ;
}
core . saveState ( State . STATE_CACHE_PRIMARY_KEY , primaryKey );
2021-11-17 13:31:22 +03:00
2023-01-03 18:13:00 +02:00
await this . handleLoadedCache ();
2022-04-05 06:57:13 -07:00
this . handleMatchResult ( matchedKey , primaryKey );
}
public handleMatchResult ( matchedKey : string | undefined , primaryKey : string ) {
2021-11-17 13:31:22 +03:00
if ( matchedKey ) {
core . saveState ( State . CACHE_MATCHED_KEY , matchedKey );
core . info ( `Cache restored from key: ${ matchedKey } ` );
} else {
core . info ( ` ${ this . packageManager } cache is not found` );
}
2022-04-05 06:57:13 -07:00
core . setOutput ( 'cache-hit' , matchedKey === primaryKey );
2021-11-17 13:31:22 +03:00
}
}
export default CacheDistributor ;