-
Notifications
You must be signed in to change notification settings - Fork 16
/
index.js
123 lines (121 loc) · 5.6 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
import console from "../modules/console.js";
console.info("Initialization done.");
import createCommit from "../modules/createCommit.js";
import yamlModule from "../modules/yamlModule.js";
import fs from "node:fs";
import path from "node:path";
import { startGroup, endGroup, exportVariable } from "@actions/core";
import { createIssue } from "../modules/octokit.js";
import modulePath from "../modules/modulePath.js";
import semver from "semver";
import fetchNPMPackageInfo from "../modules/fetchNPMPackageInfo.js";
const labels = ["ci:prefetch"];
const prefetchTargetsPath = "scripts/prefetch/targets.yaml";
/**
* @typedef { { gadget: { name: string, fileName: string }, appendCode?: string, removeCode?: string[] } } prefetchTargetBase
*/
/**
* @typedef { prefetchTargetBase & { type: "npm", moduleName: string, distFilePath: string, version?: string, ignoreSemverDiff?: semver.ReleaseType[] } } prefetchTargetFromNPM
*/
/**
* @typedef { prefetchTargetBase & { type: "custom", url: string } } prefetchTargetFromCustom
*/
/**
* @type {(prefetchTargetFromNPM | prefetchTargetFromCustom)[]}
*/
const prefetchTargets = await yamlModule.readFile(prefetchTargetsPath);
startGroup("prefetchTargets:");
console.info(prefetchTargets);
endGroup();
const fileList = [];
for (const prefetchTarget of prefetchTargets) {
console.info("target:", prefetchTarget);
const { type, moduleName, gadget: { name, fileName }, distFilePath, appendCode, removeCode = [], ignoreSemverDiff, url } = prefetchTarget;
let { version } = prefetchTarget;
const file = path.join("src/gadgets", name, fileName);
fileList.push(file);
console.info(`[${name}]`, "Start to fetch...");
const data = await (async () => {
if (type === "npm") {
const packageName = `${moduleName}${typeof version === "string" ? `@${version}` : ""}`;
const filePath = path.posix.join("npm", packageName, distFilePath);
const url = new URL(filePath, "https://cdn.jsdelivr.net/");
console.info(`[${name}]`, `url: ${url}`);
prefetchTarget.jsdelivrUrl = url;
const response = await fetch(url, {
method: "GET",
});
return await response.text();
}
if (type === "custom") {
console.info(`[${name}]`, `url: ${url}`);
const response = await fetch(url, {
method: "GET",
});
return await response.text();
}
})();
if (data.startsWith("Couldn't find the requested file")) {
throw new Error(`[${name}] Couldn't find the requested file.`);
}
console.info(`[${name}]`, "Successfully fetched.");
const code = [
"/**",
` * Generated by ${modulePath(import.meta)}`,
" * Options:",
];
for (const [k, v] of Object.entries(prefetchTarget)) {
code.push(` * ${k}: ${JSON.stringify(v, null, 1).replace(/\n */g, " ")}`);
}
code.push(" */", removeCode.reduce((p, c) => p.replaceAll(c, ""), data.replace(/(?<=\n)\/\/\/ *<reference [^\n]+\n?/ig, "")));
if (typeof appendCode === "string") {
code.push(appendCode);
}
code.push("");
if (await fs.promises.readFile(file, { encoding: "utf-8" }).catch(() => null) === code.join("\n")) {
console.info(`[${name}]`, "Nothing changed, continue.");
continue;
}
const folder = path.dirname(file);
const filename = path.basename(file);
const eslintrcName = path.join(folder, ".eslintrc.yaml");
await fs.promises.mkdir(folder, {
recursive: true,
});
await fs.promises.writeFile(file, code.join("\n"));
if (path.extname(file) === ".js") {
const eslintrc = await yamlModule.readFile(eslintrcName).catch(() => ({}));
if (!Array.isArray(eslintrc.ignorePatterns)) {
eslintrc.ignorePatterns = [];
}
if (!eslintrc.ignorePatterns.includes(filename)) {
eslintrc.ignorePatterns.push(filename);
await yamlModule.writeFile(eslintrcName, eslintrc);
}
}
console.info(`[${name}]`, "wrote the code file and eslintrc successfully.");
if (type === "npm") {
const packageInfo = await fetchNPMPackageInfo(moduleName);
if (Object.hasOwn(packageInfo["dist-tags"], version)) {
version = packageInfo["dist-tags"][version];
}
const distVersions = Object.keys(packageInfo.versions);
console.info(`[${name}]`, "distVersions:", distVersions);
const targetVersion = semver.maxSatisfying(distVersions, version || "*");
console.info(`[${name}]`, "targetVersion:", targetVersion);
await createCommit(`auto(Gadget-${name}): bump ${moduleName} to ${targetVersion} by prefetch`);
if (packageInfo["dist-tags"].latest !== targetVersion) {
const releaseType = semver.diff(packageInfo["dist-tags"].latest, targetVersion);
if (!Array.isArray(ignoreSemverDiff) || !ignoreSemverDiff.includes(releaseType)) {
await createIssue(
`[prefetch] Found new ${releaseType} verion of ${moduleName}`,
`Found new ${releaseType} verion of ${moduleName} that is higher than \`${targetVersion}\`, while [\`${prefetchTargetsPath}\`](${prefetchTargetsPath}) configured as \`${moduleName}@${version || "*"}\`, please consider to upgrade it: ${new URL(path.posix.join("package", name), "https://www.npmjs.com/")}`,
labels,
`New ${releaseType} verion: \`${moduleName}@${packageInfo["dist-tags"].latest}\``,
);
}
}
}
}
exportVariable("linguist-generated-prefetch", JSON.stringify(fileList));
console.info("Done.");