@rigkit/provider-freestyle 0.2.2 → 0.2.4
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 +10 -3
- package/package.json +8 -4
- package/src/host-auth.test.ts +375 -0
- package/src/host-auth.ts +591 -0
- package/src/index.ts +42 -76
- package/src/provider.test.ts +197 -105
- package/src/provider.ts +149 -396
- package/src/terminal-session.test.ts +42 -2
- package/src/terminal-session.ts +633 -308
- package/src/version.ts +1 -1
package/src/index.ts
CHANGED
|
@@ -3,36 +3,42 @@ import {
|
|
|
3
3
|
type WorkflowProviderDefinition,
|
|
4
4
|
} from "@rigkit/sdk";
|
|
5
5
|
import type { BaseProviderPlugin } from "@rigkit/engine";
|
|
6
|
-
import type { WorkflowProviderController } from "@rigkit/engine";
|
|
7
|
-
import { Freestyle } from "freestyle";
|
|
8
6
|
import * as z from "zod/v4-mini";
|
|
9
7
|
import { freestyleIdentityId, freestyleToken, freestyleTokenId } from "./auth.ts";
|
|
8
|
+
import {
|
|
9
|
+
createFreestyleAuthenticatedClient,
|
|
10
|
+
createFreestyleProxyFetch,
|
|
11
|
+
type FreestyleProviderAuthConfig,
|
|
12
|
+
} from "./host-auth.ts";
|
|
10
13
|
import {
|
|
11
14
|
FREESTYLE_PROVIDER_ID,
|
|
12
15
|
FREESTYLE_TERMINAL_PROVIDER_ID,
|
|
13
16
|
createFreestyleTerminalController,
|
|
14
17
|
createFreestyleWorkflowProvider,
|
|
15
|
-
isFreestyleVmSnapshotRef,
|
|
16
18
|
} from "./provider.ts";
|
|
17
|
-
import type { FreestyleRuntime, FreestyleTerminalRuntime
|
|
18
|
-
import { createFreestyleStore } from "./store.ts";
|
|
19
|
+
import type { FreestyleRuntime, FreestyleTerminalRuntime } from "./provider.ts";
|
|
19
20
|
|
|
20
21
|
const freestyleProviderConfigSchema = z.object({
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
auth: z.optional(z.object({
|
|
23
|
+
apiKey: z.optional(z.string().check(z.minLength(1))),
|
|
24
|
+
profile: z.optional(z.string().check(z.minLength(1))),
|
|
25
|
+
teamId: z.optional(z.string().check(z.minLength(1))),
|
|
26
|
+
apiUrl: z.optional(z.string().check(z.minLength(1))),
|
|
27
|
+
dashboardUrl: z.optional(z.string().check(z.minLength(1))),
|
|
28
|
+
stackApiUrl: z.optional(z.string().check(z.minLength(1))),
|
|
29
|
+
stackAppUrl: z.optional(z.string().check(z.minLength(1))),
|
|
30
|
+
stackProjectId: z.optional(z.string().check(z.minLength(1))),
|
|
31
|
+
stackPublishableClientKey: z.optional(z.string().check(z.minLength(1))),
|
|
32
|
+
})),
|
|
27
33
|
});
|
|
28
34
|
|
|
29
35
|
export type FreestyleProviderConfig = z.output<typeof freestyleProviderConfigSchema>;
|
|
36
|
+
export type { FreestyleProviderAuthConfig };
|
|
30
37
|
|
|
31
38
|
export type FreestyleProviderDefinition = WorkflowProviderDefinition<
|
|
32
39
|
typeof FREESTYLE_PROVIDER_ID,
|
|
33
40
|
FreestyleProviderConfig,
|
|
34
|
-
FreestyleRuntime
|
|
35
|
-
FreestyleWorkspaceContext
|
|
41
|
+
FreestyleRuntime
|
|
36
42
|
>;
|
|
37
43
|
|
|
38
44
|
export type FreestyleTerminalProviderDefinition = WorkflowProviderDefinition<
|
|
@@ -42,7 +48,7 @@ export type FreestyleTerminalProviderDefinition = WorkflowProviderDefinition<
|
|
|
42
48
|
>;
|
|
43
49
|
|
|
44
50
|
export function provider(
|
|
45
|
-
config: FreestyleProviderDefinition["config"],
|
|
51
|
+
config: FreestyleProviderDefinition["config"] = {},
|
|
46
52
|
): FreestyleProviderDefinition {
|
|
47
53
|
return defineProvider(FREESTYLE_PROVIDER_ID, config, freestyleProviderPlugin);
|
|
48
54
|
}
|
|
@@ -60,63 +66,18 @@ export const defineFreestyleProvider = provider;
|
|
|
60
66
|
|
|
61
67
|
export const freestyleProviderPlugin: BaseProviderPlugin = {
|
|
62
68
|
providerId: FREESTYLE_PROVIDER_ID,
|
|
63
|
-
createProvider({ provider,
|
|
69
|
+
async createProvider({ provider, hostStorage, local }) {
|
|
64
70
|
const config = parseFreestyleProviderConfig(provider.config);
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const savedIdentity = store.getIdentity();
|
|
76
|
-
if (savedIdentity) {
|
|
77
|
-
return createFreestyleWorkflowProvider({
|
|
78
|
-
apiKey,
|
|
79
|
-
identityId: savedIdentity.identityId,
|
|
80
|
-
token: savedIdentity.token,
|
|
81
|
-
vm,
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const client = new Freestyle({ apiKey });
|
|
86
|
-
const { identity, identityId } = await client.identities.create();
|
|
87
|
-
const { token, tokenId } = await identity.tokens.create();
|
|
88
|
-
const createdIdentity = store.saveIdentity({
|
|
89
|
-
identityId: freestyleIdentityId(identityId),
|
|
90
|
-
tokenId: freestyleTokenId(tokenId),
|
|
91
|
-
token: freestyleToken(token),
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
return createFreestyleWorkflowProvider({
|
|
95
|
-
apiKey,
|
|
96
|
-
identityId: createdIdentity.identityId,
|
|
97
|
-
token: createdIdentity.token,
|
|
98
|
-
vm,
|
|
99
|
-
});
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
providerId: FREESTYLE_PROVIDER_ID,
|
|
104
|
-
runtime: async (context) => await (await load()).runtime(context),
|
|
105
|
-
validateArtifact: (ref) => isFreestyleVmSnapshotRef(ref),
|
|
106
|
-
workspace: {
|
|
107
|
-
canUse: (ref) => isFreestyleVmSnapshotRef(ref),
|
|
108
|
-
createWorkspace: async (sourceRef, input) =>
|
|
109
|
-
await (await load()).workspace!.createWorkspace(sourceRef, input),
|
|
110
|
-
deleteWorkspace: async (workspace) =>
|
|
111
|
-
await (await load()).workspace!.deleteWorkspace(workspace),
|
|
112
|
-
snapshotWorkspace: async (workspace) =>
|
|
113
|
-
await (await load()).workspace!.snapshotWorkspace(workspace),
|
|
114
|
-
ssh: async (workspaceOrResourceId, options) =>
|
|
115
|
-
await (await load()).workspace!.ssh(workspaceOrResourceId, options),
|
|
116
|
-
workspaceContext: async (workspace) =>
|
|
117
|
-
await (await load()).workspace!.workspaceContext!(workspace),
|
|
118
|
-
},
|
|
119
|
-
} satisfies WorkflowProviderController<FreestyleRuntime, FreestyleWorkspaceContext>;
|
|
71
|
+
const authenticated = await createFreestyleAuthenticatedClient({
|
|
72
|
+
auth: config.auth,
|
|
73
|
+
hostStorage,
|
|
74
|
+
local,
|
|
75
|
+
});
|
|
76
|
+
return createFreestyleWorkflowProvider({
|
|
77
|
+
client: authenticated.client,
|
|
78
|
+
identityId: authenticated.identityId,
|
|
79
|
+
token: authenticated.token,
|
|
80
|
+
});
|
|
120
81
|
},
|
|
121
82
|
};
|
|
122
83
|
|
|
@@ -127,6 +88,10 @@ export const freestyleTerminalPlugin: BaseProviderPlugin = {
|
|
|
127
88
|
},
|
|
128
89
|
};
|
|
129
90
|
|
|
91
|
+
export {
|
|
92
|
+
createFreestyleAuthenticatedClient,
|
|
93
|
+
createFreestyleProxyFetch,
|
|
94
|
+
} from "./host-auth.ts";
|
|
130
95
|
export {
|
|
131
96
|
freestyleIdentityId,
|
|
132
97
|
freestyleToken,
|
|
@@ -138,22 +103,23 @@ export {
|
|
|
138
103
|
export {
|
|
139
104
|
FREESTYLE_PROVIDER_ID,
|
|
140
105
|
FREESTYLE_TERMINAL_PROVIDER_ID,
|
|
141
|
-
createFreestyleProvider,
|
|
142
106
|
createFreestyleTerminalController,
|
|
143
107
|
createFreestyleWorkflowController,
|
|
144
108
|
createFreestyleWorkflowProvider,
|
|
145
|
-
isFreestyleVmSnapshotRef,
|
|
146
109
|
} from "./provider.ts";
|
|
147
110
|
export { createFreestyleStore } from "./store.ts";
|
|
148
111
|
export { createFreestyleTerminalSession } from "./terminal-session.ts";
|
|
149
112
|
export { RIGKIT_PROVIDER_FREESTYLE_VERSION } from "./version.ts";
|
|
113
|
+
export { Freestyle, VmBaseImage, VmSpec, VmWith, VmWithInstance } from "freestyle";
|
|
114
|
+
export type { CreateVmOptions } from "freestyle";
|
|
150
115
|
export type {
|
|
116
|
+
FreestyleCmuxSshOptions,
|
|
117
|
+
FreestyleCmuxSshOptionsInput,
|
|
151
118
|
FreestyleRuntime,
|
|
119
|
+
FreestyleSdkVm,
|
|
120
|
+
FreestyleSshInput,
|
|
152
121
|
FreestyleTerminalRuntime,
|
|
153
|
-
|
|
154
|
-
FreestyleVmRuntime,
|
|
155
|
-
FreestyleVmSnapshotRef,
|
|
156
|
-
FreestyleWorkspaceContext,
|
|
122
|
+
FreestyleVscodeUrlOptions,
|
|
157
123
|
} from "./provider.ts";
|
|
158
124
|
export type { FreestyleGitRelationship, FreestyleIdentity } from "./store.ts";
|
|
159
125
|
|
package/src/provider.test.ts
CHANGED
|
@@ -1,127 +1,219 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import { afterEach, describe, expect, test } from "bun:test";
|
|
2
|
+
import { Freestyle } from "freestyle";
|
|
3
|
+
import type { ProviderInteractionSession, ProviderRuntimeContext } from "@rigkit/engine";
|
|
4
|
+
import { freestyleIdentityId, freestyleToken } from "./auth.ts";
|
|
5
|
+
import {
|
|
6
|
+
buildInteractiveSshCommand,
|
|
7
|
+
createFreestyleTerminalController,
|
|
8
|
+
createFreestyleWorkflowController,
|
|
9
|
+
} from "./provider.ts";
|
|
10
|
+
|
|
11
|
+
const previousFetch = globalThis.fetch;
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
globalThis.fetch = previousFetch;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe("Freestyle provider host adapters", () => {
|
|
18
|
+
test("creates SSH options and grants VM access internally", async () => {
|
|
19
|
+
const requests: string[] = [];
|
|
20
|
+
globalThis.fetch = (async (resource, init) => {
|
|
21
|
+
requests.push(`${init?.method ?? "GET"} ${String(resource)}`);
|
|
22
|
+
return Response.json({});
|
|
23
|
+
}) as typeof fetch;
|
|
24
|
+
|
|
25
|
+
const runtime = await createFreestyleWorkflowController({
|
|
26
|
+
client: new Freestyle({ apiKey: "test-key" }),
|
|
27
|
+
identityId: freestyleIdentityId("identity-stream"),
|
|
28
|
+
token: freestyleToken("token"),
|
|
29
|
+
}).runtime(providerContext());
|
|
30
|
+
|
|
31
|
+
await expect(runtime.createSSHOptions({ vmId: "vm-stream" })).resolves.toEqual({
|
|
32
|
+
kind: "ssh",
|
|
33
|
+
host: "vm-ssh.freestyle.sh",
|
|
34
|
+
username: "vm-stream+root",
|
|
35
|
+
auth: { type: "token", token: "token" },
|
|
36
|
+
command: "ssh vm-stream+root:token@vm-ssh.freestyle.sh",
|
|
37
|
+
});
|
|
38
|
+
expect(requests).toContain("POST https://api.freestyle.sh/identity/v1/identities/identity-stream/permissions/vm/vm-stream");
|
|
16
39
|
});
|
|
17
40
|
|
|
18
|
-
test("
|
|
19
|
-
|
|
20
|
-
|
|
41
|
+
test("creates cmux ssh options with Freestyle-owned ssh settings", async () => {
|
|
42
|
+
globalThis.fetch = (async () => Response.json({})) as unknown as typeof fetch;
|
|
43
|
+
|
|
44
|
+
const runtime = await createFreestyleWorkflowController({
|
|
45
|
+
client: new Freestyle({ apiKey: "test-key" }),
|
|
46
|
+
identityId: freestyleIdentityId("identity-stream"),
|
|
47
|
+
token: freestyleToken("token"),
|
|
48
|
+
}).runtime(providerContext());
|
|
49
|
+
|
|
50
|
+
const ssh = await runtime.cmux.createSshOptions({
|
|
51
|
+
vmId: "vm-stream",
|
|
52
|
+
sshOptions: ["ServerAliveInterval=15"],
|
|
53
|
+
skipDaemonBootstrap: true,
|
|
21
54
|
});
|
|
22
55
|
|
|
23
|
-
expect(
|
|
24
|
-
|
|
56
|
+
expect(ssh).toEqual({
|
|
57
|
+
kind: "ssh",
|
|
58
|
+
destination: "vm-stream+root,token@vm-ssh.freestyle.sh",
|
|
59
|
+
skipDaemonBootstrap: true,
|
|
60
|
+
sshOptions: [
|
|
61
|
+
"StrictHostKeyChecking=no",
|
|
62
|
+
"UserKnownHostsFile=/dev/null",
|
|
63
|
+
"LogLevel=ERROR",
|
|
64
|
+
"IdentitiesOnly=yes",
|
|
65
|
+
"IdentityFile=/dev/null",
|
|
66
|
+
"ControlMaster=no",
|
|
67
|
+
"ServerAliveInterval=15",
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("treats existing VM permissions as idempotent for cmux ssh options", async () => {
|
|
73
|
+
const calls: string[] = [];
|
|
74
|
+
const runtime = await createFreestyleWorkflowController({
|
|
75
|
+
client: {
|
|
76
|
+
identities: {
|
|
77
|
+
ref: () => ({
|
|
78
|
+
permissions: {
|
|
79
|
+
vms: {
|
|
80
|
+
grant: async () => {
|
|
81
|
+
calls.push("grant");
|
|
82
|
+
throw new Error("PERMISSION_ALREADY_EXISTS: Permission already exists");
|
|
83
|
+
},
|
|
84
|
+
update: async () => {
|
|
85
|
+
calls.push("update");
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
}),
|
|
90
|
+
},
|
|
91
|
+
} as unknown as Freestyle,
|
|
92
|
+
identityId: freestyleIdentityId("identity-stream"),
|
|
93
|
+
token: freestyleToken("token"),
|
|
94
|
+
}).runtime(providerContext());
|
|
95
|
+
|
|
96
|
+
await expect(runtime.cmux.createSshOptions({ vmId: "vm-stream" })).resolves.toMatchObject({
|
|
97
|
+
destination: "vm-stream+root,token@vm-ssh.freestyle.sh",
|
|
98
|
+
});
|
|
99
|
+
expect(calls).toEqual(["grant", "update"]);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("creates VS Code URLs using the Freestyle ssh authority", async () => {
|
|
103
|
+
globalThis.fetch = (async () => Response.json({})) as unknown as typeof fetch;
|
|
104
|
+
|
|
105
|
+
const runtime = await createFreestyleWorkflowController({
|
|
106
|
+
client: new Freestyle({ apiKey: "test-key" }),
|
|
107
|
+
identityId: freestyleIdentityId("identity-stream"),
|
|
108
|
+
token: freestyleToken("token"),
|
|
109
|
+
}).runtime(providerContext());
|
|
110
|
+
|
|
111
|
+
const url = await runtime.vscode.createUrl({ vmId: "vm-stream", cwd: "/workspace/site" });
|
|
112
|
+
|
|
113
|
+
expect(url).toBe(
|
|
114
|
+
"vscode://vscode-remote/ssh-remote+vm-stream%2Broot%3Atoken%40vm-ssh.freestyle.sh/workspace/site?windowId=_blank",
|
|
115
|
+
);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("honors explicit SSH users", async () => {
|
|
119
|
+
globalThis.fetch = (async () => Response.json({})) as unknown as typeof fetch;
|
|
120
|
+
|
|
121
|
+
const runtime = await createFreestyleWorkflowController({
|
|
122
|
+
client: new Freestyle({ apiKey: "test-key" }),
|
|
123
|
+
identityId: freestyleIdentityId("identity-stream"),
|
|
124
|
+
token: freestyleToken("token"),
|
|
125
|
+
}).runtime(providerContext());
|
|
126
|
+
|
|
127
|
+
await expect(runtime.createSSHOptions({ vmId: "vm-stream", user: "ubuntu" })).resolves.toMatchObject({
|
|
128
|
+
username: "vm-stream+ubuntu",
|
|
129
|
+
command: "ssh vm-stream+ubuntu:token@vm-ssh.freestyle.sh",
|
|
130
|
+
});
|
|
25
131
|
});
|
|
26
132
|
|
|
27
|
-
test("
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
chunks.push(chunk);
|
|
133
|
+
test("runs terminal commands as SSH remote commands instead of typed startup input", async () => {
|
|
134
|
+
let html = "";
|
|
135
|
+
const runtime = await createFreestyleTerminalController().runtime({
|
|
136
|
+
...providerContext(),
|
|
137
|
+
interaction: {
|
|
138
|
+
present: async <Result>(session: ProviderInteractionSession<Result>) => {
|
|
139
|
+
const response = await fetch(session.url);
|
|
140
|
+
html = await response.text();
|
|
141
|
+
session.stop();
|
|
142
|
+
return { finished: true } as Result;
|
|
143
|
+
},
|
|
39
144
|
},
|
|
40
145
|
});
|
|
41
146
|
|
|
42
|
-
expect(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
command: "printf ready",
|
|
147
|
+
await expect(runtime.open("GitHub auth", {
|
|
148
|
+
ssh: {
|
|
149
|
+
kind: "ssh",
|
|
150
|
+
host: "vm-ssh.freestyle.sh",
|
|
151
|
+
username: "vm-stream+root",
|
|
152
|
+
auth: { type: "token", token: "token" },
|
|
153
|
+
command: "ssh vm-stream+root:token@vm-ssh.freestyle.sh",
|
|
50
154
|
},
|
|
155
|
+
command: "gh auth login --hostname github.com",
|
|
156
|
+
})).resolves.toEqual({ finished: true });
|
|
157
|
+
|
|
158
|
+
expect(html).toContain("gh auth login --hostname github.com");
|
|
159
|
+
expect(html).toContain("const startupInput = null;");
|
|
160
|
+
expect(html).toContain("const canFinishWhileRunning = false;");
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test("can keep an SSH terminal open after a successful remote command", () => {
|
|
164
|
+
const command = buildInteractiveSshCommand(
|
|
51
165
|
{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
166
|
+
kind: "ssh",
|
|
167
|
+
host: "vm-ssh.freestyle.sh",
|
|
168
|
+
username: "vm-stream+root",
|
|
169
|
+
auth: { type: "token", token: "token" },
|
|
170
|
+
command: "ssh vm-stream+root:token@vm-ssh.freestyle.sh",
|
|
57
171
|
},
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
172
|
+
"gh auth status -h github.com",
|
|
173
|
+
{ keepOpenAfterCommand: true },
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
expect(command).toContain("gh auth status -h github.com");
|
|
177
|
+
expect(command).toContain("status=$?");
|
|
178
|
+
expect(command).toContain('if [ "$status" -ne 0 ]; then exit "$status"; fi');
|
|
179
|
+
expect(command).toContain('exec "${SHELL:-/bin/bash}" -l');
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test("allows finishing while a keep-open SSH command is running", async () => {
|
|
183
|
+
let html = "";
|
|
184
|
+
const runtime = await createFreestyleTerminalController().runtime({
|
|
185
|
+
...providerContext(),
|
|
186
|
+
interaction: {
|
|
187
|
+
present: async <Result>(session: ProviderInteractionSession<Result>) => {
|
|
188
|
+
const response = await fetch(session.url);
|
|
189
|
+
html = await response.text();
|
|
190
|
+
session.stop();
|
|
191
|
+
return { finished: true } as Result;
|
|
192
|
+
},
|
|
63
193
|
},
|
|
64
|
-
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
await runtime.open("GitHub auth", {
|
|
197
|
+
ssh: {
|
|
198
|
+
kind: "ssh",
|
|
199
|
+
host: "vm-ssh.freestyle.sh",
|
|
200
|
+
username: "vm-stream+root",
|
|
201
|
+
auth: { type: "token", token: "token" },
|
|
202
|
+
command: "ssh vm-stream+root:token@vm-ssh.freestyle.sh",
|
|
203
|
+
},
|
|
204
|
+
command: "gh auth login --hostname github.com",
|
|
205
|
+
keepOpenAfterCommand: true,
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
expect(html).toContain("const canFinishWhileRunning = true;");
|
|
65
209
|
});
|
|
66
210
|
});
|
|
67
211
|
|
|
68
|
-
|
|
69
|
-
kind: "ssh",
|
|
70
|
-
host: "localhost",
|
|
71
|
-
username: "root",
|
|
72
|
-
auth: { type: "token", token: "token" },
|
|
73
|
-
command: "ssh vm-stream",
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
class StreamingProvider implements BaseDevMachineProvider<FreestyleWorkspaceContext> {
|
|
77
|
-
readonly providerId = "freestyle";
|
|
78
|
-
|
|
79
|
-
async createVm(): Promise<VmHandle> {
|
|
80
|
-
return { vmId: "vm-stream" };
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async createVmFromSnapshot(): Promise<VmHandle> {
|
|
84
|
-
return { vmId: "vm-stream" };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async exec(_vm: VmHandle, _command: string, options?: ExecOptions): Promise<ExecResult> {
|
|
88
|
-
await options?.onOutput?.({ stream: "stdout", data: "ready\n" });
|
|
89
|
-
return { stdout: "ready\n", stderr: "", exitCode: 0, ok: true };
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async readFile(): Promise<string> {
|
|
93
|
-
return "";
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async writeFile(): Promise<void> {}
|
|
97
|
-
|
|
98
|
-
async snapshot(): Promise<{ snapshotId: string; sourceVmId: string }> {
|
|
99
|
-
return { snapshotId: "snap-stream", sourceVmId: "vm-stream" };
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async ssh(): Promise<SshConnection> {
|
|
103
|
-
return sshConnection;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async workspaceContext(): Promise<FreestyleWorkspaceContext> {
|
|
107
|
-
return {
|
|
108
|
-
ssh: sshConnection,
|
|
109
|
-
host: sshConnection.host,
|
|
110
|
-
username: sshConnection.username,
|
|
111
|
-
vscodeAuthority: "root@localhost",
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
async deleteVm(): Promise<void> {}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function providerContext(events: WorkflowEvent[]): ProviderRuntimeContext {
|
|
212
|
+
function providerContext(): ProviderRuntimeContext {
|
|
119
213
|
return {
|
|
120
214
|
workflow: "workflow",
|
|
121
215
|
nodePath: "workflow.step",
|
|
122
|
-
emit: (
|
|
123
|
-
events.push(event);
|
|
124
|
-
},
|
|
216
|
+
emit: () => {},
|
|
125
217
|
interaction: {
|
|
126
218
|
present: async () => {
|
|
127
219
|
throw new Error("unexpected interaction");
|