-
Notifications
You must be signed in to change notification settings - Fork 48
/
generate.ts
115 lines (95 loc) · 3.45 KB
/
generate.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
import * as _ from "lodash";
import stringify, { Comparator } from "json-stable-stringify";
import { Octokit } from "@octokit/rest";
import { Endpoints } from "@octokit/types";
import { writeFileSync } from "fs";
import { resolve } from "path";
//================================================
// GitHub
//================================================
type Release = Endpoints["GET /repos/{owner}/{repo}/releases"]["response"]["data"][number];
const github = new Octokit({ auth: process.env.GH_TOKEN });
//================================================
// Version
//================================================
type Version = string;
const VERSION_PATTERNS: RegExp[] = [/^llvmorg-(?<version>\d+\.\d+\.\d+)$/];
function extractVersionNumber(release: Release): Version | undefined {
return _.chain(VERSION_PATTERNS)
.map(pattern => pattern.exec(release.tag_name)?.groups?.version)
.find(version => !!version)
.value();
}
//================================================
// Asset
//================================================
interface Asset {
readonly version: Version;
readonly os: "darwin" | "linux" | "win32";
readonly arch: "arm64" | "x64";
readonly url: string;
}
const ASSET_PATTERNS: [Asset["os"], Asset["arch"], RegExp][] = [
["darwin", "arm64", /^clang\+llvm-.+-arm64-apple-(darwin|macos).*\.tar\.xz$/],
["darwin", "x64", /^clang\+llvm-.+-x86_64-apple-(darwin|macos).*\.tar\.xz$/],
["linux", "arm64", /^clang\+llvm-.+-aarch64-linux-gnu.*\.tar\.xz$/],
["linux", "x64", /^clang\+llvm-.+-x86_64-linux-gnu-?ubuntu.*\.tar\.xz$/],
["win32", "arm64", /^LLVM-.+-woa64\.exe$/],
["win32", "x64", /^LLVM-.+-win64\.exe$/],
];
function extractAssets(release: Release): Asset[] {
const version = extractVersionNumber(release);
if (!version) {
return [];
}
const assets: Asset[] = [];
for (const asset of release.assets) {
for (const [os, arch, pattern] of ASSET_PATTERNS) {
if (!/rc\d+/.test(asset.name) && pattern.test(asset.name)) {
assets.push({ version, os, arch, url: asset.browser_download_url });
}
}
}
return assets;
}
//================================================
// Generate
//================================================
function parseVersionNumber(string: string): number | null {
const match = /(\d+)\.(\d+)\.(\d+)/.exec(string);
if (match) {
const parts = match.slice(1, 4).map(p => Number.parseInt(p));
return parts[0] * 100_000_000 + parts[1] * 100_000 + parts[2];
} else {
return null;
}
}
async function generate() {
const assets = (
await github.paginate("GET /repos/{owner}/{repo}/releases", {
owner: "llvm",
repo: "llvm-project",
})
).flatMap(extractAssets);
const output: Record<string, Record<string, Record<string, string>>> = {};
for (const asset of assets) {
let os = output[asset.os] ?? (output[asset.os] = {});
let arch = os[asset.arch] ?? (os[asset.arch] = {});
arch[asset.version] = asset.url.replace(
`https://github.com/llvm/llvm-project/releases/download/llvmorg-${asset.version}`,
"",
);
}
const comparator: Comparator = (a, b) => {
const versionA = parseVersionNumber(a.key);
const versionB = parseVersionNumber(b.key);
if (versionA && versionB) {
return versionA - versionB;
} else {
return a.key.localeCompare(b.key);
}
};
const json = stringify(output, { space: " ", cmp: comparator });
writeFileSync(resolve(__dirname, "assets.json"), json);
}
generate();