-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.js
224 lines (184 loc) · 6.74 KB
/
index.js
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
const cache = require('@actions/cache');
const core = require('@actions/core');
const exec = require('@actions/exec');
const fs = require('fs');
const glob = require('@actions/glob');
const http = require('@actions/http-client');
const io = require('@actions/io');
const tc = require('@actions/tool-cache');
const os = require('os');
const path = require('path');
const process = require('process');
function isExactCacheKeyMatch(key, cacheKey) {
return !!(cacheKey && cacheKey.localeCompare(key, undefined, { sensitivity: "accent" }) === 0);
}
async function getRelease(version, token) {
let osPlatform = os.platform();
const platformMappings = {
'win32': 'windows'
};
osPlatform = platformMappings[osPlatform] || osPlatform;
let osArch = os.arch();
const archMappings = {
x32: 'i386',
x64: 'x86_64'
};
osArch = archMappings[osArch] || osArch;
core.debug(`Finding release for ${version} (${osPlatform}_${osArch})`);
const release = await fetchRelease(version, token);
if (!release.name) {
core.warning(`API response: ${JSON.stringify(release)}`);
core.warning(`If you are hitting API rate limits, see the README for instructions on using a GitHub token.`);
throw new Error(`No trellis-cli release found for version ${version}`);
}
core.debug(`Release ${release.name} (tag: ${release.tag_name}) found.`);
const asset = release.assets.find((asset) => {
if (asset.browser_download_url.match(new RegExp(osArch, 'i')) && asset.browser_download_url.match(new RegExp(osPlatform, 'i'))) {
return asset;
}
});
if (!asset) {
throw new Error(`No trellis-cli binary found for platform ${osPlatform} or arch ${osArch}.`);
}
return {
version: release.tag_name,
url: asset.browser_download_url,
}
}
async function fetchRelease(version, token) {
const client = new http.HttpClient('setup-trellis-cli-client');
let headers = {};
if (token !== '') {
headers['authorization'] = `Bearer ${token}`;
} else {
core.warning(`No repo-token provided. We recommend setting one to avoid rate limiting. See the README for instructions.`);
}
let url = null;
if (version === 'latest' || version === '') {
url = `https://api.github.com/repos/roots/trellis-cli/releases/latest`;
} else {
url = `https://api.github.com/repos/roots/trellis-cli/releases/tags/${version}`;
}
const response = await client.get(url, headers);
const body = await response.readBody();
return JSON.parse(body);
}
async function downloadRelease(release) {
const downloadPath = await tc.downloadTool(release.url);
core.debug(`Downloaded to ${downloadPath}`);
const cliPath = await tc.extractTar(downloadPath);
core.debug(`Extracted to ${cliPath}`);
const cachePath = await tc.cacheDir(cliPath, 'trellis-cli', release.version);
core.debug(`Cached to ${cachePath}`);
return cachePath;
}
async function ensurePython3() {
try {
const python3Path = await io.which('python3', true);
core.debug(`python3 found at ${python3Path}`);
if (core.isDebug()) {
await exec.exec('python3 --version');
}
} catch(error) {
const msg = `
Python not found and is a required dependency for using trellis-cli and Trellis.
Add a setup-python step like the one below *before* setup-trellis-cli.
- uses: actions/setup-python@v2
with:
python-version: '3.9'
`
throw new Error(msg);
}
}
async function withCache(cacheable, paths, baseKey, hashPattern) {
const keyPrefix = `${process.env.RUNNER_OS}-${baseKey}-`;
const hash = await glob.hashFiles(hashPattern);
const primaryKey = `${keyPrefix}${hash}`;
const restoreKeys = [keyPrefix];
const cacheKey = await cache.restoreCache(paths, primaryKey, restoreKeys);
if (!cacheKey) {
core.info(`Cache not found for keys: ${[primaryKey, ...restoreKeys].join(", ")}`);
} else {
core.info(`Cache restored from key: ${cacheKey}`);
}
await cacheable();
if (isExactCacheKeyMatch(primaryKey, cacheKey)) {
core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
return;
}
try {
await cache.saveCache(paths, primaryKey);
} catch {
await cache.saveCache(paths, primaryKey + "-retry");
}
}
async function cachedInit() {
return await withCache(async () => {
await exec.exec('trellis init')
}, [path.join('.trellis', 'virtualenv')], 'trellis-venv', '**/requirements.txt');
}
async function runGalaxyInstall() {
return await withCache(async () => {
await exec.exec('trellis galaxy install')
}, [path.join('vendor', 'roles')], 'trellis-galaxy', '**/galaxy.yml');
}
async function run() {
try {
const ansibleVaultPassword = core.getInput('ansible-vault-password', { required: true});
const autoInit = core.getBooleanInput('auto-init');
const cacheVirtualenv = core.getBooleanInput('cache-virtualenv');
const galaxyInstall = core.getBooleanInput('galaxy-install');
const trellisPath = core.getInput('trellis-directory') || 'trellis';
const version = core.getInput('version') || 'latest';
const token = core.getInput('repo-token');
await core.group('Install trellis-cli', async () => {
const release = await getRelease(version, token);
const cliPath = await downloadRelease(release);
core.addPath(cliPath);
core.debug(`Added ${cliPath} to PATH`);
// don't check for trellis-cli updates
core.exportVariable('TRELLIS_NO_UPDATE_NOTIFIER', 'true');
core.info(`trellis-cli ${release.version} installed successfully`);
core.setOutput('version', release.version);
});
await ensurePython3();
try {
core.debug(`Changing directories to ${trellisPath}`);
process.chdir(trellisPath)
} catch (error) {
throw new Error(`Could not change directory to ${trellisPath}. Ensure directory exists first.`);
}
core.startGroup('Create .vault_pass file')
if (ansibleVaultPassword != '') {
fs.writeFileSync('.vault_pass', ansibleVaultPassword, { mode: 0o644 });
core.info(`Vault password written to .vault_pass file`);
}
core.endGroup()
if (autoInit) {
core.debug(`auto-init enabled`);
if (cacheVirtualenv) {
core.debug(`cache-virtualenv enabled`);
await core.group('Initialize project', async () => {
await cachedInit();
});
} else {
await core.group('Initialize project', async () => {
await exec.exec('trellis init');
});
}
}
if (galaxyInstall) {
core.debug(`galaxy-install enabled`);
await core.group('Install Galaxy roles', async () => {
await runGalaxyInstall();
});
}
} catch (error) {
if (error.name === cache.ReserveCacheError.name) {
core.info(error.message);
} else {
core.setFailed(error.message);
}
}
}
run();