Skip to content

Commit 3d925ba

Browse files
authored
Merge pull request #4549 from github/cklin/electron-ver-from-npm
Read VS Code Electron version from .npmrc
2 parents ae711e4 + a1b7714 commit 3d925ba

3 files changed

Lines changed: 154 additions & 12 deletions

File tree

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1-
export async function fetchJson<T>(url: string): Promise<T> {
1+
async function fetchResponse(url: string): Promise<Response> {
22
const response = await fetch(url);
33
if (!response.ok) {
44
throw new Error(
55
`Could not fetch ${url}: ${response.status} ${response.statusText}`,
66
);
77
}
88

9+
return response;
10+
}
11+
12+
export async function fetchJson<T>(url: string): Promise<T> {
13+
const response = await fetchResponse(url);
914
return (await response.json()) as T;
1015
}
16+
17+
export async function fetchText(url: string): Promise<string> {
18+
const response = await fetchResponse(url);
19+
return await response.text();
20+
}

‎extensions/ql-vscode/scripts/util/vscode-versions.ts‎

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { minVersion } from "semver";
2-
import { fetchJson } from "./fetch";
1+
import { minVersion, valid } from "semver";
2+
import { fetchJson, fetchText } from "./fetch";
33

44
type VsCodePackageJson = {
5-
devDependencies: {
6-
electron: string;
5+
devDependencies?: {
6+
electron?: string;
77
};
88
};
99

@@ -15,6 +15,40 @@ async function getVsCodePackageJson(
1515
);
1616
}
1717

18+
async function getVsCodeNpmrc(version: string): Promise<string> {
19+
return await fetchText(
20+
`https://raw.githubusercontent.com/microsoft/vscode/${version}/.npmrc`,
21+
);
22+
}
23+
24+
export function parseElectronVersion(npmrc: string): string {
25+
const electronVersion = /^target="([^"]+)"$/m.exec(npmrc)?.[1];
26+
if (!electronVersion || !valid(electronVersion)) {
27+
throw new Error(
28+
"Could not find a valid Electron version in VS Code .npmrc",
29+
);
30+
}
31+
32+
return electronVersion;
33+
}
34+
35+
async function getVsCodeElectronVersion(version: string): Promise<string> {
36+
const packageJson = await getVsCodePackageJson(version);
37+
const packageElectronVersion = packageJson.devDependencies?.electron;
38+
if (packageElectronVersion) {
39+
const electronVersion = minVersion(packageElectronVersion)?.version;
40+
if (!electronVersion) {
41+
throw new Error(
42+
"Could not find a valid Electron version in VS Code package.json",
43+
);
44+
}
45+
46+
return electronVersion;
47+
}
48+
49+
return parseElectronVersion(await getVsCodeNpmrc(version));
50+
}
51+
1852
interface ElectronVersion {
1953
version: string;
2054
date: string;
@@ -44,13 +78,7 @@ type VersionInformation = {
4478
export async function getVersionInformation(
4579
vscodeVersion: string,
4680
): Promise<VersionInformation> {
47-
const vsCodePackageJson = await getVsCodePackageJson(vscodeVersion);
48-
const electronVersion = minVersion(
49-
vsCodePackageJson.devDependencies.electron,
50-
)?.version;
51-
if (!electronVersion) {
52-
throw new Error("Could not find Electron version");
53-
}
81+
const electronVersion = await getVsCodeElectronVersion(vscodeVersion);
5482

5583
const electronReleases = await getElectronReleases();
5684

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import {
2+
getVersionInformation,
3+
parseElectronVersion,
4+
} from "../../../../scripts/util/vscode-versions";
5+
6+
const electronReleases = [
7+
{
8+
version: "29.4.0",
9+
node: "20.9.0",
10+
chrome: "122.0.6261.156",
11+
},
12+
{
13+
version: "42.10.0",
14+
node: "24.18.1",
15+
chrome: "148.0.7778.280",
16+
},
17+
];
18+
19+
function mockFetch(
20+
responses: Record<string, unknown>,
21+
): jest.SpiedFunction<typeof fetch> {
22+
return jest.spyOn(globalThis, "fetch").mockImplementation(async (input) => {
23+
const url = input.toString();
24+
const response = responses[url];
25+
if (response === undefined) {
26+
throw new Error(`Unexpected URL: ${url}`);
27+
}
28+
29+
return {
30+
ok: true,
31+
json: async () => response,
32+
text: async () => response,
33+
} as Response;
34+
});
35+
}
36+
37+
afterEach(() => {
38+
jest.restoreAllMocks();
39+
});
40+
41+
describe("parseElectronVersion", () => {
42+
it("parses the Electron target from a VS Code .npmrc", () => {
43+
expect(
44+
parseElectronVersion(
45+
['target="42.10.0"', 'runtime="electron"', "disturl=example"].join(
46+
"\n",
47+
),
48+
),
49+
).toBe("42.10.0");
50+
});
51+
52+
it.each([
53+
["a missing target", 'runtime="electron"'],
54+
["an invalid target", 'target="not-a-version"'],
55+
["an unquoted target", "target=42.10.0"],
56+
])("rejects %s", (_description, npmrc) => {
57+
expect(() => parseElectronVersion(npmrc)).toThrow(
58+
"Could not find a valid Electron version in VS Code .npmrc",
59+
);
60+
});
61+
});
62+
63+
describe("getVersionInformation", () => {
64+
it("reads Electron from package.json for older VS Code releases", async () => {
65+
const fetchMock = mockFetch({
66+
"https://raw.githubusercontent.com/microsoft/vscode/1.90.0/package.json":
67+
{
68+
devDependencies: {
69+
electron: "29.4.0",
70+
},
71+
},
72+
"https://releases.electronjs.org/releases.json": electronReleases,
73+
});
74+
75+
await expect(getVersionInformation("1.90.0")).resolves.toEqual({
76+
vscodeVersion: "1.90.0",
77+
electronVersion: "29.4.0",
78+
nodeVersion: "20.9.0",
79+
chromiumVersion: "122.0.6261.156",
80+
});
81+
expect(fetchMock).not.toHaveBeenCalledWith(
82+
"https://raw.githubusercontent.com/microsoft/vscode/1.90.0/.npmrc",
83+
);
84+
});
85+
86+
it("falls back to .npmrc for newer VS Code releases", async () => {
87+
mockFetch({
88+
"https://raw.githubusercontent.com/microsoft/vscode/1.137.0/package.json":
89+
{
90+
devDependencies: {},
91+
},
92+
"https://raw.githubusercontent.com/microsoft/vscode/1.137.0/.npmrc":
93+
'target="42.10.0"\nruntime="electron"\n',
94+
"https://releases.electronjs.org/releases.json": electronReleases,
95+
});
96+
97+
await expect(getVersionInformation("1.137.0")).resolves.toEqual({
98+
vscodeVersion: "1.137.0",
99+
electronVersion: "42.10.0",
100+
nodeVersion: "24.18.1",
101+
chromiumVersion: "148.0.7778.280",
102+
});
103+
});
104+
});

0 commit comments

Comments
 (0)