Skip to content

Commit

Permalink
Add another pip default dependency file for cache hash (#604)
Browse files Browse the repository at this point in the history
  • Loading branch information
e-korolevskii committed Feb 20, 2023
1 parent 869e769 commit 7b9ef6f
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
43 changes: 37 additions & 6 deletions __tests__/cache-restore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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,
Expand All @@ -213,13 +209,48 @@ 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')
.join(',')}], make sure you have checked out the target repository`
);
}
);

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', () => {
Expand Down
23 changes: 20 additions & 3 deletions dist/cache-save/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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);
Expand All @@ -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:
Expand Down
28 changes: 24 additions & 4 deletions dist/setup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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);
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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* () {
Expand Down Expand Up @@ -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) {
Expand Down
11 changes: 8 additions & 3 deletions src/cache-distributions/cache-distributor.ts
Original file line number Diff line number Diff line change
@@ -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',
Expand All @@ -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`
);
}

Expand Down
2 changes: 2 additions & 0 deletions src/cache-distributions/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const CACHE_DEPENDENCY_BACKUP_PATH: string = '**/pyproject.toml';
export {CACHE_DEPENDENCY_BACKUP_PATH};
7 changes: 6 additions & 1 deletion src/cache-distributions/pip-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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 = '';

Expand Down

0 comments on commit 7b9ef6f

Please sign in to comment.