@mycadet/cli 0.12.7 → 0.12.9-dev.202610131452.9acab64
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 +2 -2
- package/knip.json +1 -1
- package/node_modules/@mycadet/assistant-api/events/cloud-disconnected.ts +21 -0
- package/node_modules/@mycadet/assistant-api/events/host-bash.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/host-cu.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/host-file.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/notification-intent.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/show-cloud-login.ts +18 -0
- package/node_modules/@mycadet/assistant-api/index.ts +11 -11
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/package.json +2 -2
- package/node_modules/@mycadet/{service-contracts/src/platform-credential.ts → assistant-api/node_modules/@mycadet/service-contracts/src/cloud-credential.ts} +9 -9
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
- package/node_modules/@mycadet/assistant-api/responses/home.ts +1 -1
- package/node_modules/@mycadet/assistant-api/surfaces.ts +4 -4
- package/node_modules/@mycadet/avatar-manifest/src/__tests__/notification-avatar.test.ts +1 -1
- package/node_modules/@mycadet/avatar-manifest/src/notification-avatar.ts +2 -2
- package/node_modules/@mycadet/environments/src/seeds.ts +6 -6
- package/node_modules/@mycadet/environments/src/shell.test.ts +1 -1
- package/node_modules/@mycadet/environments/src/types.ts +6 -6
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/avatar-manifest/src/__tests__/notification-avatar.test.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/avatar-manifest/src/notification-avatar.ts +2 -2
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/seeds.ts +6 -6
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/shell.test.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/types.ts +6 -6
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/package.json +2 -2
- package/node_modules/@mycadet/{assistant-api/node_modules/@mycadet/service-contracts/src/platform-credential.ts → local-mode/node_modules/@mycadet/service-contracts/src/cloud-credential.ts} +9 -9
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
- package/node_modules/@mycadet/local-mode/src/__tests__/pair.test.ts +5 -5
- package/node_modules/@mycadet/local-mode/src/__tests__/retire.test.ts +1 -1
- package/node_modules/@mycadet/local-mode/src/config.ts +2 -2
- package/node_modules/@mycadet/local-mode/src/index.ts +1 -1
- package/node_modules/@mycadet/local-mode/src/lockfile-contract.test.ts +3 -3
- package/node_modules/@mycadet/local-mode/src/lockfile-contract.ts +10 -5
- package/node_modules/@mycadet/local-mode/src/lockfile.test.ts +15 -15
- package/node_modules/@mycadet/local-mode/src/lockfile.ts +9 -9
- package/node_modules/@mycadet/local-mode/src/pair.ts +2 -2
- package/node_modules/@mycadet/local-mode/src/retire.ts +3 -3
- package/node_modules/@mycadet/local-mode/src/teleport-backup-policy.ts +2 -2
- package/node_modules/@mycadet/local-mode/src/unpair.ts +2 -2
- package/node_modules/@mycadet/service-contracts/package.json +2 -2
- package/node_modules/@mycadet/{local-mode/node_modules/@mycadet/service-contracts/src/platform-credential.ts → service-contracts/src/cloud-credential.ts} +9 -9
- package/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
- package/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
- package/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
- package/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
- package/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
- package/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
- package/package.json +6 -4
- package/src/__tests__/assistant-api-key-resolution.test.ts +6 -6
- package/src/__tests__/{assistant-client-platform-auth.test.ts → assistant-client-cloud-auth.test.ts} +10 -10
- package/src/__tests__/assistant-client-refresh.test.ts +2 -2
- package/src/__tests__/backup.test.ts +86 -91
- package/src/__tests__/client-token.test.ts +1 -1
- package/src/__tests__/client-tui-refresh.test.ts +1 -1
- package/src/__tests__/client-web-config.test.ts +1 -2
- package/src/__tests__/{platform-client.test.ts → cloud-client.test.ts} +59 -59
- package/src/__tests__/{platform-releases.test.ts → cloud-releases.test.ts} +28 -18
- package/src/__tests__/{cloudflare-tunnel.test.ts → cloudflare.test.ts} +1 -1
- package/src/__tests__/connect-import.test.ts +55 -39
- package/src/__tests__/debug.test.ts +38 -38
- package/src/__tests__/ensure-binary.test.ts +182 -0
- package/src/__tests__/guardian-token.test.ts +149 -56
- package/src/__tests__/hatch-provider-secrets.test.ts +2 -2
- package/src/__tests__/helpers/guardian-token.ts +22 -0
- package/src/__tests__/helpers/http.ts +10 -0
- package/src/__tests__/nginx-ingress.test.ts +15 -20
- package/src/__tests__/ngrok-spawn.test.ts +49 -0
- package/src/__tests__/orphan-detection.test.ts +1 -1
- package/src/__tests__/pair.test.ts +149 -85
- package/src/__tests__/{ps-platform-status.test.ts → ps-cloud-status.test.ts} +80 -26
- package/src/__tests__/ps-table.test.ts +79 -0
- package/src/__tests__/{recover.test.ts → restore.test.ts} +29 -28
- package/src/__tests__/retire.test.ts +58 -199
- package/src/__tests__/root-process-lockfile.test.ts +99 -0
- package/src/__tests__/sleep.test.ts +19 -19
- package/src/__tests__/statefulset.test.ts +8 -8
- package/src/__tests__/{tailscale-tunnel.test.ts → tailscale.test.ts} +2 -2
- package/src/__tests__/teleport-backup.test.ts +3 -3
- package/src/__tests__/teleport.test.ts +180 -211
- package/src/__tests__/tunnel.test.ts +490 -270
- package/src/__tests__/uninstall.test.ts +150 -9
- package/src/__tests__/upgrade-local.test.ts +3 -3
- package/src/__tests__/upgrade-replay-env.test.ts +12 -12
- package/src/__tests__/wake.test.ts +260 -43
- package/src/__tests__/workos-pkce.test.ts +2 -2
- package/src/commands/backup.ts +24 -24
- package/src/commands/client.ts +76 -78
- package/src/commands/completions.test.ts +104 -0
- package/src/commands/completions.ts +87 -0
- package/src/commands/debug.ts +20 -20
- package/src/commands/exec.ts +12 -12
- package/src/commands/flags.ts +2 -2
- package/src/commands/hatch.ts +27 -24
- package/src/commands/login.ts +22 -22
- package/src/commands/logs.ts +8 -8
- package/src/commands/pair.ts +140 -37
- package/src/commands/ps.ts +232 -86
- package/src/commands/restart.ts +30 -0
- package/src/commands/restore.ts +140 -22
- package/src/commands/retire.ts +48 -150
- package/src/commands/rollback.ts +20 -26
- package/src/commands/setup.ts +2 -2
- package/src/commands/sleep.ts +2 -2
- package/src/commands/teleport.ts +110 -129
- package/src/commands/terminal.ts +158 -18
- package/src/commands/tunnel.ts +156 -175
- package/src/commands/uninstall.ts +137 -54
- package/src/commands/unpair.ts +3 -3
- package/src/commands/upgrade.ts +30 -54
- package/src/commands/use.ts +1 -1
- package/src/commands/wake.ts +166 -50
- package/src/index.ts +18 -9
- package/src/lib/__tests__/{platform-client-signed-url.test.ts → cloud-client-signed-url.test.ts} +16 -16
- package/src/lib/__tests__/docker.test.ts +168 -20
- package/src/lib/__tests__/job-polling.test.ts +2 -2
- package/src/lib/__tests__/local-gateway-cli.test.ts +42 -0
- package/src/lib/__tests__/local-runtime-client.test.ts +4 -4
- package/src/lib/__tests__/runtime-url.test.ts +1 -1
- package/src/lib/assistant-api-key-resolution.ts +5 -5
- package/src/lib/assistant-client.ts +8 -8
- package/src/lib/assistant-config.ts +58 -12
- package/src/lib/{platform-client.ts → cloud-client.ts} +105 -99
- package/src/lib/cloud-login.ts +23 -24
- package/src/lib/{platform-releases.ts → cloud-releases.ts} +11 -9
- package/src/lib/cloud-values.ts +3 -0
- package/src/lib/color.ts +4 -0
- package/src/lib/config-utils.ts +1 -1
- package/src/lib/detached-process.ts +1 -1
- package/src/lib/docker.ts +300 -111
- package/src/lib/ensure-binary.ts +171 -0
- package/src/lib/environments/__tests__/paths.test.ts +29 -3
- package/src/lib/environments/__tests__/resolve.test.ts +26 -26
- package/src/lib/environments/paths.ts +16 -8
- package/src/lib/environments/resolve.ts +10 -12
- package/src/lib/flag-args.test.ts +1 -1
- package/src/lib/flag-args.ts +1 -1
- package/src/lib/guardian-token.ts +37 -5
- package/src/lib/hatch-local.ts +32 -29
- package/src/lib/hatch-next-steps.ts +5 -9
- package/src/lib/health-check.ts +6 -6
- package/src/lib/ingress-config.ts +8 -35
- package/src/lib/job-polling.ts +2 -2
- package/src/lib/live-voice/connection.ts +12 -12
- package/src/lib/live-voice/tunnel.test.ts +11 -11
- package/src/lib/live-voice/tunnel.ts +15 -15
- package/src/lib/local-runtime-client.ts +20 -20
- package/src/lib/local.ts +46 -34
- package/src/lib/nginx-ingress.ts +40 -15
- package/src/lib/pair.ts +1 -1
- package/src/lib/process.ts +1 -1
- package/src/lib/provider-secrets.ts +3 -3
- package/src/lib/retire-apple-container.ts +1 -1
- package/src/lib/runtime-url.ts +8 -8
- package/src/lib/statefulset.ts +2 -2
- package/src/lib/step-runner.ts +6 -1
- package/src/lib/sync-cloud-assistants.ts +19 -19
- package/src/lib/teleport-backup.ts +4 -4
- package/src/lib/terminal-client.ts +17 -17
- package/src/lib/terminal-session.ts +24 -24
- package/src/lib/{tunnel-edge.ts → tunnel.ts} +199 -11
- package/src/lib/tunnels/cadet.ts +29 -0
- package/src/lib/{cloudflare-tunnel.ts → tunnels/cloudflare.ts} +36 -15
- package/src/lib/tunnels/gateway-notify.ts +61 -0
- package/src/lib/{ngrok.ts → tunnels/ngrok.ts} +350 -89
- package/src/lib/{tailscale-tunnel.ts → tunnels/tailscale.ts} +53 -9
- package/src/lib/upgrade-lifecycle.ts +8 -21
- package/src/lib/upgrade-preflight.ts +2 -2
- package/src/lib/workos-pkce.ts +5 -5
- package/node_modules/@mycadet/assistant-api/events/platform-disconnected.ts +0 -21
- package/node_modules/@mycadet/assistant-api/events/show-platform-login.ts +0 -20
- package/src/commands/recover.ts +0 -131
- package/src/commands/roadmap.ts +0 -459
- package/src/commands/ssh.ts +0 -144
- package/src/commands/workflows.ts +0 -305
- package/src/lib/managed-cloud.ts +0 -3
|
@@ -21,7 +21,7 @@ import { join } from "node:path";
|
|
|
21
21
|
import type { AssistantEntry } from "../lib/assistant-config.js";
|
|
22
22
|
import { loadAllAssistants } from "../lib/assistant-config.js";
|
|
23
23
|
import * as loopbackFetchModule from "../lib/loopback-fetch.js";
|
|
24
|
-
import * as
|
|
24
|
+
import * as cloudClientModule from "../lib/cloud-client.js";
|
|
25
25
|
import * as retireLocalModule from "../lib/retire-local.js";
|
|
26
26
|
|
|
27
27
|
const testDir = mkdtempSync(join(tmpdir(), "cli-retire-test-"));
|
|
@@ -35,11 +35,11 @@ const originalStdinIsRaw = process.stdin.isRaw;
|
|
|
35
35
|
const originalSetRawMode = process.stdin.setRawMode;
|
|
36
36
|
const originalStdoutWrite = process.stdout.write;
|
|
37
37
|
const realRetireLocalModule = { ...retireLocalModule };
|
|
38
|
-
const
|
|
38
|
+
const realCloudClientModule = { ...cloudClientModule };
|
|
39
39
|
const realLoopbackFetchModule = { ...loopbackFetchModule };
|
|
40
40
|
|
|
41
41
|
const retireLocalMock = mock(async () => {});
|
|
42
|
-
const
|
|
42
|
+
const readCloudTokenMock = mock((): string | null => null);
|
|
43
43
|
const authHeadersMock = mock(async () => ({
|
|
44
44
|
"Content-Type": "application/json",
|
|
45
45
|
"X-Session-Token": "session-token",
|
|
@@ -51,7 +51,7 @@ const authHeadersForKnownOrganizationMock = mock(
|
|
|
51
51
|
"Cadet-Organization-Id": organizationId,
|
|
52
52
|
}),
|
|
53
53
|
);
|
|
54
|
-
const
|
|
54
|
+
const getCloudUrlMock = mock(() => "https://platform.example.com");
|
|
55
55
|
const readGatewayCredentialMock = mock(
|
|
56
56
|
async (
|
|
57
57
|
_gatewayUrl: string,
|
|
@@ -71,12 +71,12 @@ mock.module("../lib/retire-local.js", () => ({
|
|
|
71
71
|
retireLocal: retireLocalMock,
|
|
72
72
|
}));
|
|
73
73
|
|
|
74
|
-
mock.module("../lib/
|
|
74
|
+
mock.module("../lib/cloud-client.js", () => ({
|
|
75
75
|
authHeaders: authHeadersMock,
|
|
76
76
|
authHeadersForKnownOrganization: authHeadersForKnownOrganizationMock,
|
|
77
|
-
|
|
77
|
+
getCloudUrl: getCloudUrlMock,
|
|
78
78
|
readGatewayCredential: readGatewayCredentialMock,
|
|
79
|
-
|
|
79
|
+
readCloudToken: readCloudTokenMock,
|
|
80
80
|
}));
|
|
81
81
|
|
|
82
82
|
mock.module("../lib/loopback-fetch.js", () => ({
|
|
@@ -168,7 +168,11 @@ describe("cadet retire", () => {
|
|
|
168
168
|
beforeEach(() => {
|
|
169
169
|
process.env.CADET_LOCKFILE_DIR = testDir;
|
|
170
170
|
delete process.env.CADET_PLATFORM_TOKEN;
|
|
171
|
-
for (const name of [
|
|
171
|
+
for (const name of [
|
|
172
|
+
"lockfile.json",
|
|
173
|
+
".cadet.lock.json",
|
|
174
|
+
".cadet.lockfile.json",
|
|
175
|
+
]) {
|
|
172
176
|
rmSync(join(testDir, name), { force: true });
|
|
173
177
|
}
|
|
174
178
|
process.argv = ["bun", "cadet", "retire"];
|
|
@@ -177,8 +181,8 @@ describe("cadet retire", () => {
|
|
|
177
181
|
}) as typeof process.exit;
|
|
178
182
|
retireLocalMock.mockReset();
|
|
179
183
|
retireLocalMock.mockResolvedValue(undefined);
|
|
180
|
-
|
|
181
|
-
|
|
184
|
+
readCloudTokenMock.mockReset();
|
|
185
|
+
readCloudTokenMock.mockReturnValue(null);
|
|
182
186
|
authHeadersMock.mockReset();
|
|
183
187
|
authHeadersMock.mockResolvedValue({
|
|
184
188
|
"Content-Type": "application/json",
|
|
@@ -192,8 +196,8 @@ describe("cadet retire", () => {
|
|
|
192
196
|
"Cadet-Organization-Id": organizationId,
|
|
193
197
|
}),
|
|
194
198
|
);
|
|
195
|
-
|
|
196
|
-
|
|
199
|
+
getCloudUrlMock.mockReset();
|
|
200
|
+
getCloudUrlMock.mockReturnValue("https://platform.example.com");
|
|
197
201
|
readGatewayCredentialMock.mockReset();
|
|
198
202
|
readGatewayCredentialMock.mockResolvedValue({
|
|
199
203
|
value: null,
|
|
@@ -220,7 +224,7 @@ describe("cadet retire", () => {
|
|
|
220
224
|
|
|
221
225
|
afterAll(() => {
|
|
222
226
|
mock.module("../lib/retire-local.js", () => realRetireLocalModule);
|
|
223
|
-
mock.module("../lib/
|
|
227
|
+
mock.module("../lib/cloud-client.js", () => realCloudClientModule);
|
|
224
228
|
mock.module("../lib/loopback-fetch.js", () => realLoopbackFetchModule);
|
|
225
229
|
if (originalLockfileDir === undefined) {
|
|
226
230
|
delete process.env.CADET_LOCKFILE_DIR;
|
|
@@ -252,35 +256,25 @@ describe("cadet retire", () => {
|
|
|
252
256
|
);
|
|
253
257
|
});
|
|
254
258
|
|
|
255
|
-
test("local retire unregisters the
|
|
256
|
-
const entry = makeEntry("assistant-1", {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (name === "cadet:platform_assistant_id") {
|
|
262
|
-
return { value: "platform-assistant-1", unreachable: false };
|
|
263
|
-
}
|
|
264
|
-
if (name === "cadet:platform_base_url") {
|
|
265
|
-
return { value: "https://platform.example.test", unreachable: false };
|
|
266
|
-
}
|
|
267
|
-
if (name === "cadet:platform_organization_id") {
|
|
268
|
-
return { value: "org-123", unreachable: false };
|
|
269
|
-
}
|
|
270
|
-
return { value: null, unreachable: false };
|
|
259
|
+
test("local retire unregisters the cloud record straight from the lockfile entry", async () => {
|
|
260
|
+
const entry = makeEntry("assistant-1", {
|
|
261
|
+
name: "Example Assistant",
|
|
262
|
+
localUrl: "http://127.0.0.1:7831",
|
|
263
|
+
cloudAssistantId: "cloud-asst-1",
|
|
264
|
+
cloudOrganizationId: "org-123",
|
|
271
265
|
});
|
|
266
|
+
writeLockfile([entry]);
|
|
267
|
+
readCloudTokenMock.mockReturnValue("session-token");
|
|
268
|
+
getCloudUrlMock.mockReturnValue("https://platform.example.test");
|
|
272
269
|
process.argv = ["bun", "cadet", "retire", "assistant-1", "--yes"];
|
|
273
270
|
|
|
274
271
|
await retire();
|
|
275
272
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
entry.bearerToken,
|
|
280
|
-
);
|
|
281
|
-
expect(authHeadersMock).not.toHaveBeenCalled();
|
|
273
|
+
// The cloud record resolves from the entry + env — the local gateway
|
|
274
|
+
// credential store is never consulted.
|
|
275
|
+
expect(readGatewayCredentialMock).not.toHaveBeenCalled();
|
|
282
276
|
expect(loopbackSafeFetchMock).toHaveBeenCalledWith(
|
|
283
|
-
"https://platform.example.test/
|
|
277
|
+
"https://platform.example.test/v1/assistants/cloud-asst-1/retire/",
|
|
284
278
|
{
|
|
285
279
|
method: "DELETE",
|
|
286
280
|
headers: {
|
|
@@ -294,194 +288,67 @@ describe("cadet retire", () => {
|
|
|
294
288
|
expect(loadAllAssistants()).toEqual([]);
|
|
295
289
|
});
|
|
296
290
|
|
|
297
|
-
test("local retire
|
|
298
|
-
const localGatewayUrl = "http://127.0.0.1:7831";
|
|
299
|
-
const entry = makeEntry("assistant-1", {
|
|
300
|
-
name: "Example Assistant",
|
|
301
|
-
runtimeUrl: "http://assistant-1.local:7831",
|
|
302
|
-
localUrl: localGatewayUrl,
|
|
303
|
-
});
|
|
304
|
-
writeLockfile([entry]);
|
|
305
|
-
readPlatformTokenMock.mockReturnValue("session-token");
|
|
306
|
-
getPlatformUrlMock.mockReturnValue("https://platform.example.test");
|
|
307
|
-
readGatewayCredentialMock.mockImplementation(async (gatewayUrl, name) => {
|
|
308
|
-
expect(gatewayUrl).toBe(localGatewayUrl);
|
|
309
|
-
if (name === "cadet:platform_assistant_id") {
|
|
310
|
-
return { value: "platform-assistant-1", unreachable: false };
|
|
311
|
-
}
|
|
312
|
-
if (name === "cadet:platform_base_url") {
|
|
313
|
-
return { value: "https://platform.example.test", unreachable: false };
|
|
314
|
-
}
|
|
315
|
-
if (name === "cadet:platform_organization_id") {
|
|
316
|
-
return { value: "org-123", unreachable: false };
|
|
317
|
-
}
|
|
318
|
-
return { value: null, unreachable: false };
|
|
319
|
-
});
|
|
320
|
-
process.argv = ["bun", "cadet", "retire", "assistant-1", "--yes"];
|
|
321
|
-
|
|
322
|
-
await retire();
|
|
323
|
-
|
|
324
|
-
expect(readGatewayCredentialMock).toHaveBeenCalledWith(
|
|
325
|
-
localGatewayUrl,
|
|
326
|
-
"cadet:platform_assistant_id",
|
|
327
|
-
entry.bearerToken,
|
|
328
|
-
);
|
|
329
|
-
expect(readGatewayCredentialMock).toHaveBeenCalledWith(
|
|
330
|
-
localGatewayUrl,
|
|
331
|
-
"cadet:platform_base_url",
|
|
332
|
-
entry.bearerToken,
|
|
333
|
-
);
|
|
334
|
-
expect(readGatewayCredentialMock).toHaveBeenCalledWith(
|
|
335
|
-
localGatewayUrl,
|
|
336
|
-
"cadet:platform_organization_id",
|
|
337
|
-
entry.bearerToken,
|
|
338
|
-
);
|
|
339
|
-
expect(loopbackSafeFetchMock).toHaveBeenCalledWith(
|
|
340
|
-
"https://platform.example.test/v1/assistants/platform-assistant-1/retire/",
|
|
341
|
-
expect.any(Object),
|
|
342
|
-
);
|
|
343
|
-
expect(retireLocalMock).toHaveBeenCalledWith("assistant-1", entry);
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
test("local retire uses saved platform registration when local credentials are unreachable", async () => {
|
|
291
|
+
test("local retire resolves the organization via the cloud when the entry omits it", async () => {
|
|
347
292
|
const entry = makeEntry("assistant-1", {
|
|
348
293
|
name: "Example Assistant",
|
|
349
|
-
|
|
350
|
-
platformBaseUrl: "https://platform.example.test",
|
|
351
|
-
platformOrganizationId: "org-123",
|
|
294
|
+
cloudAssistantId: "cloud-asst-1",
|
|
352
295
|
});
|
|
353
296
|
writeLockfile([entry]);
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
readGatewayCredentialMock.mockResolvedValue({
|
|
357
|
-
value: null,
|
|
358
|
-
unreachable: true,
|
|
359
|
-
});
|
|
297
|
+
readCloudTokenMock.mockReturnValue("session-token");
|
|
298
|
+
getCloudUrlMock.mockReturnValue("https://platform.example.test");
|
|
360
299
|
process.argv = ["bun", "cadet", "retire", "assistant-1", "--yes"];
|
|
361
300
|
|
|
362
301
|
await retire();
|
|
363
302
|
|
|
364
|
-
expect(
|
|
365
|
-
|
|
366
|
-
"
|
|
367
|
-
entry.bearerToken,
|
|
303
|
+
expect(authHeadersMock).toHaveBeenCalledWith(
|
|
304
|
+
"session-token",
|
|
305
|
+
"https://platform.example.test",
|
|
368
306
|
);
|
|
307
|
+
expect(authHeadersForKnownOrganizationMock).not.toHaveBeenCalled();
|
|
369
308
|
expect(loopbackSafeFetchMock).toHaveBeenCalledWith(
|
|
370
|
-
"https://platform.example.test/v1/assistants/
|
|
309
|
+
"https://platform.example.test/v1/assistants/cloud-asst-1/retire/",
|
|
371
310
|
{
|
|
372
311
|
method: "DELETE",
|
|
373
312
|
headers: {
|
|
374
313
|
"Content-Type": "application/json",
|
|
375
314
|
"X-Session-Token": "session-token",
|
|
376
|
-
"Cadet-Organization-Id": "org-123",
|
|
377
315
|
},
|
|
378
316
|
},
|
|
379
317
|
);
|
|
380
|
-
expect(consoleWarnSpy.mock.calls.flat().join("\n")).toContain(
|
|
381
|
-
"using saved platform registration",
|
|
382
|
-
);
|
|
383
318
|
expect(retireLocalMock).toHaveBeenCalledWith("assistant-1", entry);
|
|
384
319
|
expect(loadAllAssistants()).toEqual([]);
|
|
385
320
|
});
|
|
386
321
|
|
|
387
|
-
test("local retire
|
|
322
|
+
test("local retire skips the cloud unregister when no assistant id is bound", async () => {
|
|
388
323
|
const entry = makeEntry("assistant-1", { name: "Example Assistant" });
|
|
389
324
|
writeLockfile([entry]);
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
value: null,
|
|
393
|
-
unreachable: true,
|
|
394
|
-
});
|
|
325
|
+
readCloudTokenMock.mockReturnValue("session-token");
|
|
326
|
+
getCloudUrlMock.mockReturnValue("https://platform.example.test");
|
|
395
327
|
process.argv = ["bun", "cadet", "retire", "assistant-1", "--yes"];
|
|
396
328
|
|
|
397
329
|
await retire();
|
|
398
330
|
|
|
399
331
|
expect(loopbackSafeFetchMock).not.toHaveBeenCalled();
|
|
400
|
-
expect(consoleWarnSpy.mock.calls.flat().join("\n")).toContain(
|
|
401
|
-
"no saved platform registration is available",
|
|
402
|
-
);
|
|
403
|
-
expect(retireLocalMock).toHaveBeenCalledWith("assistant-1", entry);
|
|
404
|
-
expect(loadAllAssistants()).toEqual([]);
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
test("local retire skips platform unregister when stored platform URL origin mismatches", async () => {
|
|
408
|
-
const entry = makeEntry("assistant-1", { name: "Example Assistant" });
|
|
409
|
-
writeLockfile([entry]);
|
|
410
|
-
readPlatformTokenMock.mockReturnValue("session-token");
|
|
411
|
-
getPlatformUrlMock.mockReturnValue("https://platform.example.com");
|
|
412
|
-
readGatewayCredentialMock.mockImplementation(async (_gatewayUrl, name) => {
|
|
413
|
-
if (name === "cadet:platform_assistant_id") {
|
|
414
|
-
return { value: "platform-assistant-1", unreachable: false };
|
|
415
|
-
}
|
|
416
|
-
if (name === "cadet:platform_base_url") {
|
|
417
|
-
return { value: "https://malicious.example.test", unreachable: false };
|
|
418
|
-
}
|
|
419
|
-
if (name === "cadet:platform_organization_id") {
|
|
420
|
-
return { value: "org-123", unreachable: false };
|
|
421
|
-
}
|
|
422
|
-
return { value: null, unreachable: false };
|
|
423
|
-
});
|
|
424
|
-
process.argv = ["bun", "cadet", "retire", "assistant-1", "--yes"];
|
|
425
|
-
|
|
426
|
-
await retire();
|
|
427
|
-
|
|
428
|
-
expect(loopbackSafeFetchMock).not.toHaveBeenCalled();
|
|
429
|
-
expect(consoleWarnSpy.mock.calls.flat().join("\n")).toContain(
|
|
430
|
-
"Stored platform URL does not match the configured platform URL",
|
|
431
|
-
);
|
|
432
|
-
expect(retireLocalMock).toHaveBeenCalledWith("assistant-1", entry);
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
test("local retire skips platform unregister when stored organization ID is missing", async () => {
|
|
436
|
-
const entry = makeEntry("assistant-1", { name: "Example Assistant" });
|
|
437
|
-
writeLockfile([entry]);
|
|
438
|
-
readPlatformTokenMock.mockReturnValue("session-token");
|
|
439
|
-
getPlatformUrlMock.mockReturnValue("https://platform.example.test");
|
|
440
|
-
readGatewayCredentialMock.mockImplementation(async (_gatewayUrl, name) => {
|
|
441
|
-
if (name === "cadet:platform_assistant_id") {
|
|
442
|
-
return { value: "platform-assistant-1", unreachable: false };
|
|
443
|
-
}
|
|
444
|
-
if (name === "cadet:platform_base_url") {
|
|
445
|
-
return { value: "https://platform.example.test", unreachable: false };
|
|
446
|
-
}
|
|
447
|
-
return { value: null, unreachable: false };
|
|
448
|
-
});
|
|
449
|
-
process.argv = ["bun", "cadet", "retire", "assistant-1", "--yes"];
|
|
450
|
-
|
|
451
|
-
await retire();
|
|
452
|
-
|
|
453
|
-
expect(loopbackSafeFetchMock).not.toHaveBeenCalled();
|
|
454
|
-
expect(consoleWarnSpy.mock.calls.flat().join("\n")).toContain(
|
|
455
|
-
"Could not read platform organization ID",
|
|
456
|
-
);
|
|
457
332
|
expect(retireLocalMock).toHaveBeenCalledWith("assistant-1", entry);
|
|
458
333
|
expect(loadAllAssistants()).toEqual([]);
|
|
459
334
|
});
|
|
460
335
|
|
|
461
336
|
test("local retire uses injected platform token from the app host", async () => {
|
|
462
|
-
const entry = makeEntry("assistant-1", {
|
|
337
|
+
const entry = makeEntry("assistant-1", {
|
|
338
|
+
name: "Example Assistant",
|
|
339
|
+
cloudAssistantId: "cloud-asst-1",
|
|
340
|
+
cloudOrganizationId: "org-123",
|
|
341
|
+
});
|
|
463
342
|
writeLockfile([entry]);
|
|
464
343
|
process.env.CADET_PLATFORM_TOKEN = "host-session-token";
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
readGatewayCredentialMock.mockImplementation(async (_gatewayUrl, name) => {
|
|
468
|
-
if (name === "cadet:platform_assistant_id") {
|
|
469
|
-
return { value: "platform-assistant-1", unreachable: false };
|
|
470
|
-
}
|
|
471
|
-
if (name === "cadet:platform_base_url") {
|
|
472
|
-
return { value: "https://platform.example.test", unreachable: false };
|
|
473
|
-
}
|
|
474
|
-
if (name === "cadet:platform_organization_id") {
|
|
475
|
-
return { value: "org-123", unreachable: false };
|
|
476
|
-
}
|
|
477
|
-
return { value: null, unreachable: false };
|
|
478
|
-
});
|
|
344
|
+
readCloudTokenMock.mockReturnValue(null);
|
|
345
|
+
getCloudUrlMock.mockReturnValue("https://platform.example.test");
|
|
479
346
|
process.argv = ["bun", "cadet", "retire", "assistant-1", "--yes"];
|
|
480
347
|
|
|
481
348
|
await retire();
|
|
482
349
|
|
|
483
350
|
expect(loopbackSafeFetchMock).toHaveBeenCalledWith(
|
|
484
|
-
"https://platform.example.test/v1/assistants/
|
|
351
|
+
"https://platform.example.test/v1/assistants/cloud-asst-1/retire/",
|
|
485
352
|
{
|
|
486
353
|
method: "DELETE",
|
|
487
354
|
headers: {
|
|
@@ -494,23 +361,15 @@ describe("cadet retire", () => {
|
|
|
494
361
|
expect(retireLocalMock).toHaveBeenCalledWith("assistant-1", entry);
|
|
495
362
|
});
|
|
496
363
|
|
|
497
|
-
test("local retire continues when
|
|
498
|
-
const entry = makeEntry("assistant-1", {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
readGatewayCredentialMock.mockImplementation(async (_gatewayUrl, name) => {
|
|
503
|
-
if (name === "cadet:platform_assistant_id") {
|
|
504
|
-
return { value: "platform-assistant-1", unreachable: false };
|
|
505
|
-
}
|
|
506
|
-
if (name === "cadet:platform_base_url") {
|
|
507
|
-
return { value: "https://platform.example.test", unreachable: false };
|
|
508
|
-
}
|
|
509
|
-
if (name === "cadet:platform_organization_id") {
|
|
510
|
-
return { value: "org-123", unreachable: false };
|
|
511
|
-
}
|
|
512
|
-
return { value: null, unreachable: false };
|
|
364
|
+
test("local retire continues when the cloud unregister fails", async () => {
|
|
365
|
+
const entry = makeEntry("assistant-1", {
|
|
366
|
+
name: "Example Assistant",
|
|
367
|
+
cloudAssistantId: "cloud-asst-1",
|
|
368
|
+
cloudOrganizationId: "org-123",
|
|
513
369
|
});
|
|
370
|
+
writeLockfile([entry]);
|
|
371
|
+
readCloudTokenMock.mockReturnValue("session-token");
|
|
372
|
+
getCloudUrlMock.mockReturnValue("https://platform.example.test");
|
|
514
373
|
loopbackSafeFetchMock.mockResolvedValue(
|
|
515
374
|
new Response("platform unavailable", { status: 503 }),
|
|
516
375
|
);
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
clearRootProcess,
|
|
9
|
+
readRootProcesses,
|
|
10
|
+
stampRootProcess,
|
|
11
|
+
} from "../lib/assistant-config.js";
|
|
12
|
+
|
|
13
|
+
// Create a temp directory and set CADET_LOCKFILE_DIR so the real lockfile
|
|
14
|
+
// helpers resolve inside it (the sleep.test.ts fixture pattern).
|
|
15
|
+
let testDir: string;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
testDir = mkdtempSync(join(tmpdir(), "cadet-root-process-test-"));
|
|
19
|
+
mkdirSync(join(testDir, "config"), { recursive: true });
|
|
20
|
+
process.env.CADET_LOCKFILE_DIR = join(testDir, "config");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
delete process.env.CADET_LOCKFILE_DIR;
|
|
25
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("root process lockfile entries", () => {
|
|
29
|
+
test("a tunnel record stamps at the root, reads back, and clears", () => {
|
|
30
|
+
stampRootProcess("tunnel", {
|
|
31
|
+
pid: 4242,
|
|
32
|
+
provider: "ngrok",
|
|
33
|
+
startedAt: "2026-10-11T00:00:00.000Z",
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(readRootProcesses().tunnel).toMatchObject({
|
|
37
|
+
pid: 4242,
|
|
38
|
+
provider: "ngrok",
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
clearRootProcess("tunnel");
|
|
42
|
+
expect(readRootProcesses().tunnel).toBeUndefined();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("tunnel and app entries stamp and clear independently", () => {
|
|
46
|
+
stampRootProcess("app", { pid: 77, startedAt: "2026-10-11T00:00:00.000Z" });
|
|
47
|
+
stampRootProcess("tunnel", {
|
|
48
|
+
pid: 78,
|
|
49
|
+
provider: "cloudflare",
|
|
50
|
+
startedAt: "2026-10-11T00:00:00.000Z",
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
expect(readRootProcesses().app?.pid).toBe(77);
|
|
54
|
+
expect(readRootProcesses().tunnel?.provider).toBe("cloudflare");
|
|
55
|
+
|
|
56
|
+
clearRootProcess("app");
|
|
57
|
+
expect(readRootProcesses().app).toBeUndefined();
|
|
58
|
+
// The sibling entry survives.
|
|
59
|
+
expect(readRootProcesses().tunnel?.pid).toBe(78);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("a record can name the assistant it fronts, for `cadet ps` nesting", () => {
|
|
63
|
+
stampRootProcess("tunnel", {
|
|
64
|
+
pid: 4242,
|
|
65
|
+
provider: "ngrok",
|
|
66
|
+
startedAt: "2026-10-11T00:00:00.000Z",
|
|
67
|
+
assistantId: "assistant-1",
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
expect(readRootProcesses().tunnel).toMatchObject({
|
|
71
|
+
pid: 4242,
|
|
72
|
+
provider: "ngrok",
|
|
73
|
+
assistantId: "assistant-1",
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("the records live at the lockfile root under their kind keys", () => {
|
|
78
|
+
stampRootProcess("app", { pid: 1, startedAt: "t" });
|
|
79
|
+
|
|
80
|
+
const raw = z
|
|
81
|
+
.object({
|
|
82
|
+
app: z.object({ pid: z.number(), startedAt: z.string() }),
|
|
83
|
+
})
|
|
84
|
+
.parse(
|
|
85
|
+
JSON.parse(
|
|
86
|
+
readFileSync(
|
|
87
|
+
join(process.env.CADET_LOCKFILE_DIR!, "lockfile.json"),
|
|
88
|
+
"utf-8",
|
|
89
|
+
),
|
|
90
|
+
),
|
|
91
|
+
);
|
|
92
|
+
expect(raw.app).toEqual({ pid: 1, startedAt: "t" });
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("clearing an absent entry is a no-op", () => {
|
|
96
|
+
clearRootProcess("tunnel");
|
|
97
|
+
expect(readRootProcesses()).toEqual({});
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
spyOn,
|
|
8
8
|
test,
|
|
9
9
|
} from "bun:test";
|
|
10
|
+
import type { GuardianTokenData } from "../lib/guardian-token.js";
|
|
10
11
|
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
11
12
|
import { tmpdir } from "node:os";
|
|
12
13
|
import { join } from "node:path";
|
|
@@ -49,10 +50,8 @@ mock.module("../lib/drain.js", () => ({
|
|
|
49
50
|
|
|
50
51
|
const realGuardianToken = { ...(await import("../lib/guardian-token.js")) };
|
|
51
52
|
const loadGuardianTokenMock = mock(
|
|
52
|
-
(_assistantId: string) =>
|
|
53
|
-
({ accessToken: "test-guardian-token" })
|
|
54
|
-
typeof realGuardianToken.loadGuardianToken
|
|
55
|
-
>,
|
|
53
|
+
(_assistantId: string): GuardianTokenData | null =>
|
|
54
|
+
makeGuardianTokenData({ accessToken: "test-guardian-token" }),
|
|
56
55
|
);
|
|
57
56
|
mock.module("../lib/guardian-token.js", () => ({
|
|
58
57
|
...realGuardianToken,
|
|
@@ -92,6 +91,7 @@ import {
|
|
|
92
91
|
DEFAULT_GATEWAY_PORT,
|
|
93
92
|
DEFAULT_QDRANT_PORT,
|
|
94
93
|
} from "../lib/constants.js";
|
|
94
|
+
import { makeGuardianTokenData } from "./helpers/guardian-token.js";
|
|
95
95
|
|
|
96
96
|
// Write a lockfile entry so the real resolveTargetAssistant() finds our test
|
|
97
97
|
// assistant without needing to mock the entire assistant-config module.
|
|
@@ -153,9 +153,9 @@ describe("sleep command", () => {
|
|
|
153
153
|
drainAssistantMock.mockReset();
|
|
154
154
|
drainAssistantMock.mockResolvedValue("drained");
|
|
155
155
|
loadGuardianTokenMock.mockReset();
|
|
156
|
-
loadGuardianTokenMock.mockReturnValue(
|
|
157
|
-
accessToken: "test-guardian-token",
|
|
158
|
-
|
|
156
|
+
loadGuardianTokenMock.mockReturnValue(
|
|
157
|
+
makeGuardianTokenData({ accessToken: "test-guardian-token" }),
|
|
158
|
+
);
|
|
159
159
|
resolveFreshBearerTokenMock.mockReset();
|
|
160
160
|
resolveFreshBearerTokenMock.mockImplementation(
|
|
161
161
|
async (_url, _id, bearerToken, _cloud) => bearerToken,
|
|
@@ -180,11 +180,11 @@ describe("sleep command", () => {
|
|
|
180
180
|
process.argv = ["bun", "cadet", "sleep", "sleep-test"];
|
|
181
181
|
|
|
182
182
|
const consoleError = spyOn(console, "error").mockImplementation(() => {});
|
|
183
|
-
const exitMock = mock((code?: number) => {
|
|
183
|
+
const exitMock = mock((code?: number | string | undefined): never => {
|
|
184
184
|
throw new Error(`process.exit:${code}`);
|
|
185
185
|
});
|
|
186
186
|
const originalExit = process.exit;
|
|
187
|
-
process.exit = exitMock
|
|
187
|
+
process.exit = exitMock;
|
|
188
188
|
|
|
189
189
|
try {
|
|
190
190
|
await expect(sleep()).rejects.toThrow("process.exit:1");
|
|
@@ -300,11 +300,11 @@ describe("sleep command", () => {
|
|
|
300
300
|
process.argv = ["bun", "cadet", "sleep", "sleep-test", "--wait"];
|
|
301
301
|
|
|
302
302
|
const consoleLog = spyOn(console, "log").mockImplementation(() => {});
|
|
303
|
-
const exitMock = mock((code?: number) => {
|
|
303
|
+
const exitMock = mock((code?: number | string | undefined): never => {
|
|
304
304
|
throw new Error(`process.exit:${code}`);
|
|
305
305
|
});
|
|
306
306
|
const originalExit = process.exit;
|
|
307
|
-
process.exit = exitMock
|
|
307
|
+
process.exit = exitMock;
|
|
308
308
|
try {
|
|
309
309
|
await expect(sleep()).rejects.toThrow("process.exit:130");
|
|
310
310
|
} finally {
|
|
@@ -350,11 +350,11 @@ describe("sleep command", () => {
|
|
|
350
350
|
process.argv = ["bun", "cadet", "sleep", "sleep-test", "--wait=abc"];
|
|
351
351
|
|
|
352
352
|
const consoleError = spyOn(console, "error").mockImplementation(() => {});
|
|
353
|
-
const exitMock = mock((code?: number) => {
|
|
353
|
+
const exitMock = mock((code?: number | string | undefined): never => {
|
|
354
354
|
throw new Error(`process.exit:${code}`);
|
|
355
355
|
});
|
|
356
356
|
const originalExit = process.exit;
|
|
357
|
-
process.exit = exitMock
|
|
357
|
+
process.exit = exitMock;
|
|
358
358
|
try {
|
|
359
359
|
await expect(sleep()).rejects.toThrow("process.exit:1");
|
|
360
360
|
expect(consoleError).toHaveBeenCalledWith(
|
|
@@ -484,11 +484,11 @@ describe("sleep command", () => {
|
|
|
484
484
|
process.argv = ["bun", "cadet", "sleep", "--all"];
|
|
485
485
|
|
|
486
486
|
const consoleError = spyOn(console, "error").mockImplementation(() => {});
|
|
487
|
-
const exitMock = mock((code?: number) => {
|
|
487
|
+
const exitMock = mock((code?: number | string | undefined): never => {
|
|
488
488
|
throw new Error(`process.exit:${code}`);
|
|
489
489
|
});
|
|
490
490
|
const originalExit = process.exit;
|
|
491
|
-
process.exit = exitMock
|
|
491
|
+
process.exit = exitMock;
|
|
492
492
|
|
|
493
493
|
try {
|
|
494
494
|
await expect(sleep()).rejects.toThrow("process.exit:1");
|
|
@@ -511,11 +511,11 @@ describe("sleep command", () => {
|
|
|
511
511
|
process.argv = ["bun", "cadet", "sleep", "--all"];
|
|
512
512
|
|
|
513
513
|
const consoleError = spyOn(console, "error").mockImplementation(() => {});
|
|
514
|
-
const exitMock = mock((code?: number) => {
|
|
514
|
+
const exitMock = mock((code?: number | string | undefined): never => {
|
|
515
515
|
throw new Error(`process.exit:${code}`);
|
|
516
516
|
});
|
|
517
517
|
const originalExit = process.exit;
|
|
518
|
-
process.exit = exitMock
|
|
518
|
+
process.exit = exitMock;
|
|
519
519
|
|
|
520
520
|
try {
|
|
521
521
|
await expect(sleep()).rejects.toThrow("process.exit:1");
|
|
@@ -532,11 +532,11 @@ describe("sleep command", () => {
|
|
|
532
532
|
process.argv = ["bun", "cadet", "sleep", "sleep-test", "--all"];
|
|
533
533
|
|
|
534
534
|
const consoleError = spyOn(console, "error").mockImplementation(() => {});
|
|
535
|
-
const exitMock = mock((code?: number) => {
|
|
535
|
+
const exitMock = mock((code?: number | string | undefined): never => {
|
|
536
536
|
throw new Error(`process.exit:${code}`);
|
|
537
537
|
});
|
|
538
538
|
const originalExit = process.exit;
|
|
539
|
-
process.exit = exitMock
|
|
539
|
+
process.exit = exitMock;
|
|
540
540
|
|
|
541
541
|
try {
|
|
542
542
|
await expect(sleep()).rejects.toThrow("process.exit:1");
|
|
@@ -35,7 +35,7 @@ describe("getBuilderManagedEnvKeys", () => {
|
|
|
35
35
|
expect(always.has(key)).toBe(true);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
expect(always.has("
|
|
38
|
+
expect(always.has("CADET_DISABLE_CLOUD")).toBe(false);
|
|
39
39
|
expect(always.has("CADET_DEVICE_ID")).toBe(false);
|
|
40
40
|
});
|
|
41
41
|
|
|
@@ -60,8 +60,8 @@ describe("getBuilderManagedEnvKeys", () => {
|
|
|
60
60
|
a.name.localeCompare(b.name),
|
|
61
61
|
);
|
|
62
62
|
expect(sorted).toEqual([
|
|
63
|
+
{ name: "CADET_CLOUD_URL", hostVar: "CADET_CLOUD_URL" },
|
|
63
64
|
{ name: "CADET_ENVIRONMENT", hostVar: "CADET_ENVIRONMENT" },
|
|
64
|
-
{ name: "CADET_PLATFORM_URL", hostVar: "CADET_PLATFORM_URL" },
|
|
65
65
|
{ name: "TUNNEL_BASE_URL", hostVar: "TUNNEL_BASE_URL" },
|
|
66
66
|
]);
|
|
67
67
|
});
|
|
@@ -76,8 +76,8 @@ describe("getBuilderManagedEnvKeys", () => {
|
|
|
76
76
|
expect(hostForwarded).toContainEqual({ name: envVar, hostVar: envVar });
|
|
77
77
|
}
|
|
78
78
|
expect(hostForwarded).toContainEqual({
|
|
79
|
-
name: "
|
|
80
|
-
hostVar: "
|
|
79
|
+
name: "CADET_CLOUD_URL",
|
|
80
|
+
hostVar: "CADET_CLOUD_URL",
|
|
81
81
|
});
|
|
82
82
|
});
|
|
83
83
|
|
|
@@ -126,7 +126,7 @@ describe("buildServiceRunArgs extra env routing", () => {
|
|
|
126
126
|
gatewayContainer: "test-gateway",
|
|
127
127
|
network: "test-net",
|
|
128
128
|
},
|
|
129
|
-
extraGatewayEnv: {
|
|
129
|
+
extraGatewayEnv: { CADET_DISABLE_CLOUD: "1" },
|
|
130
130
|
extraAssistantEnv: { FOO: "bar" },
|
|
131
131
|
};
|
|
132
132
|
|
|
@@ -134,19 +134,19 @@ describe("buildServiceRunArgs extra env routing", () => {
|
|
|
134
134
|
|
|
135
135
|
test("extraGatewayEnv lands only in gateway args", () => {
|
|
136
136
|
const gatewayArgs = runArgs.gateway();
|
|
137
|
-
expect(gatewayArgs).toContain("
|
|
137
|
+
expect(gatewayArgs).toContain("CADET_DISABLE_CLOUD=1");
|
|
138
138
|
expect(gatewayArgs).not.toContain("FOO=bar");
|
|
139
139
|
});
|
|
140
140
|
|
|
141
141
|
test("extraAssistantEnv lands only in assistant args", () => {
|
|
142
142
|
const assistantArgs = runArgs.assistant();
|
|
143
143
|
expect(assistantArgs).toContain("FOO=bar");
|
|
144
|
-
expect(assistantArgs).not.toContain("
|
|
144
|
+
expect(assistantArgs).not.toContain("CADET_DISABLE_CLOUD=1");
|
|
145
145
|
});
|
|
146
146
|
|
|
147
147
|
test("credential-executor args get neither extra env map", () => {
|
|
148
148
|
const cesArgs = runArgs["credential-executor"]();
|
|
149
|
-
expect(cesArgs).not.toContain("
|
|
149
|
+
expect(cesArgs).not.toContain("CADET_DISABLE_CLOUD=1");
|
|
150
150
|
expect(cesArgs).not.toContain("FOO=bar");
|
|
151
151
|
});
|
|
152
152
|
|