Live deploy console: stream compose up output to the browser (0.22.0)
Deploying a local stack from the editor now opens a console modal that streams
the `docker compose up -d` output (image pulls, container creation) live over a
new `/ws/deploy/{stack_id}` WebSocket, replacing the blind "Deploying…" spinner.
The compose subprocess keeps running server-side if the modal is closed early;
the same audit entry + start/error notification as the REST start path is recorded.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5b59f5e8f9
commit
7592085ce9
@@ -7,6 +7,7 @@ import { Button, Card, Input } from "@/components/ui";
|
||||
import { EditorHelperPanel } from "@/components/stacks/EditorHelperPanel";
|
||||
import { EnvEditor } from "@/components/env/EnvEditor";
|
||||
import { PortConflictDialog } from "@/components/stacks/PortConflictDialog";
|
||||
import { DeployConsole } from "@/components/stacks/DeployConsole";
|
||||
import { stacksApi } from "@/api/stacks";
|
||||
import { agentsApi } from "@/api/agents";
|
||||
import { portsApi, type PortConflict } from "@/api/ports";
|
||||
@@ -40,6 +41,7 @@ export function StackEditor() {
|
||||
const [conflicts, setConflicts] = useState<PortConflict[] | null>(null);
|
||||
const [checking, setChecking] = useState(false);
|
||||
const [host, setHost] = useState("local");
|
||||
const [deployId, setDeployId] = useState<string | null>(null);
|
||||
|
||||
const existing = useQuery({
|
||||
queryKey: ["stack", id],
|
||||
@@ -97,9 +99,10 @@ export function StackEditor() {
|
||||
qc.invalidateQueries({ queryKey: ["stack", stackId] });
|
||||
toast.success("Saved");
|
||||
if (deploy && stackId) {
|
||||
const t = toast.loading("Deploying…");
|
||||
await stacksApi.start(stackId);
|
||||
toast.success("Deployed ✓", { id: t });
|
||||
// Stream the deploy live in the console modal instead of a blind
|
||||
// spinner; navigation happens when the user closes it.
|
||||
setDeployId(stackId);
|
||||
return;
|
||||
}
|
||||
navigate(`/stacks/${stackId}`);
|
||||
} catch (err) {
|
||||
@@ -244,6 +247,19 @@ export function StackEditor() {
|
||||
onCancel={() => setConflicts(null)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{deployId && (
|
||||
<DeployConsole
|
||||
stackId={deployId}
|
||||
onClose={() => {
|
||||
const sid = deployId;
|
||||
setDeployId(null);
|
||||
qc.invalidateQueries({ queryKey: ["stacks"] });
|
||||
qc.invalidateQueries({ queryKey: ["stack", sid] });
|
||||
navigate(`/stacks/${sid}`);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user