add support for caching

This commit is contained in:
Dmitry Shibanov 2021-10-27 09:52:29 +03:00
parent feeaa3ba49
commit 952fef3565
14 changed files with 124033 additions and 7678 deletions

View file

@ -0,0 +1,47 @@
import * as cache from '@actions/cache';
import * as core from '@actions/core';
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 toolName: string, protected patterns: string) {}
protected abstract getCacheGlobalDirectories(): Promise<string[]>;
protected abstract computeKeys(): Promise<{
primaryKey: string;
restoreKey: string[] | undefined;
}>;
public async restoreCache() {
const {primaryKey, restoreKey} = await this.computeKeys();
const cachePath = await this.getCacheGlobalDirectories();
core.saveState(State.CACHE_PATHS, cachePath);
core.saveState(State.STATE_CACHE_PRIMARY_KEY, primaryKey);
if (primaryKey.endsWith('-')) {
throw new Error(
`No file in ${process.cwd()} matched to [${this.patterns
.split('\n')
.join(',')}], make sure you have checked out the target repository`
);
}
const matchedKey = await cache.restoreCache(
cachePath,
primaryKey,
restoreKey
);
if (matchedKey) {
core.saveState(State.CACHE_MATCHED_KEY, matchedKey);
core.info(`Cache restored from key: ${matchedKey}`);
} else {
core.info(`${this.toolName} cache is not found`);
}
}
}
export default CacheDistributor;

View file

@ -0,0 +1,22 @@
import PipCache from './pip-cache';
import PipenvCache from './pipenv-cache';
export enum PackageManagers {
Pip = 'pip',
Pipenv = 'pipenv'
}
export async function getCacheDistributor(
packageManager: string,
pythonVersion: string,
patterns: string | undefined
) {
switch (packageManager) {
case PackageManagers.Pip:
return new PipCache(patterns);
case PackageManagers.Pipenv:
return new PipenvCache(pythonVersion, patterns);
default:
throw new Error(`Caching for '${packageManager}' is not supported`);
}
}

View file

@ -0,0 +1,47 @@
import * as glob from '@actions/glob';
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as path from 'path';
import os from 'os';
import CacheDistributor from './cache-distributor';
class PipCache extends CacheDistributor {
constructor(patterns: string = '**/requirements.txt') {
super('pip', patterns);
}
protected async getCacheGlobalDirectories() {
const {stdout, stderr, exitCode} = await exec.getExecOutput(
'pip cache dir'
);
if (stderr) {
throw new Error(
`Could not get cache folder path for pip package manager`
);
}
let resolvedPath = stdout.trim();
if (resolvedPath.includes('~')) {
resolvedPath = path.join(os.homedir(), resolvedPath.slice(1));
}
core.info(`global cache directory path is ${resolvedPath}`);
return [resolvedPath];
}
protected async computeKeys() {
const hash = await glob.hashFiles(this.patterns);
const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${this.toolName}-${hash}`;
const restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${this.toolName}-`;
return {
primaryKey,
restoreKey: [restoreKey]
};
}
}
export default PipCache;

View file

@ -0,0 +1,42 @@
import * as glob from '@actions/glob';
import * as os from 'os';
import * as path from 'path';
import * as core from '@actions/core';
import CacheDistributor from './cache-distributor';
class PipenvCache extends CacheDistributor {
constructor(
private pythonVersion: string,
protected patterns: string = 'Pipfile.lock'
) {
super('pipenv', patterns);
}
private getVirtualenvsPath() {
if (process.platform === 'win32') {
return '.virtualenvs';
} else {
return '.local/share/virtualenvs';
}
}
protected async getCacheGlobalDirectories() {
const cachePath = path.join(os.homedir(), this.getVirtualenvsPath());
core.debug(`Pipenv virtualenvs path is ${cachePath}`);
return [cachePath];
}
protected async computeKeys() {
const hash = await glob.hashFiles(this.patterns);
const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-python-${this.pythonVersion}-${this.toolName}-${hash}`;
const restoreKey = undefined;
return {
primaryKey,
restoreKey
};
}
}
export default PipenvCache;