automify 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/package.json +1 -1
- package/scripts/qemu-image.js +5 -2
- package/src/lib/qemu-cli-automify.js +16 -3
package/README.md
CHANGED
|
@@ -126,6 +126,9 @@ Pre-warm or refresh QEMU image caches:
|
|
|
126
126
|
# Pre-warm the minimal QEMU CLI cache.
|
|
127
127
|
npx automify-qemu-image
|
|
128
128
|
|
|
129
|
+
# Pre-warm a QEMU CLI cache for examples that need Node.js in the VM.
|
|
130
|
+
npx automify-qemu-image --package coreutils --package nodejs
|
|
131
|
+
|
|
129
132
|
# Pre-warm the QEMU desktop cache with Xvfb/openbox/xterm/xdotool/scrot.
|
|
130
133
|
npx automify-qemu-image --desktop
|
|
131
134
|
|
|
@@ -281,7 +284,7 @@ const cli = automify.virtualCli({
|
|
|
281
284
|
memory: "2g",
|
|
282
285
|
cpus: 2
|
|
283
286
|
},
|
|
284
|
-
additionalAptPackages: ["coreutils"],
|
|
287
|
+
additionalAptPackages: ["coreutils", "nodejs"],
|
|
285
288
|
shared: { hostPath: process.cwd(), containerPath: "/workspace" }
|
|
286
289
|
});
|
|
287
290
|
|
|
@@ -779,7 +782,7 @@ RUN_OPENAI_QEMU_DESKTOP_E2E=1 \
|
|
|
779
782
|
node --test test/e2e/live-openai.e2e.test.js
|
|
780
783
|
```
|
|
781
784
|
|
|
782
|
-
Use `AUTOMIFY_QEMU_DEFAULT_IMAGE_URL` to point the default Debian download at a mirror, and `AUTOMIFY_QEMU_IMAGE_CACHE_DIR` to choose the cache directory. By default, Automify caches the downloaded Debian base image and prepared Automify-ready Debian images on the user's computer.
|
|
785
|
+
Use `AUTOMIFY_QEMU_DEFAULT_IMAGE_URL` to point the default Debian download at a mirror, and `AUTOMIFY_QEMU_IMAGE_CACHE_DIR` to choose the cache directory. By default, Automify caches the downloaded Debian base image and prepared Automify-ready Debian images on the user's computer. CLI cache variants bake the requested `packages` and `additionalAptPackages`; the desktop cache is a separate variant that bakes Xvfb/openbox/xterm/xdotool/scrot so warm desktop boots do not reinstall apt packages. Configure image caching with `defaultImageCache`, for example `defaultImageCache: { dir: "/var/cache/automify-qemu", forcePrepare: true }`. Run `npx automify-qemu-image` to pre-warm the minimal QEMU CLI cache, or add flags such as `--package coreutils --package nodejs` to pre-warm a package-specific CLI cache. Run `npx automify-qemu-image --desktop` to pre-warm the QEMU desktop cache. Run `npx automify-qemu-image --image-url https://example.com/path/linux.qcow2 --cache-dir /var/cache/automify-qemu-custom` to pre-warm an alternate cloud qcow2 cache, then use the same URL and cache directory at runtime with `vm.imageUrl` or `qemuImageUrl` plus `defaultImageCache`. Run `npx automify-qemu-image --force-download` to replace the cached base image and rebuild the prepared image. Local disks passed with `image` or `vm.image` are not prepared by the cache command; they must already be bootable with SSH access. On ARM hosts Automify auto-detects common QEMU UEFI firmware paths; set `AUTOMIFY_QEMU_FIRMWARE` if your QEMU install keeps the firmware elsewhere.
|
|
783
786
|
|
|
784
787
|
## License
|
|
785
788
|
|
package/package.json
CHANGED
package/scripts/qemu-image.js
CHANGED
|
@@ -19,6 +19,8 @@ const options = parseArgs(args);
|
|
|
19
19
|
console.log("Preparing Automify QEMU default Debian image cache.");
|
|
20
20
|
if (options.desktop) {
|
|
21
21
|
console.log("Desktop cache enabled: the prepared image will include the default QEMU desktop packages.");
|
|
22
|
+
} else if (options.packages.length > 0) {
|
|
23
|
+
console.log("CLI cache enabled: the prepared image will include the requested apt packages.");
|
|
22
24
|
} else {
|
|
23
25
|
console.log("CLI cache enabled: the prepared image will stay minimal for QEMU virtual CLI runs.");
|
|
24
26
|
}
|
|
@@ -39,7 +41,7 @@ try {
|
|
|
39
41
|
imageUrl: options.imageUrl,
|
|
40
42
|
defaultImageCache: options.defaultImageCache,
|
|
41
43
|
preparedImageProfile: options.desktop ? "desktop" : undefined,
|
|
42
|
-
preparedPackages: options.desktop ? uniquePackages([...DEFAULT_QEMU_DESKTOP_PACKAGES, ...options.packages]) :
|
|
44
|
+
preparedPackages: options.desktop ? uniquePackages([...DEFAULT_QEMU_DESKTOP_PACKAGES, ...options.packages]) : options.packages,
|
|
43
45
|
vmName: "automify-qemu-image"
|
|
44
46
|
});
|
|
45
47
|
|
|
@@ -132,7 +134,7 @@ Options:
|
|
|
132
134
|
--force-prepare Rebuild only the prepared image
|
|
133
135
|
--no-prepare Download only the base Debian qcow2
|
|
134
136
|
--desktop Prepare the QEMU desktop cache variant
|
|
135
|
-
--package <name> Add an apt package to the prepared
|
|
137
|
+
--package <name> Add an apt package to the prepared cache
|
|
136
138
|
--cache-dir <path> Cache root for base and prepared images
|
|
137
139
|
--prepared-cache-dir <path>
|
|
138
140
|
Cache directory for prepared images
|
|
@@ -143,6 +145,7 @@ Options:
|
|
|
143
145
|
|
|
144
146
|
Examples:
|
|
145
147
|
npx automify-qemu-image # pre-warm the QEMU CLI cache
|
|
148
|
+
npx automify-qemu-image --package coreutils --package nodejs
|
|
146
149
|
npx automify-qemu-image --desktop # pre-warm the QEMU desktop cache
|
|
147
150
|
npx automify-qemu-image --force-download
|
|
148
151
|
npx automify-qemu-image --cache-dir ${root}/.automify-qemu-cache
|
|
@@ -34,6 +34,7 @@ const execFileAsync = promisify(execFile);
|
|
|
34
34
|
|
|
35
35
|
const DEFAULT_CWD = "/workspace";
|
|
36
36
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
37
|
+
const DEFAULT_STARTUP_TIMEOUT_MS = 120_000;
|
|
37
38
|
const VIRTUAL_CLI_OPTION_KEYS = mergeOptionKeys(AUTOMIFY_OPTION_KEYS, [
|
|
38
39
|
"preset",
|
|
39
40
|
"command",
|
|
@@ -195,6 +196,7 @@ export class QemuCliSession {
|
|
|
195
196
|
this.originalSshKeyPath = options.sshKeyPath;
|
|
196
197
|
this.originalSudo = options.sudo;
|
|
197
198
|
this.defaultImage = null;
|
|
199
|
+
this.preparedPackages = new Set();
|
|
198
200
|
this.usesDefaultImage = !this.image && !options.existingVM;
|
|
199
201
|
this.name = options.vmName ?? `automify-vm-cli-${randomUUID()}`;
|
|
200
202
|
this.cwd = normalizeGuestPath(options.cwd, DEFAULT_CWD);
|
|
@@ -251,7 +253,7 @@ export class QemuCliSession {
|
|
|
251
253
|
this.started = true;
|
|
252
254
|
await waitForSsh(this.execFile, this.sshCommand, this.sshOptions());
|
|
253
255
|
await this.runSsh(this.startupScript(), {
|
|
254
|
-
timeout:
|
|
256
|
+
timeout: this.startupTimeoutMs()
|
|
255
257
|
});
|
|
256
258
|
debugVirtualCli(this.options, "vm_ready", { vmName: this.name });
|
|
257
259
|
} catch (error) {
|
|
@@ -288,13 +290,15 @@ export class QemuCliSession {
|
|
|
288
290
|
sshPort: this.sshPort,
|
|
289
291
|
sshTimeoutMs: this.options.sshTimeoutMs,
|
|
290
292
|
startupTimeoutMs: this.options.startupTimeoutMs,
|
|
291
|
-
timeoutMs: this.
|
|
293
|
+
timeoutMs: this.startupTimeoutMs(),
|
|
292
294
|
qemuTimeoutMs: this.options.qemuTimeoutMs,
|
|
293
295
|
createCloudInitServer: this.options.createCloudInitServer,
|
|
296
|
+
preparedPackages: this.options.installDependencies === false ? [] : this.dependencyPackages(),
|
|
294
297
|
spawn: this.spawn,
|
|
295
298
|
vmName: this.name
|
|
296
299
|
});
|
|
297
300
|
this.defaultImage = prepared;
|
|
301
|
+
this.preparedPackages = new Set(prepared.preparedPackages ?? []);
|
|
298
302
|
this.image = prepared.image;
|
|
299
303
|
this.options = {
|
|
300
304
|
...this.options,
|
|
@@ -313,7 +317,7 @@ export class QemuCliSession {
|
|
|
313
317
|
}
|
|
314
318
|
|
|
315
319
|
startupScript() {
|
|
316
|
-
const packages =
|
|
320
|
+
const packages = this.dependencyPackages().filter((pkg) => !this.preparedPackages.has(pkg));
|
|
317
321
|
const startupCommand = this.options.startupCommand ?? ":";
|
|
318
322
|
return [
|
|
319
323
|
installCommand(packages, this.options),
|
|
@@ -323,6 +327,14 @@ export class QemuCliSession {
|
|
|
323
327
|
].join(" && ");
|
|
324
328
|
}
|
|
325
329
|
|
|
330
|
+
dependencyPackages() {
|
|
331
|
+
return uniquePackages([...(this.options.packages ?? []), ...(this.options.additionalAptPackages ?? [])]);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
startupTimeoutMs() {
|
|
335
|
+
return positiveInteger(this.options.startupTimeoutMs) ?? DEFAULT_STARTUP_TIMEOUT_MS;
|
|
336
|
+
}
|
|
337
|
+
|
|
326
338
|
async run(command, options = {}) {
|
|
327
339
|
await this.start();
|
|
328
340
|
const cwd = normalizeGuestPath(options.cwd ?? this.cwd, this.cwd);
|
|
@@ -385,6 +397,7 @@ export class QemuCliSession {
|
|
|
385
397
|
}
|
|
386
398
|
await this.defaultImage?.close();
|
|
387
399
|
this.defaultImage = null;
|
|
400
|
+
this.preparedPackages = new Set();
|
|
388
401
|
if (this.usesDefaultImage) {
|
|
389
402
|
this.image = null;
|
|
390
403
|
this.options = {
|