Skip to content

Commit 7b9ef6f

Browse files
Add another pip default dependency file for cache hash (actions#604)
1 parent 869e769 commit 7b9ef6f

File tree

7 files changed

+98
-18
lines changed

7 files changed

+98
-18
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Using `architecture` input it is possible to specify the required Python or PyPy
5252

5353
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.
5454

55-
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.
55+
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.
5656

5757
- For `pip`, the action will cache the global cache directory
5858
- For `pipenv`, the action will cache virtualenv directory

__tests__/cache-restore.test.ts

+37-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as exec from '@actions/exec';
55
import * as io from '@actions/io';
66
import {getCacheDistributor} from '../src/cache-distributions/cache-factory';
77
import {State} from '../src/cache-distributions/cache-distributor';
8-
import * as utils from './../src/utils';
8+
import * as constants from '../src/cache-distributions/constants';
99

1010
describe('restore-cache', () => {
1111
const pipFileLockHash =
@@ -196,11 +196,7 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
196196
30000
197197
);
198198

199-
it.each([
200-
['pip', '3.8.12', 'requirements-linux.txt', 'requirements-linux.txt'],
201-
['pip', '3.8.12', 'requirements.txt', 'requirements.txt'],
202-
['pipenv', '3.9.12', 'requirements.txt', 'requirements.txt']
203-
])(
199+
it.each([['pipenv', '3.9.12', 'requirements.txt', 'requirements.txt']])(
204200
'Should throw an error because dependency file is not found',
205201
async (
206202
packageManager,
@@ -213,13 +209,48 @@ virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/py
213209
pythonVersion,
214210
dependencyFile
215211
);
212+
216213
await expect(cacheDistributor.restoreCache()).rejects.toThrowError(
217214
`No file in ${process.cwd()} matched to [${cacheDependencyPath
218215
.split('\n')
219216
.join(',')}], make sure you have checked out the target repository`
220217
);
221218
}
222219
);
220+
221+
it.each([
222+
['pip', '3.8.12', 'requirements-linux.txt'],
223+
['pip', '3.8.12', 'requirements.txt']
224+
])(
225+
'Shouldn`t throw an error as there is a default file `pyproject.toml` to use when requirements.txt is not specified',
226+
async (packageManager, pythonVersion, dependencyFile) => {
227+
const cacheDistributor = getCacheDistributor(
228+
packageManager,
229+
pythonVersion,
230+
dependencyFile
231+
);
232+
await expect(cacheDistributor.restoreCache()).resolves;
233+
}
234+
);
235+
236+
it.each([
237+
['pip', '3.8.12', 'requirements-linux.txt'],
238+
['pip', '3.8.12', 'requirements.txt']
239+
])(
240+
'Should throw an error as there is no default file `pyproject.toml` to use when requirements.txt is not specified',
241+
async (packageManager, pythonVersion, dependencyFile) => {
242+
jest.mock('../src/cache-distributions/constants', () => ({
243+
CACHE_DEPENDENCY_BACKUP_PATH: '**/pyprojecttest.toml'
244+
}));
245+
246+
const cacheDistributor = getCacheDistributor(
247+
packageManager,
248+
pythonVersion,
249+
dependencyFile
250+
);
251+
await expect(cacheDistributor.restoreCache()).resolves;
252+
}
253+
);
223254
});
224255

