Skip to content

Commit 58a59d3

Browse files
committed
feat: add module for checking basic system requirements
1 parent 9f45e74 commit 58a59d3

File tree

6 files changed

+282
-0
lines changed

6 files changed

+282
-0
lines changed

lib/system-reqs.js

+112
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/system-reqs.js.map

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node_modules/.package-lock.json

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"js-yaml": "^4.1.0",
5050
"jsonschema": "1.4.1",
5151
"long": "^5.3.1",
52+
"macos-version": "^6.0.0",
5253
"node-forge": "^1.3.1",
5354
"octokit": "^4.1.2",
5455
"path": "^0.12.7",

src/system-reqs.ts

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// Enforce system requirements for the CodeQL CLI.
2+
// https://codeql.github.com/docs/codeql-overview/system-requirements/
3+
4+
import { readFileSync } from "fs";
5+
import os from "os";
6+
7+
import { isMacOSVersionGreaterThanOrEqualTo } from "macos-version";
8+
9+
import { assertNever, ConfigurationError } from "./util";
10+
11+
const platformMap = {
12+
darwin: "macOS",
13+
linux: "Linux",
14+
win32: "Windows",
15+
};
16+
17+
const platformRequirements = {
18+
macOS: {
19+
version: ["13.0.1", "14.0.1"],
20+
arch: ["arm64", "x64"],
21+
},
22+
Linux: {
23+
// We only accept Ubuntu 20.04, 21.04, and 22.04
24+
version: ["20.04", "21.04", "22.04"],
25+
arch: ["x64"],
26+
},
27+
Windows: {
28+
version: ["10", "Server 2019", "11", "Server 2022"],
29+
arch: ["x64"],
30+
},
31+
};
32+
33+
export function passesSystemRequirements(): boolean {
34+
// CodeQL System requirements are two-level: the CLI must run on a specific platform,
35+
// and that platform must have certain capabilities.
36+
37+
const platform = getPlatform();
38+
switch (platform) {
39+
case "macOS":
40+
return checkMacOSPlatform();
41+
case "Linux":
42+
return checkLinuxPlatform();
43+
case "Windows":
44+
return checkWindowsPlatform();
45+
default:
46+
assertNever(platform);
47+
}
48+
}
49+
50+
// MacOS checks
51+
52+
function checkMacOSPlatform(): boolean {
53+
const macOSPlatformRequirements = platformRequirements["macOS"];
54+
return (
55+
checkMacOSVersion(macOSPlatformRequirements["version"]) &&
56+
checkMacOSArch(macOSPlatformRequirements["arch"])
57+
);
58+
}
59+
60+
function checkMacOSVersion(supportedVersions: string[]): boolean {
61+
return supportedVersions.some((version) => {
62+
return isMacOSVersionGreaterThanOrEqualTo(version);
63+
});
64+
}
65+
66+
function checkMacOSArch(supportedArchs: string[]): boolean {
67+
const arch = getArch();
68+
return supportedArchs.includes(arch);
69+
}
70+
71+
// Linux checks
72+
73+
function checkLinuxPlatform(): boolean {
74+
const linuxPlatformRequirements = platformRequirements["Linux"];
75+
return (
76+
checkLinuxVersion(linuxPlatformRequirements["version"]) &&
77+
checkLinuxArch(linuxPlatformRequirements["arch"])
78+
);
79+
}
80+
81+
function checkLinuxVersion(supportedVersions: string[]): boolean {
82+
const data = readFileSync("/etc/os-release", "utf8");
83+
const lines = data.split("\n");
84+
const releaseDetails: Record<string, string> = {};
85+
for (const line of lines) {
86+
const words = line.split("=");
87+
if (words.length === 2) {
88+
releaseDetails[words[0].trim().toLowerCase()] = words[1].trim();
89+
}
90+
}
91+
92+
return (
93+
releaseDetails.name === "Ubuntu" &&
94+
supportedVersions.includes(releaseDetails.version_id)
95+
);
96+
}
97+
98+
function checkLinuxArch(supportedArchs: string[]): boolean {
99+
const arch = getArch();
100+
return supportedArchs.includes(arch);
101+
}
102+
103+
// Windows checks
104+
105+
function checkWindowsPlatform(): boolean {
106+
const windowsPlatformRequirements = platformRequirements["Windows"];
107+
return (
108+
checkWindowsVersion(windowsPlatformRequirements["version"]) &&
109+
checkWindowsArch(windowsPlatformRequirements["arch"])
110+
);
111+
}
112+
113+
function checkWindowsVersion(supportedVersions: string[]): boolean {
114+
// os.release() on windows returns a string like "Windows 11 Home"
115+
const windowsVersion = os.release();
116+
return supportedVersions.some((version) =>
117+
new RegExp(version, "i").test(windowsVersion),
118+
);
119+
}
120+
121+
function checkWindowsArch(supportedArchs: string[]): boolean {
122+
const arch = getArch();
123+
return supportedArchs.includes(arch);
124+
}
125+
126+
// Auxiliary functions
127+
128+
function getPlatform(): "macOS" | "Linux" | "Windows" {
129+
const platform = process.platform;
130+
const mappedPlatform = platformMap[platform];
131+
if (mappedPlatform === undefined) {
132+
throw new ConfigurationError(`Unsupported platform: ${platform}`);
133+
}
134+
return mappedPlatform;
135+
}
136+
137+
function getArch(): string {
138+
return process.arch;
139+
}

0 commit comments

Comments
 (0)