diff --git a/web/lib/api.ts b/web/lib/api.ts index b0e3e2b..e8cc3f7 100644 --- a/web/lib/api.ts +++ b/web/lib/api.ts @@ -132,6 +132,65 @@ export interface ServerWithKeys extends Server { keys: (Assignment & { key: Key })[]; } +export interface WorkflowStep { + step_id: string; + name: string; + description: string; + interpreter: "bash" | "powershell"; + script: string; + declared_outputs: string[]; + secret_refs: string[]; +} + +export interface WorkflowStepRef { + step_id: string; + order: number; + on_failure: "stop" | "continue" | "retry"; + max_retries: number; + overrides?: { script?: string; secret_refs?: string[] }; +} + +export interface Workflow { + workflow_id: string; + name: string; + target_server_ids: string[]; + steps: WorkflowStepRef[]; +} + +export interface StepRun { + order: number; + name: string; + status: string; + attempts: number; + exit_code: number; + stdout: string; + stderr: string; + output_env: Record; + started_at?: string; + finished_at?: string; +} + +export interface ServerRun { + server_id: string; + hostname: string; + status: string; + run_env: Record; + steps: StepRun[]; + started_at?: string; + finished_at?: string; +} + +export interface WorkflowRun { + run_id: string; + workflow_id: string; + name: string; + status: string; + triggered_by: string; + started_at: string; + finished_at?: string; + server_runs: ServerRun[]; +} + class ApiError extends Error { constructor( public status: number, @@ -324,4 +383,73 @@ export const api = { body: JSON.stringify(body), }); }, + + // Steps + listSteps(): Promise { + return request("/steps"); + }, + + createStep(s: Partial): Promise { + return request("/steps", { + method: "POST", + body: JSON.stringify(s), + }); + }, + + updateStep(stepId: string, s: Partial): Promise { + return request(`/steps/${stepId}`, { + method: "PUT", + body: JSON.stringify(s), + }); + }, + + deleteStep(stepId: string): Promise { + return request(`/steps/${stepId}`, { method: "DELETE" }); + }, + + // Workflows + listWorkflows(): Promise { + return request("/workflows"); + }, + + getWorkflow(workflowId: string): Promise { + return request(`/workflows/${workflowId}`); + }, + + createWorkflow(w: Partial): Promise { + return request("/workflows", { + method: "POST", + body: JSON.stringify(w), + }); + }, + + updateWorkflow(workflowId: string, w: Partial): Promise { + return request(`/workflows/${workflowId}`, { + method: "PUT", + body: JSON.stringify(w), + }); + }, + + deleteWorkflow(workflowId: string): Promise { + return request(`/workflows/${workflowId}`, { method: "DELETE" }); + }, + + runWorkflow(workflowId: string): Promise<{ run_id: string }> { + return request<{ run_id: string }>(`/workflows/${workflowId}/run`, { + method: "POST", + }); + }, + + listRuns(workflowId: string): Promise { + return request(`/workflows/${workflowId}/runs`); + }, + + // Runs + getRun(runId: string): Promise { + return request(`/runs/${runId}`); + }, + + cancelRun(runId: string): Promise { + return request(`/runs/${runId}/cancel`, { method: "POST" }); + }, };