@vellumai/cli 0.10.10 → 0.10.11-dev.202607212222.fe33210
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/package.json +1 -1
- package/src/__tests__/clean.test.ts +10 -0
- package/src/__tests__/nginx-ingress.test.ts +8 -1
- package/src/__tests__/preload.ts +9 -2
- package/src/__tests__/retire-local.test.ts +21 -1
- package/src/__tests__/sleep.test.ts +8 -0
- package/src/__tests__/teleport.test.ts +16 -0
- package/src/lib/__tests__/local-ces.test.ts +18 -0
- package/src/lib/environments/__tests__/paths.test.ts +16 -1
- package/src/lib/local.ts +3 -4
- package/src/shared/provider-env-vars.ts +1 -0
package/package.json
CHANGED
|
@@ -19,6 +19,13 @@ const stopProcessMock = mock(
|
|
|
19
19
|
async (_pid: number, _label: string): Promise<boolean> => true,
|
|
20
20
|
);
|
|
21
21
|
|
|
22
|
+
// Snapshot the real modules so the afterAll below can restore them. Bun runs
|
|
23
|
+
// every test file in one process with a shared loader, and `mock.restore()`
|
|
24
|
+
// does not undo `mock.module()`; without restoring, these mocks (notably the
|
|
25
|
+
// partial `process.js` mock) leak into sibling test files.
|
|
26
|
+
const realOrphanDetection = { ...(await import("../lib/orphan-detection.js")) };
|
|
27
|
+
const realProcess = { ...(await import("../lib/process.js")) };
|
|
28
|
+
|
|
22
29
|
beforeAll(() => {
|
|
23
30
|
mock.module("../lib/orphan-detection.js", () => ({
|
|
24
31
|
detectOrphanedProcesses: detectOrphansMock,
|
|
@@ -65,6 +72,9 @@ afterEach(() => {
|
|
|
65
72
|
|
|
66
73
|
afterAll(() => {
|
|
67
74
|
process.argv = [...originalArgv];
|
|
75
|
+
// Restore the real modules so the mocks do not leak into sibling test files.
|
|
76
|
+
mock.module("../lib/orphan-detection.js", () => realOrphanDetection);
|
|
77
|
+
mock.module("../lib/process.js", () => realProcess);
|
|
68
78
|
});
|
|
69
79
|
|
|
70
80
|
// ── Tests ─────────────────────────────────────────────────────────────────────
|
|
@@ -10,8 +10,9 @@ import {
|
|
|
10
10
|
import { tmpdir } from "node:os";
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
|
|
13
|
-
import { afterEach, describe, expect, mock, test } from "bun:test";
|
|
13
|
+
import { afterAll, afterEach, describe, expect, mock, test } from "bun:test";
|
|
14
14
|
|
|
15
|
+
const realChildProcess = { ...childProcess };
|
|
15
16
|
const execFileSyncMock = mock(childProcess.execFileSync);
|
|
16
17
|
|
|
17
18
|
mock.module("node:child_process", () => ({
|
|
@@ -19,6 +20,12 @@ mock.module("node:child_process", () => ({
|
|
|
19
20
|
execFileSync: execFileSyncMock,
|
|
20
21
|
}));
|
|
21
22
|
|
|
23
|
+
// Restore the real module once this file finishes so the mock does not leak
|
|
24
|
+
// into sibling test files in the same `bun test` run.
|
|
25
|
+
afterAll(() => {
|
|
26
|
+
mock.module("node:child_process", () => realChildProcess);
|
|
27
|
+
});
|
|
28
|
+
|
|
22
29
|
import {
|
|
23
30
|
buildIngressNginxConfig,
|
|
24
31
|
buildRemoteWebIndexHtml,
|
package/src/__tests__/preload.ts
CHANGED
|
@@ -25,7 +25,14 @@ afterAll(() => {
|
|
|
25
25
|
/* best-effort cleanup */
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
//
|
|
29
|
-
//
|
|
28
|
+
// Restore spies created via spyOn()/mock() at the end of the run.
|
|
29
|
+
//
|
|
30
|
+
// NOTE: this does NOT prevent inter-file leaks of `mock.module()`. This
|
|
31
|
+
// `afterAll` runs once, after ALL files complete (a preload's afterAll wraps
|
|
32
|
+
// the whole run, not each file), and `mock.restore()` does not undo
|
|
33
|
+
// `mock.module()` registrations anyway. A file that calls `mock.module()`
|
|
34
|
+
// must restore the real module itself in its own `afterAll` by re-registering
|
|
35
|
+
// the captured real exports (see e.g. teleport.test.ts / recover.test.ts),
|
|
36
|
+
// otherwise the mock leaks into whichever file Bun runs next.
|
|
30
37
|
mock.restore();
|
|
31
38
|
});
|
|
@@ -17,10 +17,22 @@ import type { AssistantEntry } from "../lib/assistant-config.js";
|
|
|
17
17
|
const testDir = mkdtempSync(join(tmpdir(), "retire-local-test-"));
|
|
18
18
|
const originalLockfileDir = process.env.VELLUM_LOCKFILE_DIR;
|
|
19
19
|
|
|
20
|
+
// Snapshot the real modules before mocking so the module-scoped `afterAll`
|
|
21
|
+
// below can restore them. Bun runs every test file in one process with a
|
|
22
|
+
// shared loader, and `mock.restore()` does not undo `mock.module()`. Without
|
|
23
|
+
// restoring, the `retire-archive.js` mock in particular leaks its hardcoded
|
|
24
|
+
// `test-assistant.*` paths into sibling files (e.g. `recover.test.ts`), which
|
|
25
|
+
// then fail to find their own archives.
|
|
26
|
+
const realProcess = { ...(await import("../lib/process.js")) };
|
|
27
|
+
const realNginxIngress = { ...(await import("../lib/nginx-ingress.js")) };
|
|
28
|
+
const realRetireArchive = { ...(await import("../lib/retire-archive.js")) };
|
|
29
|
+
|
|
20
30
|
const stopProcessByPidFileMock = mock(
|
|
21
31
|
async (_pidFile: string, _label: string): Promise<boolean> => true,
|
|
22
32
|
);
|
|
23
|
-
const stopOrphanedDaemonProcessesMock = mock(
|
|
33
|
+
const stopOrphanedDaemonProcessesMock = mock(
|
|
34
|
+
async (): Promise<boolean> => false,
|
|
35
|
+
);
|
|
24
36
|
const stopIngressNginxMock = mock(async (): Promise<boolean> => false);
|
|
25
37
|
|
|
26
38
|
mock.module("../lib/process.js", () => ({
|
|
@@ -40,6 +52,14 @@ mock.module("../lib/retire-archive.js", () => ({
|
|
|
40
52
|
getMetadataPath: () => join(retiredStagingDir, "test-assistant.meta.json"),
|
|
41
53
|
}));
|
|
42
54
|
|
|
55
|
+
// Restore the real modules once this file finishes so the mocks above do not
|
|
56
|
+
// leak into other test files in the same `bun test` run.
|
|
57
|
+
afterAll(() => {
|
|
58
|
+
mock.module("../lib/process.js", () => realProcess);
|
|
59
|
+
mock.module("../lib/nginx-ingress.js", () => realNginxIngress);
|
|
60
|
+
mock.module("../lib/retire-archive.js", () => realRetireArchive);
|
|
61
|
+
});
|
|
62
|
+
|
|
43
63
|
import { retireLocal } from "../lib/retire-local.js";
|
|
44
64
|
|
|
45
65
|
const instanceDir = join(testDir, "test-instance");
|
|
@@ -23,11 +23,19 @@ const isProcessAliveMock = mock((): { alive: boolean; pid: number | null } => ({
|
|
|
23
23
|
pid: null,
|
|
24
24
|
}));
|
|
25
25
|
|
|
26
|
+
const realProcess = { ...(await import("../lib/process.js")) };
|
|
27
|
+
|
|
26
28
|
mock.module("../lib/process.js", () => ({
|
|
27
29
|
isProcessAlive: isProcessAliveMock,
|
|
28
30
|
stopProcessByPidFile: stopProcessByPidFileMock,
|
|
29
31
|
}));
|
|
30
32
|
|
|
33
|
+
// Restore the real module once this file finishes so the mock does not leak
|
|
34
|
+
// into other test files in the same `bun test` run.
|
|
35
|
+
afterAll(() => {
|
|
36
|
+
mock.module("../lib/process.js", () => realProcess);
|
|
37
|
+
});
|
|
38
|
+
|
|
31
39
|
import { sleep } from "../commands/sleep.js";
|
|
32
40
|
import {
|
|
33
41
|
DEFAULT_DAEMON_PORT,
|
|
@@ -282,6 +282,17 @@ mock.module("../lib/local-runtime-client.js", () => ({
|
|
|
282
282
|
localRuntimePreflightFromGcs: localRuntimePreflightFromGcsMock,
|
|
283
283
|
}));
|
|
284
284
|
|
|
285
|
+
// Snapshot the remaining real modules before mocking so `afterAll` can
|
|
286
|
+
// restore them too — otherwise these mocks leak into sibling test files that
|
|
287
|
+
// import the same modules in the same `bun test` run.
|
|
288
|
+
const realHatchLocal = { ...(await import("../lib/hatch-local.js")) };
|
|
289
|
+
const realDocker = { ...(await import("../lib/docker.js")) };
|
|
290
|
+
const realProcess = { ...(await import("../lib/process.js")) };
|
|
291
|
+
const realRetireLocal = { ...(await import("../lib/retire-local.js")) };
|
|
292
|
+
const realUpgradeLifecycle = {
|
|
293
|
+
...(await import("../lib/upgrade-lifecycle.js")),
|
|
294
|
+
};
|
|
295
|
+
|
|
285
296
|
const hatchLocalMock = mock(async () => {});
|
|
286
297
|
|
|
287
298
|
mock.module("../lib/hatch-local.js", () => ({
|
|
@@ -350,6 +361,11 @@ afterAll(() => {
|
|
|
350
361
|
mock.module("../lib/guardian-token.js", () => realGuardianToken);
|
|
351
362
|
mock.module("../lib/platform-client.js", () => realPlatformClient);
|
|
352
363
|
mock.module("../lib/local-runtime-client.js", () => realLocalRuntimeClient);
|
|
364
|
+
mock.module("../lib/hatch-local.js", () => realHatchLocal);
|
|
365
|
+
mock.module("../lib/docker.js", () => realDocker);
|
|
366
|
+
mock.module("../lib/process.js", () => realProcess);
|
|
367
|
+
mock.module("../lib/retire-local.js", () => realRetireLocal);
|
|
368
|
+
mock.module("../lib/upgrade-lifecycle.js", () => realUpgradeLifecycle);
|
|
353
369
|
rmSync(testDir, { recursive: true, force: true });
|
|
354
370
|
delete process.env.VELLUM_LOCKFILE_DIR;
|
|
355
371
|
});
|
|
@@ -15,6 +15,15 @@ import { startCes } from "../local.js";
|
|
|
15
15
|
// Mocks
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
17
|
|
|
18
|
+
// Snapshot the real modules before any `mock.module()` call so we can
|
|
19
|
+
// re-register them in a module-scoped `afterAll` below. Bun runs every test
|
|
20
|
+
// file in one process with a shared loader; without restoring, these mocks
|
|
21
|
+
// leak into sibling files (e.g. `step-runner.test.ts`, whose real `spawn`
|
|
22
|
+
// then returns this file's fake child with no `stdin` and a no-op `on`).
|
|
23
|
+
const realChildProcess = { ...(await import("node:child_process")) };
|
|
24
|
+
const realXdgLog = { ...(await import("../xdg-log.js")) };
|
|
25
|
+
const realProcess = { ...(await import("../process.js")) };
|
|
26
|
+
|
|
18
27
|
// Capture spawn calls so we can assert on cmd/env.
|
|
19
28
|
let lastSpawnCall: {
|
|
20
29
|
cmd: string[];
|
|
@@ -55,6 +64,15 @@ mock.module("../process.js", () => ({
|
|
|
55
64
|
stopProcessGracefully: mock(async () => {}),
|
|
56
65
|
}));
|
|
57
66
|
|
|
67
|
+
// Restore the real modules once this file finishes so the mocks above do not
|
|
68
|
+
// leak into other test files in the same `bun test` run. `mock.restore()` does
|
|
69
|
+
// not undo `mock.module()`, so we re-register the captured real exports.
|
|
70
|
+
afterAll(() => {
|
|
71
|
+
mock.module("node:child_process", () => realChildProcess);
|
|
72
|
+
mock.module("../xdg-log.js", () => realXdgLog);
|
|
73
|
+
mock.module("../process.js", () => realProcess);
|
|
74
|
+
});
|
|
75
|
+
|
|
58
76
|
// ---------------------------------------------------------------------------
|
|
59
77
|
// Tests
|
|
60
78
|
// ---------------------------------------------------------------------------
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
afterAll,
|
|
3
|
+
afterEach,
|
|
4
|
+
beforeEach,
|
|
5
|
+
describe,
|
|
6
|
+
expect,
|
|
7
|
+
mock,
|
|
8
|
+
test,
|
|
9
|
+
} from "bun:test";
|
|
2
10
|
import { join } from "path";
|
|
3
11
|
|
|
4
12
|
const TEST_HOME = "/test/home";
|
|
@@ -18,6 +26,13 @@ mock.module("os", () => ({
|
|
|
18
26
|
homedir: () => TEST_HOME,
|
|
19
27
|
}));
|
|
20
28
|
|
|
29
|
+
// Restore the real `os` module once this file finishes so the `homedir()`
|
|
30
|
+
// override does not leak into other test files in the same `bun test` run.
|
|
31
|
+
afterAll(() => {
|
|
32
|
+
mock.module("node:os", () => realOs);
|
|
33
|
+
mock.module("os", () => realOs);
|
|
34
|
+
});
|
|
35
|
+
|
|
21
36
|
// Imports that depend on the mocked `os` module must come after the
|
|
22
37
|
// mock.module() calls above.
|
|
23
38
|
const {
|
package/src/lib/local.ts
CHANGED
|
@@ -42,8 +42,8 @@ const _require = createRequire(import.meta.url);
|
|
|
42
42
|
const DARWIN_UNIX_SOCKET_MAX_PATH_BYTES = 103;
|
|
43
43
|
|
|
44
44
|
// The longest socket filename we place in the workspace directory.
|
|
45
|
-
// assistant
|
|
46
|
-
const LONGEST_SOCKET_FILENAME = "assistant
|
|
45
|
+
// assistant.sock = 14 chars, plus 1 for the "/" separator = 15 overhead.
|
|
46
|
+
const LONGEST_SOCKET_FILENAME = "assistant.sock";
|
|
47
47
|
const LOCAL_RUNTIME_PACKAGE = "vellum";
|
|
48
48
|
|
|
49
49
|
export interface LocalRuntimeInstall {
|
|
@@ -300,7 +300,7 @@ function warnIfLegacyWorkspaceFallbackDetected(
|
|
|
300
300
|
}
|
|
301
301
|
|
|
302
302
|
/**
|
|
303
|
-
* On macOS, if `{workspaceDir}/assistant
|
|
303
|
+
* On macOS, if `{workspaceDir}/assistant.sock` would exceed the
|
|
304
304
|
* 103-byte AF_UNIX path limit, compute a short tmpdir-based IPC socket
|
|
305
305
|
* directory and return it. Returns `undefined` when no override is needed
|
|
306
306
|
* (the workspace path is short enough, or we're not on macOS).
|
|
@@ -340,7 +340,6 @@ function applyIpcSocketDirOverride(
|
|
|
340
340
|
mkdirSync(override, { recursive: true });
|
|
341
341
|
env.GATEWAY_IPC_SOCKET_DIR = override;
|
|
342
342
|
env.ASSISTANT_IPC_SOCKET_DIR = override;
|
|
343
|
-
env.ASSISTANT_SKILL_IPC_SOCKET_DIR = override;
|
|
344
343
|
}
|
|
345
344
|
|
|
346
345
|
function isAssistantSourceDir(dir: string): boolean {
|