2021-11-17 13:31:22 +03:00
|
|
|
import * as glob from '@actions/glob';
|
|
|
|
|
import * as core from '@actions/core';
|
|
|
|
|
import * as exec from '@actions/exec';
|
2022-02-04 14:00:41 +03:00
|
|
|
import * as child_process from 'child_process';
|
|
|
|
|
import utils from 'util';
|
2021-11-17 13:31:22 +03:00
|
|
|
import * as path from 'path';
|
|
|
|
|
import os from 'os';
|
|
|
|
|
|
2026-07-15 22:10:44 +05:30
|
|
|
import CacheDistributor from './cache-distributor.js';
|
|
|
|
|
import {IS_WINDOWS} from '../utils.js';
|
|
|
|
|
import {CACHE_DEPENDENCY_BACKUP_PATH} from './constants.js';
|
2021-11-17 13:31:22 +03:00
|
|
|
|
|
|
|
|
class PipCache extends CacheDistributor {
|
2023-02-20 13:36:57 +01:00
|
|
|
private cacheDependencyBackupPath: string = CACHE_DEPENDENCY_BACKUP_PATH;
|
|
|
|
|
|
2022-01-31 12:42:08 +02:00
|
|
|
constructor(
|
|
|
|
|
private pythonVersion: string,
|
2023-03-09 12:44:56 +02:00
|
|
|
cacheDependencyPath = '**/requirements.txt'
|
2022-01-31 12:42:08 +02:00
|
|
|
) {
|
2021-11-17 13:31:22 +03:00
|
|
|
super('pip', cacheDependencyPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected async getCacheGlobalDirectories() {
|
2026-06-23 23:31:57 +05:30
|
|
|
let exitCode = 0;
|
2022-02-04 14:00:41 +03:00
|
|
|
let stdout = '';
|
|
|
|
|
let stderr = '';
|
|
|
|
|
|
|
|
|
|
// Add temporary fix for Windows
|
2026-06-23 23:31:57 +05:30
|
|
|
// On Windows, it is necessary to execute through an exec
|
|
|
|
|
// because the getExecOutput gives a non-zero code or writes to stderr for pip 22.0.2,
|
2022-02-04 14:00:41 +03:00
|
|
|
// or spawn must be started with the shell option enabled for getExecOutput
|
|
|
|
|
// Related issue: https://github.com/actions/setup-python/issues/328
|
|
|
|
|
if (IS_WINDOWS) {
|
|
|
|
|
const execPromisify = utils.promisify(child_process.exec);
|
2026-06-23 23:31:57 +05:30
|
|
|
try {
|
|
|
|
|
({stdout, stderr} = await execPromisify('pip cache dir'));
|
|
|
|
|
} catch (err) {
|
|
|
|
|
// Pip outputs warnings to stderr (e.g., --no-python-version-warning flag deprecation warning), causing false failure detection
|
|
|
|
|
// Related issue: https://github.com/actions/setup-python/issues/1034
|
|
|
|
|
// If an error occurs, capture stderr and set exitCode to 1 to indicate failure
|
|
|
|
|
stderr = (err as any).stderr ?? (err as Error).message;
|
|
|
|
|
exitCode = 1;
|
|
|
|
|
}
|
2022-02-04 14:00:41 +03:00
|
|
|
} else {
|
2026-06-23 23:31:57 +05:30
|
|
|
({stdout, stderr, exitCode} = await exec.getExecOutput('pip cache dir'));
|
2022-02-04 14:00:41 +03:00
|
|
|
}
|
2021-11-17 13:31:22 +03:00
|
|
|
|
|
|
|
|
if (exitCode && 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.debug(`global cache directory path is ${resolvedPath}`);
|
|
|
|
|
|
|
|
|
|
return [resolvedPath];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected async computeKeys() {
|
2023-02-20 13:36:57 +01:00
|
|
|
const hash =
|
|
|
|
|
(await glob.hashFiles(this.cacheDependencyPath)) ||
|
|
|
|
|
(await glob.hashFiles(this.cacheDependencyBackupPath));
|
2026-06-19 05:17:28 +05:30
|
|
|
const osSegment = await this.getLinuxInfoKeySegment();
|
|
|
|
|
const primaryKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}-${hash}`;
|
|
|
|
|
const restoreKey = `${this.CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${process.arch}${osSegment}-python-${this.pythonVersion}-${this.packageManager}`;
|
2021-11-17 13:31:22 +03:00
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
primaryKey,
|
|
|
|
|
restoreKey: [restoreKey]
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default PipCache;
|