Skip to content

Commit 4ba1847

Browse files
authored
improve sanity testing (#43)
1 parent 81a28f1 commit 4ba1847

File tree

4 files changed

+136
-61
lines changed

4 files changed

+136
-61
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vscode/vscode-bisect",
3-
"version": "1.0.8",
3+
"version": "1.0.9",
44
"description": "Bisect released VS Code builds to find bugs or performance issues similar to what git bisect supports.",
55
"repository": {
66
"type": "git",

src/launcher.ts

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { mkdirSync, rmSync } from 'node:fs';
77
import clipboard from 'clipboardy';
88
import { ChildProcessWithoutNullStreams, spawn } from 'node:child_process';
9+
import { homedir } from 'node:os';
910
import { basename, join } from 'node:path';
1011
import { URL } from 'node:url';
1112
import { URI } from 'vscode-uri';
@@ -96,7 +97,7 @@ class Launcher {
9697

9798
if (path && (build.flavor === Flavor.WindowsUserInstaller || build.flavor === Flavor.WindowsSystemInstaller)) {
9899
LOGGER.log(`${chalk.gray('[build]')} installing ${chalk.green(path)}...`);
99-
return this.runWindowsDesktopInstaller(path);
100+
return this.runWindowsDesktopInstaller(build.flavor, build.quality, path);
100101
}
101102

102103
if (isDockerCliFlavor(build.flavor)) {
@@ -174,16 +175,50 @@ class Launcher {
174175
}
175176
}
176177

177-
private runWindowsDesktopInstaller(path: string): IInstance {
178+
private runWindowsDesktopInstaller(flavor: Flavor.WindowsUserInstaller | Flavor.WindowsSystemInstaller, quality: Quality, path: string): IInstance {
178179
const cp = spawn(path, ['/silent']);
179180

181+
const windowsExecutablePath = `"${this.getWindowsVSCodeExecutablePath(flavor, quality)}"`;
182+
this.safeWriteClipboardSync(windowsExecutablePath);
183+
184+
console.log(`${chalk.gray('[build]')} Setup is running and will launch the build. If that is not the case, please open a new terminal, and run ${chalk.green(windowsExecutablePath)} (added to clipboard) to start.`);
185+
180186
return {
181187
async stop() {
182188
cp.kill();
183189
}
184190
}
185191
}
186192

193+
private getWindowsVSCodeExecutablePath(flavor: Flavor.WindowsUserInstaller | Flavor.WindowsSystemInstaller, quality: Quality): string {
194+
const isUserInstaller = flavor === Flavor.WindowsUserInstaller;
195+
const isInsiders = quality === Quality.Insider;
196+
197+
// Determine base directory
198+
let baseDir: string;
199+
if (isUserInstaller) {
200+
// User installer installs to %LOCALAPPDATA%\Programs
201+
const localAppData = process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local');
202+
baseDir = join(localAppData, 'Programs');
203+
} else {
204+
// System installer installs to %PROGRAMFILES%
205+
const programFiles = process.env['PROGRAMFILES'] || 'C:\\Program Files';
206+
baseDir = programFiles;
207+
}
208+
209+
let appFolder: string;
210+
let executableName: string;
211+
if (isInsiders) {
212+
appFolder = 'Microsoft VS Code Insiders';
213+
executableName = 'code-insiders.cmd';
214+
} else {
215+
appFolder = 'Microsoft VS Code';
216+
executableName = 'code.cmd';
217+
}
218+
219+
return join(baseDir, appFolder, 'bin', executableName);
220+
}
221+
187222
private async runDesktopPerformance(build: IBuild): Promise<IInstance> {
188223
const executable = await this.getExecutablePath(build);
189224

@@ -240,24 +275,9 @@ class Launcher {
240275
private async launchLocalWebServer(build: IBuild): Promise<IWebInstance> {
241276
const cp = await this.spawnBuild(build);
242277

243-
async function stop() {
244-
return new Promise<void>((resolve, reject) => {
245-
const pid = cp.pid!;
246-
kill(pid, error => {
247-
if (error) {
248-
try {
249-
process.kill(pid, 0);
250-
} catch (error) {
251-
resolve(); // process doesn't exist anymore... so, all good
252-
return;
253-
}
254-
255-
reject(error);
256-
} else {
257-
resolve();
258-
}
259-
});
260-
});
278+
const that = this;
279+
function stop() {
280+
return that.treeKill(cp.pid!);
261281
}
262282

263283
return new Promise<IWebInstance>(resolve => {
@@ -277,6 +297,25 @@ class Launcher {
277297
});
278298
}
279299

300+
private treeKill(pid: number): Promise<void> {
301+
return new Promise((resolve, reject) => {
302+
kill(pid, error => {
303+
if (error) {
304+
try {
305+
process.kill(pid, 0);
306+
} catch (error) {
307+
resolve(); // process doesn't exist anymore... so, all good
308+
return;
309+
}
310+
311+
reject(error);
312+
} else {
313+
resolve();
314+
}
315+
});
316+
});
317+
}
318+
280319
private async launchRemoteWeb(build: IBuild): Promise<IInstance> {
281320
open(VSCODE_DEV_URL(build.commit, build.quality));
282321

@@ -286,8 +325,13 @@ class Launcher {
286325
private async launchElectronOrCLI(build: IBuild): Promise<IInstance> {
287326
const cp = await this.spawnBuild(build);
288327

328+
const that = this;
289329
async function stop() {
290-
cp.kill();
330+
if (build.flavor === Flavor.Cli) {
331+
return that.treeKill(cp.pid!)
332+
} else {
333+
return cp.kill();
334+
}
291335
}
292336

293337
return new Promise<IInstance>(resolve => {

src/sanity.ts

Lines changed: 68 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,48 +13,63 @@ import { launcher } from "./launcher.js";
1313
class Sanity {
1414

1515
async testAllFlavors(commit: string): Promise<void> {
16+
this.logWelcome();
17+
1618
const quality = Quality.Stable;
1719
const runtime = Runtime.DesktopLocal;
1820

19-
const buildKinds: (IBuild & { label: string })[] = [
20-
{
21-
commit, quality, runtime, flavor: Flavor.Default, label: (() => {
22-
switch (platform) {
23-
case Platform.MacOSArm:
24-
case Platform.MacOSX64:
25-
return `macOS (${arch})`;
26-
case Platform.LinuxArm:
27-
case Platform.LinuxX64:
28-
return `Linux (${arch})`;
29-
case Platform.WindowsArm:
30-
case Platform.WindowsX64:
31-
return `Windows (${arch})`;
21+
const useDocker = await this.promptUserForDocker();
22+
23+
let buildKinds: (IBuild & { label: string })[] = [];
24+
if (useDocker) {
25+
buildKinds = [
26+
{ commit, quality, runtime, flavor: Flavor.CliLinuxAmd64, label: 'Server & CLI (AMD64)' },
27+
{ commit, quality, runtime, flavor: Flavor.CliLinuxArm64, label: 'Server & CLI (ARM64)' },
28+
{ commit, quality, runtime, flavor: Flavor.CliLinuxArmv7, label: 'Server & CLI (ARMv7)' },
29+
{ commit, quality, runtime, flavor: Flavor.CliAlpineAmd64, label: 'Server & CLI (Alpine AMD64)' },
30+
{ commit, quality, runtime, flavor: Flavor.CliAlpineArm64, label: 'Server & CLI (Alpine ARM64)' },
31+
]
32+
} else {
33+
buildKinds = [
34+
{
35+
commit, quality, runtime, flavor: Flavor.Default, label: (() => {
36+
switch (platform) {
37+
case Platform.MacOSArm:
38+
case Platform.MacOSX64:
39+
return `macOS (${arch})`;
40+
case Platform.LinuxArm:
41+
case Platform.LinuxX64:
42+
return `Linux (${arch})`;
43+
case Platform.WindowsArm:
44+
case Platform.WindowsX64:
45+
return `Windows (${arch})`;
46+
}
47+
})()
48+
},
49+
];
50+
51+
switch (platform) {
52+
case Platform.MacOSArm:
53+
case Platform.MacOSX64:
54+
buildKinds.push({ commit, quality, runtime, flavor: Flavor.DarwinUniversal, label: 'macOS (universal)' });
55+
break;
56+
case Platform.LinuxArm:
57+
case Platform.LinuxX64:
58+
buildKinds.push({ commit, quality, runtime, flavor: Flavor.LinuxDeb, label: `Linux (Debian)` });
59+
buildKinds.push({ commit, quality, runtime, flavor: Flavor.LinuxRPM, label: `Linux (RPM)` });
60+
if (arch === Arch.X64) {
61+
buildKinds.push({ commit, quality, runtime, flavor: Flavor.LinuxSnap, label: `Linux (Snap)` });
3262
}
33-
})()
34-
},
35-
];
36-
switch (platform) {
37-
case Platform.MacOSArm:
38-
case Platform.MacOSX64:
39-
buildKinds.push({ commit, quality, runtime, flavor: Flavor.DarwinUniversal, label: 'macOS (universal)' });
40-
break;
41-
case Platform.LinuxArm:
42-
case Platform.LinuxX64:
43-
buildKinds.push({ commit, quality, runtime, flavor: Flavor.LinuxDeb, label: `Linux (Debian)` });
44-
buildKinds.push({ commit, quality, runtime, flavor: Flavor.LinuxRPM, label: `Linux (RPM)` });
45-
if (arch === Arch.X64) {
46-
buildKinds.push({ commit, quality, runtime, flavor: Flavor.LinuxSnap, label: `Linux (Snap)` });
47-
}
48-
break;
49-
case Platform.WindowsArm:
50-
case Platform.WindowsX64:
51-
buildKinds.push({ commit, quality, runtime, flavor: Flavor.WindowsUserInstaller, label: `Windows User Installer (${arch})` });
52-
buildKinds.push({ commit, quality, runtime, flavor: Flavor.WindowsSystemInstaller, label: `Windows System Installer (${arch})` });
53-
break;
54-
}
55-
buildKinds.push({ commit, quality, runtime, flavor: Flavor.Cli, label: 'Server & CLI' });
63+
break;
64+
case Platform.WindowsArm:
65+
case Platform.WindowsX64:
66+
buildKinds.push({ commit, quality, runtime, flavor: Flavor.WindowsUserInstaller, label: `Windows User Installer (${arch})` });
67+
buildKinds.push({ commit, quality, runtime, flavor: Flavor.WindowsSystemInstaller, label: `Windows System Installer (${arch})` });
68+
break;
69+
}
5670

57-
this.logWelcome();
71+
buildKinds.push({ commit, quality, runtime, flavor: Flavor.Cli, label: 'Server & CLI' });
72+
}
5873

5974
for (let i = 0; i < buildKinds.length; i++) {
6075
const build = buildKinds[i];
@@ -66,6 +81,22 @@ class Sanity {
6681
}
6782
}
6883

84+
private async promptUserForDocker() {
85+
const response = await prompts([
86+
{
87+
type: 'select',
88+
name: 'useDocker',
89+
message: 'Are you assigned to sanity test builds locally or the server/CLI via docker on all supported Linux architectures?',
90+
choices: [
91+
{ title: 'Run builds locally', value: false },
92+
{ title: 'Run server/CLI via Docker (must be running)', value: true }
93+
]
94+
}
95+
]);
96+
97+
return response.useDocker;
98+
}
99+
69100
async tryBuild(build: IBuild, options: { forceReDownload: boolean, label: string, isLast: boolean }): Promise<boolean /* continue */> {
70101
try {
71102
const instance = await launcher.launch(build, options);

0 commit comments

Comments
 (0)