create-interview-cockpit 0.17.3 → 0.18.0
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/template/client/src/App.tsx +3 -0
- package/template/client/src/api.ts +83 -8
- package/template/client/src/components/GithubActionsLabModal.tsx +746 -0
- package/template/client/src/components/InfraLabModal.tsx +993 -262
- package/template/client/src/components/LabsPanel.tsx +71 -5
- package/template/client/src/components/Sidebar.tsx +400 -14
- package/template/client/src/components/WorkspaceSwitcher.tsx +4 -0
- package/template/client/src/enterpriseLocalLab.ts +921 -0
- package/template/client/src/githubActionsLab.ts +287 -0
- package/template/client/src/infraLab.ts +378 -6
- package/template/client/src/reactLab.ts +409 -0
- package/template/client/src/store.ts +83 -10
- package/template/client/src/types.ts +27 -3
- package/template/client/tsconfig.tsbuildinfo +1 -1
- package/template/cockpit.json +1 -1
- package/template/server/src/gha-runner.ts +468 -0
- package/template/server/src/google-drive.ts +35 -24
- package/template/server/src/index.ts +241 -10
- package/template/server/src/infra-runner.ts +321 -30
- package/template/server/src/storage.ts +3 -1
package/package.json
CHANGED
|
@@ -9,6 +9,7 @@ import DocRefModal from "./components/DocRefModal";
|
|
|
9
9
|
import AiSettingsModal from "./components/AiSettingsModal";
|
|
10
10
|
import CodeRunnerModal from "./components/CodeRunnerModal";
|
|
11
11
|
import InfraLabModal from "./components/InfraLabModal";
|
|
12
|
+
import GithubActionsLabModal from "./components/GithubActionsLabModal";
|
|
12
13
|
import DeploymentLabModal from "./components/DeploymentLabModal";
|
|
13
14
|
import CanvasLabModal from "./components/CanvasLabModal";
|
|
14
15
|
import {
|
|
@@ -44,6 +45,7 @@ export default function App() {
|
|
|
44
45
|
closeSettings,
|
|
45
46
|
showCodeRunner,
|
|
46
47
|
showInfraLab,
|
|
48
|
+
showGhaLab,
|
|
47
49
|
showDeploymentLab,
|
|
48
50
|
showCanvasLab,
|
|
49
51
|
closeCodeRunner,
|
|
@@ -191,6 +193,7 @@ export default function App() {
|
|
|
191
193
|
{showSettings && <AiSettingsModal />}
|
|
192
194
|
{showCodeRunner && <CodeRunnerModal />}
|
|
193
195
|
{showInfraLab && <InfraLabModal />}
|
|
196
|
+
{showGhaLab && <GithubActionsLabModal />}
|
|
194
197
|
{showDeploymentLab && <DeploymentLabModal />}
|
|
195
198
|
{showCanvasLab && <CanvasLabModal />}
|
|
196
199
|
</div>
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
ContextFileOrigin,
|
|
6
6
|
WorkspacesRegistry,
|
|
7
7
|
InfraLabWorkspace,
|
|
8
|
+
GithubActionsLabWorkspace,
|
|
8
9
|
} from "./types";
|
|
9
10
|
|
|
10
11
|
const BASE = "/api";
|
|
@@ -79,8 +80,8 @@ export interface InfraRunListItem {
|
|
|
79
80
|
startedAt: string;
|
|
80
81
|
completedAt: string;
|
|
81
82
|
durationMs: number;
|
|
82
|
-
provider: "aws";
|
|
83
|
-
executionMode: "plan-only" | "localstack";
|
|
83
|
+
provider: "aws" | "docker";
|
|
84
|
+
executionMode: "plan-only" | "localstack" | "docker";
|
|
84
85
|
diagnostics: InfraDiagnostic[];
|
|
85
86
|
planSummary?: InfraPlanSummary;
|
|
86
87
|
error?: string;
|
|
@@ -243,6 +244,19 @@ export async function updateQuestion(
|
|
|
243
244
|
return res.json();
|
|
244
245
|
}
|
|
245
246
|
|
|
247
|
+
export async function copyQuestion(
|
|
248
|
+
id: string,
|
|
249
|
+
data: { parentQuestionId?: string | null; targetTopicId?: string } = {},
|
|
250
|
+
): Promise<Question[]> {
|
|
251
|
+
const res = await fetch(`${BASE}/questions/${id}/copy`, {
|
|
252
|
+
method: "POST",
|
|
253
|
+
headers: { "Content-Type": "application/json" },
|
|
254
|
+
body: JSON.stringify(data),
|
|
255
|
+
});
|
|
256
|
+
if (!res.ok) throw new Error(await res.text());
|
|
257
|
+
return res.json();
|
|
258
|
+
}
|
|
259
|
+
|
|
246
260
|
export async function deleteQuestion(id: string): Promise<void> {
|
|
247
261
|
await fetch(`${BASE}/questions/${id}`, { method: "DELETE" });
|
|
248
262
|
}
|
|
@@ -470,6 +484,60 @@ export async function streamInfraCommand(
|
|
|
470
484
|
}
|
|
471
485
|
}
|
|
472
486
|
|
|
487
|
+
// ─── GitHub Actions Lab ──────────────────────────────────────────────────
|
|
488
|
+
|
|
489
|
+
export type GhaStreamMessage =
|
|
490
|
+
| { type: "output"; kind: "stdout" | "stderr" | "info"; text: string }
|
|
491
|
+
| { type: "complete"; runId: string; exitCode: number; durationMs: number }
|
|
492
|
+
| { type: "error"; error: string };
|
|
493
|
+
|
|
494
|
+
export async function streamGhaCommand(
|
|
495
|
+
input: {
|
|
496
|
+
questionId?: string;
|
|
497
|
+
fileId?: string;
|
|
498
|
+
label?: string;
|
|
499
|
+
command: string;
|
|
500
|
+
workspace: GithubActionsLabWorkspace;
|
|
501
|
+
},
|
|
502
|
+
onMessage: (message: GhaStreamMessage) => void,
|
|
503
|
+
): Promise<void> {
|
|
504
|
+
const res = await fetch(`${BASE}/gha/run-stream`, {
|
|
505
|
+
method: "POST",
|
|
506
|
+
headers: { "Content-Type": "application/json" },
|
|
507
|
+
body: JSON.stringify(input),
|
|
508
|
+
});
|
|
509
|
+
if (!res.ok || !res.body) {
|
|
510
|
+
const err = await res.text().catch(() => "act run failed");
|
|
511
|
+
throw new Error(err || "act run failed");
|
|
512
|
+
}
|
|
513
|
+
const reader = res.body.getReader();
|
|
514
|
+
const decoder = new TextDecoder();
|
|
515
|
+
let buffer = "";
|
|
516
|
+
|
|
517
|
+
const flushBuffer = () => {
|
|
518
|
+
const events = buffer.replace(/\r/g, "").split("\n\n");
|
|
519
|
+
buffer = events.pop() ?? "";
|
|
520
|
+
for (const event of events) {
|
|
521
|
+
if (!event.trim()) continue;
|
|
522
|
+
const payload = event
|
|
523
|
+
.split("\n")
|
|
524
|
+
.filter((line) => line.startsWith("data:"))
|
|
525
|
+
.map((line) => line.slice(5).trimStart())
|
|
526
|
+
.join("\n");
|
|
527
|
+
if (!payload) continue;
|
|
528
|
+
onMessage(JSON.parse(payload) as GhaStreamMessage);
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
while (true) {
|
|
533
|
+
const { value, done } = await reader.read();
|
|
534
|
+
buffer += decoder.decode(value ?? new Uint8Array(), { stream: !done });
|
|
535
|
+
flushBuffer();
|
|
536
|
+
if (done) break;
|
|
537
|
+
}
|
|
538
|
+
if (buffer.trim()) flushBuffer();
|
|
539
|
+
}
|
|
540
|
+
|
|
473
541
|
export async function fetchInfraRun(runId: string): Promise<InfraRunDetails> {
|
|
474
542
|
const res = await fetch(`${BASE}/infra/runs/${encodeURIComponent(runId)}`);
|
|
475
543
|
if (!res.ok) throw new Error(await res.text());
|
|
@@ -664,12 +732,19 @@ export async function activateWorkspaceApi(
|
|
|
664
732
|
return res.json();
|
|
665
733
|
}
|
|
666
734
|
|
|
667
|
-
export
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
735
|
+
export type SyncWorkspaceResult =
|
|
736
|
+
| { needsAuth: true; authUrl: string }
|
|
737
|
+
| {
|
|
738
|
+
needsAuth?: false;
|
|
739
|
+
topicsUpserted: number;
|
|
740
|
+
filesImported: number;
|
|
741
|
+
filesSkipped: number;
|
|
742
|
+
errors: string[];
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
export async function syncWorkspaceApi(
|
|
746
|
+
id: string,
|
|
747
|
+
): Promise<SyncWorkspaceResult> {
|
|
673
748
|
const res = await fetch(`${BASE}/workspaces/${id}/sync`, { method: "POST" });
|
|
674
749
|
return res.json();
|
|
675
750
|
}
|