Skip to content

Commit 6074eb3

Browse files
committed
Added the ability to launch persistent vms (which cuts down all of the npm install and VM launch times)
1 parent 69596fa commit 6074eb3

3 files changed

Lines changed: 104 additions & 9 deletions

File tree

package-lock.json

Lines changed: 4 additions & 4 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
@@ -55,7 +55,7 @@
5555
"@types/node": "^18",
5656
"@types/plist": "^3.0.5",
5757
"@types/semver": "^7.5.4",
58-
"codify-plugin-test": "0.0.53-beta14",
58+
"codify-plugin-test": "0.0.53-beta15",
5959
"commander": "^12.1.0",
6060
"eslint": "^8.51.0",
6161
"eslint-config-oclif": "^5",

scripts/run-tests.ts

Lines changed: 99 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,45 @@
1+
import { Shell, SpawnStatus, VerbosityLevel } from 'codify-plugin-lib';
2+
import { testSpawn } from 'codify-plugin-test';
13
import { Command } from 'commander';
2-
import { glob } from 'glob';
3-
import { spawn, spawnSync } from 'node:child_process';
4+
import { spawn } from 'node:child_process';
45
import * as inspector from 'node:inspector';
56
import os from 'node:os';
6-
import { OS } from 'codify-schemas';
7+
import path from 'node:path';
8+
9+
import { codifySpawn } from '../src/utils/codify-spawn';
710

811
const IP_REGEX = /VM was assigned with (.*) IP/;
912

1013
const program = new Command();
1114

1215
program
16+
.option('--launchPersistent', 'Launches a persistent VM for testing', false)
1317
.option('--operatingSystem <operatingSystem>', 'Operating system to run tests on', os.platform())
18+
.option('--persistent', 'Runs tests on a persistent VM (reuse) to skip the overhead of launching a new VM each time', false)
1419
.argument('[file]', 'File to run')
1520
.action(main)
1621
.parse()
1722

18-
async function main(argument: string, args: { operatingSystem: string }): Promise<void> {
23+
async function main(argument: string, args: { operatingSystem: string; persistent: boolean; launchPersistent: boolean }): Promise<void> {
1924
const debug = isInDebugMode();
2025
if (debug) {
2126
console.log('Running in debug mode!')
2227
}
2328

29+
if (args.launchPersistent) {
30+
await launchPersistentVm();
31+
return process.exit(0);
32+
}
33+
34+
if (args.persistent) {
35+
if (!argument) {
36+
throw new Error('No test specified for persistent mode');
37+
}
38+
39+
await launchPersistentTest(argument, debug, args.operatingSystem);
40+
return process.exit(0);
41+
}
42+
2443
if (!argument) {
2544
await launchTestAll(debug, args.operatingSystem)
2645
return process.exit(0);
@@ -49,6 +68,67 @@ async function launchSingleTest(test: string, debug: boolean, operatingSystem: s
4968
await run(`cirrus run --lazy-pull ${image} -e FILE_NAME="${test}" -o simple`, debug)
5069
}
5170

71+
async function launchPersistentTest(test: string, debug: boolean, operatingSystem: string) {
72+
if (operatingSystem === 'darwin') {
73+
const { data: vmList } = await codifySpawn('tart list --format json');
74+
console.log(vmList);
75+
76+
const parsedVmList = JSON.parse(vmList);
77+
const runningVm = parsedVmList.find(vm => vm.Name.startsWith('codify-test-vm') && vm.Running === true);
78+
if (!runningVm) {
79+
throw new Error('No persistent VM found');
80+
}
81+
82+
const vmName = runningVm.Name;
83+
const dir = '/Users/admin/codify-homebrew-plugin';
84+
85+
const debugFlag = debug ? ' -e DEBUG="--inspect-brk=9229"' : ''
86+
87+
console.log('Refreshing files on VM...');
88+
const { data: ipAddr } = await testSpawn(`tart ip ${vmName}`);
89+
await testSpawn(`tart exec ${vmName} rm -rf ${dir}/src`);
90+
await testSpawn(`tart exec ${vmName} rm -rf ${dir}/test`);
91+
await testSpawn(`sshpass -p "admin" scp -r -o PubkeyAuthentication=no -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${path.join(process.cwd(), 'test')} admin@${ipAddr}:${dir}/test`);
92+
await testSpawn(`sshpass -p "admin" scp -r -o PubkeyAuthentication=no -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${path.join(process.cwd(), 'src')} admin@${ipAddr}:${dir}/src`);
93+
94+
console.log('Done refreshing files on VM. Starting tests...');
95+
VerbosityLevel.set(3);
96+
await codifySpawn(`tart exec -i ${vmName} zsh -i -c "cd ${dir} && FORCE_COLOR=true npm run test -- ${test} --disable-console-intercept ${debugFlag} --no-file-parallelism"`);
97+
}
98+
}
99+
100+
async function launchPersistentVm() {
101+
const newVmName = `codify-test-vm-${Date.now()}`;
102+
console.log(`Cloning new VM... ${newVmName}`);
103+
104+
await testSpawn(`tart clone codify-test-vm ${newVmName}`);
105+
testSpawn(`tart run ${newVmName}`)
106+
.then(cleanupVm)
107+
108+
process.on('exit', cleanupVm);
109+
process.on('SIGINT', cleanupVm);
110+
process.on('SIGHUP', cleanupVm);
111+
process.on('SIGTERM', cleanupVm);
112+
113+
await sleep(5000);
114+
await waitUntilVmIsReady(newVmName);
115+
116+
const { data: ipAddr } = await testSpawn(`tart ip ${newVmName}`);
117+
await testSpawn(`sshpass -p "admin" rsync -avz -e 'ssh -o PubkeyAuthentication=no -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' --exclude 'node_modules' --exclude '.git' --exclude 'dist' --exclude '.fleet' ${process.cwd()} admin@${ipAddr}:~`);
118+
await testSpawn(`tart exec ${newVmName} zsh -i -c "cd ~/codify-homebrew-plugin && npm ci"`);
119+
console.log('Finished installing dependencies. Start tests in a new terminal window.');
120+
121+
await sleep(1_000_000_000);
122+
// This is effective the end just without a return
123+
124+
async function cleanupVm() {
125+
console.log('Deleting VM after...')
126+
await testSpawn(`tart delete ${newVmName}`);
127+
process.exit(0);
128+
}
129+
}
130+
131+
52132
async function run(cmd: string, debug: boolean, simple = true) {
53133
const messageBuffer: string[] = [];
54134

@@ -108,7 +188,22 @@ async function run(cmd: string, debug: boolean, simple = true) {
108188

109189
}
110190

191+
function sleep(ms: number) {
192+
return new Promise(resolve => setTimeout(resolve, ms));
193+
}
111194

112195
function isInDebugMode() {
113196
return inspector.url() !== undefined;
114197
}
198+
199+
200+
async function waitUntilVmIsReady(vmName: string): Promise<void> {
201+
while (true) {
202+
const result = await testSpawn(`tart exec ${vmName} pwd`, { interactive: true })
203+
if (result.status === SpawnStatus.SUCCESS) {
204+
return;
205+
}
206+
207+
await sleep(1000);
208+
}
209+
}

0 commit comments

Comments
 (0)