-
Notifications
You must be signed in to change notification settings - Fork 754
/
cache.ts
134 lines (122 loc) · 4.77 KB
/
cache.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
* @fileoverview this file provides methods handling dependency cache
*/
import { join } from 'path';
import os from 'os';
import * as cache from '@actions/cache';
import * as core from '@actions/core';
import * as glob from '@actions/glob';
const STATE_CACHE_PRIMARY_KEY = 'cache-primary-key';
const CACHE_MATCHED_KEY = 'cache-matched-key';
const CACHE_KEY_PREFIX = 'setup-java';
interface PackageManager {
id: 'maven' | 'gradle';
/**
* Paths of the file that specify the files to cache.
*/
path: string[];
pattern: string[];
}
const supportedPackageManager: PackageManager[] = [
{
id: 'maven',
path: [join(os.homedir(), '.m2', 'repository')],
// https://github.com/actions/cache/blob/0638051e9af2c23d10bb70fa9beffcad6cff9ce3/examples.md#java---maven
pattern: ['**/pom.xml']
},
{
id: 'gradle',
path: [join(os.homedir(), '.gradle', 'caches'), join(os.homedir(), '.gradle', 'wrapper')],
// https://github.com/actions/cache/blob/0638051e9af2c23d10bb70fa9beffcad6cff9ce3/examples.md#java---gradle
pattern: ['**/*.gradle*', '**/gradle-wrapper.properties']
}
];
function findPackageManager(id: string): PackageManager {
const packageManager = supportedPackageManager.find(packageManager => packageManager.id === id);
if (packageManager === undefined) {
throw new Error(`unknown package manager specified: ${id}`);
}
return packageManager;
}
/**
* A function that generates a cache key to use.
* Format of the generated key will be "${{ platform }}-${{ id }}-${{ fileHash }}"".
* If there is no file matched to {@link PackageManager.path}, the generated key ends with a dash (-).
* @see {@link https://docs.github.com/en/actions/guides/caching-dependencies-to-speed-up-workflows#matching-a-cache-key|spec of cache key}
*/
async function computeCacheKey(packageManager: PackageManager) {
const hash = await glob.hashFiles(packageManager.pattern.join('\n'));
return `${CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${packageManager.id}-${hash}`;
}
/**
* Restore the dependency cache
* @param id ID of the package manager, should be "maven" or "gradle"
*/
export async function restore(id: string) {
const packageManager = findPackageManager(id);
const primaryKey = await computeCacheKey(packageManager);
core.debug(`primary key is ${primaryKey}`);
core.saveState(STATE_CACHE_PRIMARY_KEY, primaryKey);
if (primaryKey.endsWith('-')) {
throw new Error(
`No file in ${process.cwd()} matched to [${
packageManager.pattern
}], make sure you have checked out the target repository`
);
}
const matchedKey = await cache.restoreCache(packageManager.path, primaryKey, [
`${CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${id}`
]);
if (matchedKey) {
core.saveState(CACHE_MATCHED_KEY, matchedKey);
core.info(`Cache restored from key: ${matchedKey}`);
} else {
core.info(`${packageManager.id} cache is not found`);
}
}
/**
* Save the dependency cache
* @param id ID of the package manager, should be "maven" or "gradle"
*/
export async function save(id: string) {
const packageManager = findPackageManager(id);
const matchedKey = core.getState(CACHE_MATCHED_KEY);
// Inputs are re-evaluted before the post action, so we want the original key used for restore
const primaryKey = core.getState(STATE_CACHE_PRIMARY_KEY);
if (!primaryKey) {
core.warning('Error retrieving key from state.');
return;
} else if (matchedKey === primaryKey) {
// no change in target directories
core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
return;
}
try {
await cache.saveCache(packageManager.path, primaryKey);
core.info(`Cache saved with the key: ${primaryKey}`);
} catch (error) {
if (error.name === cache.ReserveCacheError.name) {
core.info(error.message);
} else {
if (isProbablyGradleDaemonProblem(packageManager, error)) {
core.warning(
'Failed to save Gradle cache on Windows. If tar.exe reported "Permission denied", try to run Gradle with `--no-daemon` option. Refer to https://github.com/actions/cache/issues/454 for details.'
);
}
throw error;
}
}
}
/**
* @param packageManager the specified package manager by user
* @param error the error thrown by the saveCache
* @returns true if the given error seems related to the {@link https://github.com/actions/cache/issues/454|running Gradle Daemon issue}.
* @see {@link https://github.com/actions/cache/issues/454#issuecomment-840493935|why --no-daemon is necessary}
*/
function isProbablyGradleDaemonProblem(packageManager: PackageManager, error: Error) {
if (packageManager.id !== 'gradle' || process.env['RUNNER_OS'] !== 'Windows') {
return false;
}
const message = error.message || '';
return message.startsWith('Tar failed with error: ');
}