Add another pip default dependency file for cache hash (#604)

This commit is contained in:
Evgenii Korolevskii 2023-02-20 13:36:57 +01:00 committed by GitHub
parent 869e769ec8
commit 7b9ef6fc5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 98 additions and 18 deletions

View File

@ -52,7 +52,7 @@ Using `architecture` input it is possible to specify the required Python or PyPy
The action has built-in functionality for caching and restoring dependencies. It uses [toolkit/cache](https://github.com/actions/toolkit/tree/main/packages/cache) under the hood for caching dependencies but requires less configuration settings. Supported package managers are `pip`, `pipenv` and `poetry`. The `cache` input is optional, and caching is turned off by default.
The action defaults to searching for a dependency file (`requirements.txt` for pip, `Pipfile.lock` for pipenv or `poetry.lock` for poetry) in the repository, and uses its hash as a part of the cache key. Input `cache-dependency-path` is used for cases when multiple dependency files are used, they are located in different subdirectories or different files for the hash that want to be used.
The action defaults to searching for a dependency file (`requirements.txt` or `pyproject.toml` for pip, `Pipfile.lock` for pipenv or `poetry.lock` for poetry) in the repository, and uses its hash as a part of the cache key. Input `cache-dependency-path` is used for cases when multiple dependency files are used, they are located in different subdirectories or different files for the hash that want to be used.
- For `pip`, the action will cache the global cache directory
- For `pipenv`, the action will cache virtualenv directory

View File

@ -5,7 +5,7 @@ import * as exec from '@actions/exec';
import * as io from '@actions/io';
import {getCacheDistributor} from '../src/cache-distributions/cache-factory';
import {State} from '../src/cache-distributions/cache-distributor';
import * as utils from './../src/utils';
import * as constants from '../src/cache-distributions/constants';
describe('restore-cache', () => {
const pipFileLockHash =
@ -196,11 +196,7 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
30000
);
it.each([
['pip', '3.8.12', 'requirements-linux.txt', 'requirements-linux.txt'],
['pip', '3.8.12', 'requirements.txt', 'requirements.txt'],
['pipenv', '3.9.12', 'requirements.txt', 'requirements.txt']
])(
it.each([['pipenv', '3.9.12', 'requirements.txt', 'requirements.txt']])(
'Should throw an error because dependency file is not found',
async (
packageManager,
@ -213,6 +209,7 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
pythonVersion,
dependencyFile
);
await expect(cacheDistributor.restoreCache()).rejects.toThrowError(
`No file in ${process.cwd()} matched to [${cacheDependencyPath
.split('\n')
@ -220,6 +217,40 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
);
}
);
it.each([
['pip', '3.8.12', 'requirements-linux.txt'],
['pip', '3.8.12', 'requirements.txt']
])(
'Shouldn`t throw an error as there is a default file `pyproject.toml` to use when requirements.txt is not specified',
async (packageManager, pythonVersion, dependencyFile) => {
const cacheDistributor = getCacheDistributor(
packageManager,
pythonVersion,
dependencyFile
);
await expect(cacheDistributor.restoreCache()).resolves;
}
);
it.each([
['pip', '3.8.12', 'requirements-linux.txt'],
['pip', '3.8.12', 'requirements.txt']
])(
'Should throw an error as there is no default file `pyproject.toml` to use when requirements.txt is not specified',
async (packageManager, pythonVersion, dependencyFile) => {
jest.mock('../src/cache-distributions/constants', () => ({
CACHE_DEPENDENCY_BACKUP_PATH: '**/pyprojecttest.toml'
}));
const cacheDistributor = getCacheDistributor(
packageManager,
pythonVersion,
dependencyFile
);
await expect(cacheDistributor.restoreCache()).resolves;
}
);
});
describe('Dependencies changed', () => {

View File

@ -59699,6 +59699,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.State = void 0;
const cache = __importStar(__nccwpck_require__(7799));
const core = __importStar(__nccwpck_require__(2186));
const constants_1 = __nccwpck_require__(8248);
var State;
(function (State) {
State["STATE_CACHE_PRIMARY_KEY"] = "cache-primary-key";
@ -59718,9 +59719,12 @@ class CacheDistributor {
return __awaiter(this, void 0, void 0, function* () {
const { primaryKey, restoreKey } = yield this.computeKeys();
if (primaryKey.endsWith('-')) {
throw new Error(`No file in ${process.cwd()} matched to [${this.cacheDependencyPath
.split('\n')
.join(',')}], make sure you have checked out the target repository`);
const file = this.packageManager === 'pip'
? `${this.cacheDependencyPath
.split('\n')
.join(',')} or ${constants_1.CACHE_DEPENDENCY_BACKUP_PATH}`
: this.cacheDependencyPath.split('\n').join(',');
throw new Error(`No file in ${process.cwd()} matched to [${file}], make sure you have checked out the target repository`);
}
const cachePath = yield this.getCacheGlobalDirectories();
core.saveState(State.CACHE_PATHS, cachePath);
@ -59744,6 +59748,19 @@ class CacheDistributor {
exports["default"] = CacheDistributor;
/***/ }),
/***/ 8248:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.CACHE_DEPENDENCY_BACKUP_PATH = void 0;
const CACHE_DEPENDENCY_BACKUP_PATH = '**/pyproject.toml';
exports.CACHE_DEPENDENCY_BACKUP_PATH = CACHE_DEPENDENCY_BACKUP_PATH;
/***/ }),
/***/ 4553:

28
dist/setup/index.js vendored
View File

@ -65775,6 +65775,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.State = void 0;
const cache = __importStar(__nccwpck_require__(7799));
const core = __importStar(__nccwpck_require__(2186));
const constants_1 = __nccwpck_require__(8248);
var State;
(function (State) {
State["STATE_CACHE_PRIMARY_KEY"] = "cache-primary-key";
@ -65794,9 +65795,12 @@ class CacheDistributor {
return __awaiter(this, void 0, void 0, function* () {
const { primaryKey, restoreKey } = yield this.computeKeys();
if (primaryKey.endsWith('-')) {
throw new Error(`No file in ${process.cwd()} matched to [${this.cacheDependencyPath
.split('\n')
.join(',')}], make sure you have checked out the target repository`);
const file = this.packageManager === 'pip'
? `${this.cacheDependencyPath
.split('\n')
.join(',')} or ${constants_1.CACHE_DEPENDENCY_BACKUP_PATH}`
: this.cacheDependencyPath.split('\n').join(',');
throw new Error(`No file in ${process.cwd()} matched to [${file}], make sure you have checked out the target repository`);
}
const cachePath = yield this.getCacheGlobalDirectories();
core.saveState(State.CACHE_PATHS, cachePath);
@ -65856,6 +65860,19 @@ function getCacheDistributor(packageManager, pythonVersion, cacheDependencyPath)
exports.getCacheDistributor = getCacheDistributor;
/***/ }),
/***/ 8248:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.CACHE_DEPENDENCY_BACKUP_PATH = void 0;
const CACHE_DEPENDENCY_BACKUP_PATH = '**/pyproject.toml';
exports.CACHE_DEPENDENCY_BACKUP_PATH = CACHE_DEPENDENCY_BACKUP_PATH;
/***/ }),
/***/ 5546:
@ -65904,10 +65921,12 @@ const path = __importStar(__nccwpck_require__(1017));
const os_1 = __importDefault(__nccwpck_require__(2037));
const cache_distributor_1 = __importDefault(__nccwpck_require__(8953));
const utils_1 = __nccwpck_require__(1314);
const constants_1 = __nccwpck_require__(8248);
class PipCache extends cache_distributor_1.default {
constructor(pythonVersion, cacheDependencyPath = '**/requirements.txt') {
super('pip', cacheDependencyPath);
this.pythonVersion = pythonVersion;
this.cacheDependencyBackupPath = constants_1.CACHE_DEPENDENCY_BACKUP_PATH;
}
getCacheGlobalDirectories() {
return __awaiter(this, void 0, void 0, function* () {
@ -65943,7 +65962,8 @@ class PipCache extends cache_distributor_1.default {
}
computeKeys() {
return __awaiter(this, void 0, void 0, function* () {
const hash = yield glob.hashFiles(this.cacheDependencyPath);
const hash = (yield glob.hashFiles(this.cacheDependencyPath)) ||
(yield glob.hashFiles(this.cacheDependencyBackupPath));
let primaryKey = '';
let restoreKey = '';
if (utils_1.IS_LINUX) {

View File

@ -1,5 +1,6 @@
import * as cache from '@actions/cache';
import * as core from '@actions/core';
import {CACHE_DEPENDENCY_BACKUP_PATH} from './constants';
export enum State {
STATE_CACHE_PRIMARY_KEY = 'cache-primary-key',
@ -24,10 +25,14 @@ abstract class CacheDistributor {
public async restoreCache() {
const {primaryKey, restoreKey} = await this.computeKeys();
if (primaryKey.endsWith('-')) {
const file =
this.packageManager === 'pip'
? `${this.cacheDependencyPath
.split('\n')
.join(',')} or ${CACHE_DEPENDENCY_BACKUP_PATH}`
: this.cacheDependencyPath.split('\n').join(',');
throw new Error(
`No file in ${process.cwd()} matched to [${this.cacheDependencyPath
.split('\n')
.join(',')}], make sure you have checked out the target repository`
`No file in ${process.cwd()} matched to [${file}], make sure you have checked out the target repository`
);
}

View File

@ -0,0 +1,2 @@
const CACHE_DEPENDENCY_BACKUP_PATH: string = '**/pyproject.toml';
export {CACHE_DEPENDENCY_BACKUP_PATH};

View File

@ -8,8 +8,11 @@ import os from 'os';
import CacheDistributor from './cache-distributor';
import {getLinuxInfo, IS_LINUX, IS_WINDOWS} from '../utils';
import {CACHE_DEPENDENCY_BACKUP_PATH} from './constants';
class PipCache extends CacheDistributor {
private cacheDependencyBackupPath: string = CACHE_DEPENDENCY_BACKUP_PATH;
constructor(
private pythonVersion: string,
cacheDependencyPath: string = '**/requirements.txt'
@ -56,7 +59,9 @@ class PipCache extends CacheDistributor {
}
protected async computeKeys() {
const hash = await glob.hashFiles(this.cacheDependencyPath);
const hash =
(await glob.hashFiles(this.cacheDependencyPath)) ||
(await glob.hashFiles(this.cacheDependencyBackupPath));
let primaryKey = '';
let restoreKey = '';