feat(ops): /operations endpoint + page — live jobs, queue depth, failures

GET /api/v1/operations aggregates active deployments, per-service
deploy-queue depth via Queue.Snapshot(), 24h deployment failures,
cron runs and backups scoped to the caller's projects (admins see all).

Frontend /operations page (Operate nav) shows in-flight count, queued
depth, failures and backup stats with live refetch while deploys are
active. CLI `containr operations` + MCP containr_operations_get.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-10-09 09:51:38 +02:00
1 parent f499678964
commit f524d95894
16 files changed
+613 -4

No files matched your search

+39
View File
@@ -1827,6 +1827,45 @@ export async function testWebhook(id: string): Promise<void> {
await requestJson(`/webhooks/${id}/test`, { method: 'POST', body: JSON.stringify({}) });
}
export type OperationsView = {
active_deployments: Array<{
id: string;
service_id: string;
service_name: string;
project_name: string;
status: string;
image: string;
error?: string | null;
started_at?: string | null;
completed_at?: string | null;
created_at: string;
}>;
deploy_queue: Array<{ service_id: string; running: boolean; queued: number }>;
recent_failures: OperationsView['active_deployments'];
cron_runs: Array<{
id: string;
job_name: string;
schedule: string;
status: string;
started_at: string;
finished_at?: string | null;
error?: string | null;
}>;
backups: Array<{
id: string;
database_id: string;
database_name: string;
status: string;
size: string;
created_at: string;
completed_at?: string | null;
}>;
};
export async function getOperations(): Promise<OperationsView> {
return requestJson<OperationsView>('/operations');
}
export function serviceStatusClass(status: ServiceStatus): string {
switch (status) {
case 'running':