225256
describe('Dependencies changed', () => {

dist/cache-save/index.js

+20-3
Original file line numberDiff line numberDiff line change
@@ -59699,6 +59699,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
5969959699
exports.State = void 0;
5970059700
const cache = __importStar(__nccwpck_require__(7799));
5970159701
const core = __importStar(__nccwpck_require__(2186));
59702+
const constants_1 = __nccwpck_require__(8248);
5970259703
var State;
5970359704
(function (State) {
5970459705
State["STATE_CACHE_PRIMARY_KEY"] = "cache-primary-key";
@@ -59718,9 +59719,12 @@ class CacheDistributor {
5971859719
return __awaiter(this, void 0, void 0, function* () {
5971959720
const { primaryKey, restoreKey } = yield this.computeKeys();
5972059721
if (primaryKey.endsWith('-')) {
59721-
throw new Error(`No file in ${process.cwd()} matched to [${this.cacheDependencyPath
59722-
.split('\n')
59723-
.join(',')}], make sure you have checked out the target repository`);
59722+
const file = this.packageManager === 'pip'
59723+
? `${this.cacheDependencyPath
59724+
.split('\n')
59725+
.join(',')} or ${constants_1.CACHE_DEPENDENCY_BACKUP_PATH}`
59726+
: this.cacheDependencyPath.split('\n').join(',');
59727+
throw new Error(`No file in ${process.cwd()} matched to [${file}], make sure you have checked out the target repository`);
5972459728
}
5972559729
const cachePath = yield this.getCacheGlobalDirectories();
5972659730
core.saveState(State.CACHE_PATHS, cachePath);
@@ -59744,6 +59748,19 @@ class CacheDistributor {
5974459748
exports["default"] = CacheDistributor;
5974559749

5974659750

59751+
/***/ }),
59752+
59753+
/***/ 8248:
59754+
/***/ ((__unused_webpack_module, exports) => {
59755+
59756+
"use strict";
59757+
59758+
Object.defineProperty(exports, "__esModule", ({ value: true }));
59759+
exports.CACHE_DEPENDENCY_BACKUP_PATH = void 0;
59760+
const CACHE_DEPENDENCY_BACKUP_PATH = '**/pyproject.toml';
59761+
exports.CACHE_DEPENDENCY_BACKUP_PATH = CACHE_DEPENDENCY_BACKUP_PATH;
59762+
59763+
5974759764
/***/ }),
5974859765

5974959766
/***/ 4553:

dist/setup/index.js

+24-4
Original file line numberDiff line numberDiff line change
@@ -65775,6 +65775,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
6577565775
exports.State = void 0;
6577665776
const cache = __importStar(__nccwpck_require__(7799));
6577765777
const core = __importStar(__nccwpck_require__(2186));
65778+
const constants_1 = __nccwpck_require__(8248);
6577865779
var State;
6577965780
(function (State) {
6578065781
State["STATE_CACHE_PRIMARY_KEY"] = "cache-primary-key";
@@ -65794,9 +65795,12 @@ class CacheDistributor {
6579465795
return __awaiter(this, void 0, void 0, function* () {
6579565796
const { primaryKey, restoreKey } = yield this.computeKeys();
6579665797
if (primaryKey.endsWith('-')) {
65797-
throw new Error(`No file in ${process.cwd()} matched to [${this.cacheDependencyPath
65798-
.split('\n')
65799-
.join(',')}], make sure you have checked out the target repository`);
65798+
const file = this.packageManager === 'pip'
65799+
? `${this.cacheDependencyPath
65800+
.split('\n')
65801+
.join(',')} or ${constants_1.CACHE_DEPENDENCY_BACKUP_PATH}`
65802+
: this.cacheDependencyPath.split('\n').join(',');
65803+
throw new Error(`No file in ${process.cwd()} matched to [${file}], make sure you have checked out the target repository`);
6580065804
}
6580165805
const cachePath = yield this.getCacheGlobalDirectories();
6580265806
core.saveState(State.CACHE_PATHS, cachePath);
@@ -65856,6 +65860,19 @@ function getCacheDistributor(packageManager, pythonVersion, cacheDependencyPath)
6585665860
exports.getCacheDistributor = getCacheDistributor;
6585765861

6585865862

65863+
/***/ }),
65864+
65865+
/***/ 8248:
65866+
/***/ ((__unused_webpack_module, exports) => {
65867+
65868+
"use strict";
65869+
65870+
Object.defineProperty(exports, "__esModule", ({ value: true }));
65871+
exports.CACHE_DEPENDENCY_BACKUP_PATH = void 0;
65872+
const CACHE_DEPENDENCY_BACKUP_PATH = '**/pyproject.toml';
65873+
exports.CACHE_DEPENDENCY_BACKUP_PATH = CACHE_DEPENDENCY_BACKUP_PATH;
65874+
65875+
6585965876
/***/ }),
6586065877

6586165878
/***/ 5546:
@@ -65904,10 +65921,12 @@ const path = __importStar(__nccwpck_require__(1017));
6590465921
const os_1 = __importDefault(__nccwpck_require__(2037));
6590565922
const cache_distributor_1 = __importDefault(__nccwpck_require__(8953));
6590665923
const utils_1 = __nccwpck_require__(1314);
65924+
const constants_1 = __nccwpck_require__(8248);
6590765925
class PipCache extends cache_distributor_1.default {
6590865926
constructor(pythonVersion, cacheDependencyPath = '**/requirements.txt') {
6590965927
super('pip', cacheDependencyPath);
6591065928
this.pythonVersion = pythonVersion;
65929+
this.cacheDependencyBackupPath = constants_1.CACHE_DEPENDENCY_BACKUP_PATH;
6591165930
}
6591265931
getCacheGlobalDirectories() {
6591365932
return __awaiter(this, void 0, void 0, function* () {
@@ -65943,7 +65962,8 @@ class PipCache extends cache_distributor_1.default {
6594365962
}
6594465963
computeKeys() {
6594565964
return __awaiter(this, void 0, void 0, function* () {
65946-
const hash = yield glob.hashFiles(this.cacheDependencyPath);
65965+
const hash = (yield glob.hashFiles(this.cacheDependencyPath)) ||
65966+
(yield glob.hashFiles(this.cacheDependencyBackupPath));
6594765967
let primaryKey = '';
6594865968
let restoreKey = '';
6594965969
if (utils_1.IS_LINUX) {

src/cache-distributions/cache-distributor.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as cache from '@actions/cache';
22
import * as core from '@actions/core';
3+
import {CACHE_DEPENDENCY_BACKUP_PATH} from './constants';
34

45
export enum State {
56
STATE_CACHE_PRIMARY_KEY = 'cache-primary-key',
@@ -24,10 +25,14 @@ abstract class CacheDistributor {
2425
public async restoreCache() {
2526
const {primaryKey, restoreKey} = await this.computeKeys();
2627
if (primaryKey.endsWith('-')) {
28+
const file =
29+
this.packageManager === 'pip'
30+
? `${this.cacheDependencyPath
31+
.split('\n')
32+
.join(',')} or ${CACHE_DEPENDENCY_BACKUP_PATH}`
33+
: this.cacheDependencyPath.split('\n').join(',');
2734
throw new Error(
28-
`No file in ${process.cwd()} matched to [${this.cacheDependencyPath
29-
.split('\n')
30-
.join(',')}], make sure you have checked out the target repository`
35+
`No file in ${process.cwd()} matched to [${file}], make sure you have checked out the target repository`
3136
);
3237
}
3338

src/cache-distributions/constants.ts

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

src/cache-distributions/pip-cache.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ import os from 'os';
88

99
import CacheDistributor from './cache-distributor';
1010
import {getLinuxInfo, IS_LINUX, IS_WINDOWS} from '../utils';
11+
import {CACHE_DEPENDENCY_BACKUP_PATH} from './constants';
1112

1213
class PipCache extends CacheDistributor {
14+
private cacheDependencyBackupPath: string = CACHE_DEPENDENCY_BACKUP_PATH;
15+
1316
constructor(
1417
private pythonVersion: string,
1518
cacheDependencyPath: string = '**/requirements.txt'
@@ -56,7 +59,9 @@ class PipCache extends CacheDistributor {
5659
}
5760

5861
protected async computeKeys() {
59-
const hash = await glob.hashFiles(this.cacheDependencyPath);
62+
const hash =
63+
(await glob.hashFiles(this.cacheDependencyPath)) ||
64+
(await glob.hashFiles(this.cacheDependencyBackupPath));
6065
let primaryKey = '';
6166
let restoreKey = '';
6267

0 commit comments

Comments
 (0)