forked from KelvinTegelaar/CIPP-API
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidate-json.mjs
More file actions
73 lines (65 loc) · 2.25 KB
/
Copy pathvalidate-json.mjs
File metadata and controls
73 lines (65 loc) · 2.25 KB
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
import { readFile, readdir, writeFile, appendFile } from "node:fs/promises";
import path from "node:path";
// Usage: node validate-json.mjs [--strip <prefix>] <dir> [dir...]
// --strip removes a leading path prefix from reported filenames, so a PR checked
// out into a subdirectory still reports repo-relative paths.
const argv = process.argv.slice(2);
let strip = "";
const roots = [];
for (let i = 0; i < argv.length; i++) {
if (argv[i] === "--strip") {
strip = argv[++i] ?? "";
} else {
roots.push(argv[i]);
}
}
async function collect(dir) {
let entries;
try {
entries = await readdir(dir, { withFileTypes: true });
} catch (error) {
if (error.code === "ENOENT") return [];
throw error;
}
const files = [];
for (const entry of entries) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) {
if (entry.name === "node_modules") continue;
files.push(...(await collect(full)));
} else if (entry.name.endsWith(".json")) {
files.push(full);
}
}
return files;
}
const report = (file) => {
const normalised = file.split(path.sep).join("/");
return strip && normalised.startsWith(strip) ? normalised.slice(strip.length) : normalised;
};
const failures = [];
let checked = 0;
for (const root of roots) {
for (const file of await collect(root)) {
checked++;
// Strip a leading UTF-8 BOM: it's tolerated by PowerShell's ConvertFrom-Json
// (how the API loads these files) but rejected by Node's JSON.parse.
const contents = (await readFile(file, "utf8")).replace(/^\uFEFF/, "");
try {
JSON.parse(contents);
} catch (error) {
failures.push({ file: report(file), message: error.message.replace(/\r?\n/g, " ") });
}
}
}
for (const { file, message } of failures) {
// Annotate the PR diff via a GitHub Actions error command.
console.log(`::error file=${file}::${message}`);
}
console.log(`Checked ${checked} JSON file(s), ${failures.length} invalid.`);
// Hand the results to the workflow so it can comment on the PR.
if (process.env.GITHUB_OUTPUT) {
await appendFile(process.env.GITHUB_OUTPUT, `invalid_count=${failures.length}\n`);
}
await writeFile("json-validation-results.json", JSON.stringify(failures, null, 2));
process.exit(failures.length > 0 ? 1 : 0);