-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
131 lines (111 loc) · 4.05 KB
/
index.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
/*
* Copyright 2022 leorize <leorize+oss@disroot.org>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
import * as core from "@actions/core";
import * as gh from "@actions/github";
import * as tc from "@actions/tool-cache";
import * as searcher from "./searcher";
import * as fs from "fs/promises";
import * as path from "path";
import * as os from "os";
import * as exec from "@actions/exec";
import { fileURLToPath } from "url";
import { v4 as uuidgen } from "uuid";
import { Octokit } from "@octokit/core";
/**
* The name of the tool being setup.
*/
const ToolName = "nimskull";
/**
* Entry point for the script
*/
async function setup() {
try {
const octokit = gh.getOctokit(core.getInput("token"), { required: true });
const version = core.getInput("nimskull-version", { required: true });
const update = core.getBooleanInput("check-latest");
await setupCompiler(octokit, version, update);
/* Since the JS being run will be in dist/, back out one folder to get the root */
const actionRoot = path.join(
path.dirname(fileURLToPath(import.meta.url)),
"..",
);
core.info(
"::add-matcher::" +
path.join(actionRoot, ".github", "nimskull-problem-matcher.json"),
);
} catch (error: any) {
core.setFailed(error.message);
}
}
/**
* Download and setup the compiler, as well as setting outputs for the action.
*
* @param client - The Octokit client used to download release data
* @param range - The semver range to match against
* @param update - Whether to update the compiler to the latest version if available.
*/
async function setupCompiler(client: Octokit, range: string, update: boolean) {
/* Check to see if the requested version is in the cache */
let installDir = tc.find(ToolName, range);
/* If its not in the cache or an update is requested */
if (!installDir || update) {
const release = await searcher.findVersion(client, range);
if (!release)
throw `Could not find any release matching the specification: ${range}`;
core.info(`Latest version matching specification: ${release.tag}`);
installDir = tc.find(ToolName, release.tag);
/* If this version is not in the cache, download and install it */
if (!installDir) {
core.info(`Version ${release.tag} is not in tool cache, downloading`);
const url = await searcher.getDownloadUrl(client, release.id);
if (!url)
throw `There are no prebuilt binaries for the current platform.`;
const compilerDir = await downloadAndExtractCompiler(url);
installDir = await tc.cacheDir(compilerDir, ToolName, release.tag);
core.info(`Added ${release.tag} to tool cache`);
}
}
const { version, commit } = JSON.parse(
await fs.readFile(path.join(installDir, "release.json"), {
encoding: "utf8",
}),
);
const binDir = path.join(installDir, "bin");
core.addPath(binDir);
core.setOutput("path", installDir);
core.setOutput("bin-path", binDir);
core.setOutput("nimskull-version", version);
core.setOutput("nimskull-commit", commit);
}
/**
* Download and extract the compiler
*
* @param url - The URL to download compiler from. Assumed to be a Github download URL.
* @return The extracted compiler directory.
*/
async function downloadAndExtractCompiler(url: string): Promise<string> {
const downloaded = await tc.downloadTool(url);
let result = "";
if (url.endsWith(".zip")) result = await tc.extractZip(downloaded);
else {
const tarFile = path.join(
process.env["RUNNER_TEMP"] || os.tmpdir(),
uuidgen(),
);
/* Un-zstd the archive manually as some tar versions doesn't support zstd */
await exec.exec("unzstd", [downloaded, "-o", tarFile]);
result = await tc.extractTar(tarFile, undefined, ["x"]);
}
/* The archive consist of one top-level folder, which contains the
* compiler and tools. */
const files = await fs.readdir(result);
if (files.length !== 1)
throw `Expected 1 folder in extracted archive but got ${files.length}`;
/* Set that folder as the result */
result = path.join(result, files[0]!);
return result;
}
setup();