Product Deployment
Bei Multi-Stack Produkten wie z.B. einer Microservices-Architektur mit 10+ Stacks mussten bisher alle Stacks einzeln deployed werden. Mit Product Deployment wird das gesamte Produkt in einem Vorgang ausgerollt — mit gemeinsamen Variablen, Fortschrittsanzeige und koordiniertem Lifecycle.
Übersicht
Abschnitt betitelt „Übersicht“| Aspekt | Einzelnes Stack Deployment | Product Deployment |
|---|---|---|
| Deploy | Ein Stack pro Vorgang | Alle Stacks eines Produkts am Stück |
| Variablen | Pro Stack einzeln konfigurieren | Shared Variables einmal, dann pro Stack |
| Fortschritt | Ein Stack mit eigener Session | Ein SessionId, N Stacks mit Overall-Fortschritt |
| Status | Kein aggregierter Status | ProductDeploymentStatus mit State Machine |
| Fehlerbehandlung | Stack-individuell | ContinueOnError — bei Teilfehlern weitermachen |
Schritt für Schritt: Produkt deployen
Abschnitt betitelt „Schritt für Schritt: Produkt deployen“Diese Anleitung zeigt den kompletten Workflow zum Deployment eines Multi-Stack Produkts über die Web-Oberfläche.
Schritt 1: Produkt im Katalog finden
Abschnitt betitelt „Schritt 1: Produkt im Katalog finden“Navigieren Sie zum Stack Catalog. Multi-Stack Produkte werden mit einem Badge angezeigt, das die Anzahl der enthaltenen Stacks zeigt (z.B. „2 stacks”).

Schritt 2: Produkt-Details ansehen
Abschnitt betitelt „Schritt 2: Produkt-Details ansehen“Klicken Sie auf View Details, um die Produkt-Detailseite zu öffnen. Hier sehen Sie alle enthaltenen Stacks mit ihren Beschreibungen und den Deploy All Button.

Schritt 3: Deployment konfigurieren
Abschnitt betitelt „Schritt 3: Deployment konfigurieren“Nach Klick auf Deploy All gelangen Sie zur Konfigurationsseite. Hier konfigurieren Sie:
- Shared Variables — Werte die an alle Stacks weitergegeben werden (z.B. Log Level, Datenbank-Host)
- Stack-Konfiguration — Pro Stack können Variablen individuell angepasst werden (Accordion-Ansicht)
- Continue on Error — Legt fest ob bei einem Stack-Fehler die verbleibenden Stacks trotzdem deployed werden

In der Sidebar sehen Sie eine Zusammenfassung mit Product Info und dem Deploy All Stacks Button.
Schritt 4: Deployment verfolgen (Split-View)
Abschnitt betitelt „Schritt 4: Deployment verfolgen (Split-View)“Nach Klick auf Deploy All Stacks wechselt die Ansicht in den Split-View Modus:
- Links: Kompakte Stack-Liste mit Echtzeit-Statusindikatoren (Pending, Deploying, Running, Failed)
- Rechts: Detaillierte Fortschrittsanzeige für den ausgewählten Stack — Progress Bar, Service-Zähler, Init Container Logs

Die Stacks werden sequenziell deployed. Der aktuell laufende Stack wird automatisch ausgewählt. Sie können jederzeit auf einen anderen Stack klicken, um dessen Fortschritt oder Ergebnis einzusehen.
Schritt 5: Ergebnis prüfen
Abschnitt betitelt „Schritt 5: Ergebnis prüfen“Nach Abschluss des Deployments wird das Ergebnis angezeigt — entweder Product Deployed Successfully oder Deployment Failed mit Details pro Stack.

Von hier aus können Sie direkt zu den Deployments navigieren.
Schritt 6: Deployments verwalten
Abschnitt betitelt „Schritt 6: Deployments verwalten“Auf der Deployments Seite erscheinen die einzelnen Stack-Deployments des Produkts. Jeder Stack kann separat verwaltet werden (Logs, Redeploy, etc.).

Schritt 7: Status auf der Produkt-Detailseite
Abschnitt betitelt „Schritt 7: Status auf der Produkt-Detailseite“Wenn Sie zum Katalog zurückkehren und die Produkt-Detailseite erneut aufrufen, sehen Sie den Deployment Status für jeden einzelnen Stack — inklusive Health-Checks.

Container Control: Stop & Restart
Abschnitt betitelt „Container Control: Stop & Restart“Laufende Product Deployments können über die Detailseite gestoppt und neu gestartet werden. Beim Stoppen wechselt das Deployment in den Status Stopped — sowohl auf Produkt- als auch auf Stack-Ebene. Dies ist nützlich für Wartungsfenster, Debugging oder um Ressourcen temporär freizugeben.
Stop & Restart Links
Abschnitt betitelt „Stop & Restart Links“Auf der Product Deployment Detailseite werden bei operativen Deployments (Status Running oder PartiallyRunning) die Links Stop Containers und Restart Containers angezeigt. Bei gestoppten Deployments (Status Stopped) ist nur Restart Containers verfügbar.

Container stoppen
Abschnitt betitelt „Container stoppen“Klicken Sie auf Stop Containers, um zur Bestätigungsseite zu gelangen. Dort werden alle Stacks aufgelistet, die gestoppt werden.

Nach Bestätigung wird der Vorgang ausgeführt. Ein Ladeindikator zeigt den Fortschritt an.

Das Ergebnis wird als Feedback-Seite angezeigt — grün bei Erfolg, rot bei Fehlern.

Stopped-Status
Abschnitt betitelt „Stopped-Status“Nach erfolgreichem Stoppen wechselt das Product Deployment in den Status Stopped. Auf der Detailseite werden sowohl das Produkt als auch alle Stacks mit einem orangenen Stopped-Badge angezeigt.

Im Stopped-Status sind folgende Aktionen verfügbar:
- Restart Containers — Container wieder starten, wechselt zurück zu
Running - Upgrade — Auf eine neue Version upgraden
- Remove — Deployment entfernen
Container neu starten
Abschnitt betitelt „Container neu starten“Klicken Sie auf Restart Containers, um alle Container sequenziell zu stoppen und danach wieder zu starten. Dies funktioniert sowohl für laufende als auch für gestoppte Deployments.

Nach Abschluss zeigt die Ergebnis-Seite den Status an. Bei einem Restart aus dem Stopped-Status wechselt das Deployment zurück zu Running (bzw. PartiallyRunning bei Teilerfolg).

Container Control via Hook
Abschnitt betitelt „Container Control via Hook“Container können auch über die Hook-API gesteuert werden — ideal für CI/CD Pipelines oder externe Automations-Tools.
Stop: POST /api/hooks/stop-containers
Restart: POST /api/hooks/restart-containers
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
productId | string | Ja | Product Group ID (z.B. e2e.test.platform) |
stackDefinitionName | string | Nein | Einzelnen Stack filtern (z.B. frontend) |
environmentId | string | Nein | Environment ID (Fallback: API Key env_id Claim) |
Permissions: Hooks.StopContainers bzw. Hooks.RestartContainers
# Alle Container eines Produkts stoppencurl -X POST http://localhost:8080/api/hooks/stop-containers \ -H "X-Api-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{"productId": "e2e.test.platform"}'
# Einzelnen Stack neu startencurl -X POST http://localhost:8080/api/hooks/restart-containers \ -H "X-Api-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{"productId": "e2e.test.platform", "stackDefinitionName": "frontend"}'Konzept: Zwei-Ebenen-Architektur
Abschnitt betitelt „Konzept: Zwei-Ebenen-Architektur“Product Deployment arbeitet auf zwei Ebenen:
- ProductDeployment (Aggregate Root) — koordiniert alle Stacks, trackt den Gesamtstatus
- Deployment (pro Stack) — die bestehende Stack-Deployment-Logik mit Container-Operations
┌─────────────────────────────────────────────┐│ ProductDeployment ││ Status: Running │ Version: 3.1.0 ││ ││ ┌─ Stack: infrastructure (Order: 0) ───┐ ││ │ Status: Running │──→ Deployment (infra-stack)│ └──────────────────────────────────────┘ ││ ││ ┌─ Stack: identity-access (Order: 1) ──┐ ││ │ Status: Running │──→ Deployment (identity-stack)│ └──────────────────────────────────────┘ ││ ││ ┌─ Stack: business (Order: 2) ─────────┐ ││ │ Status: Running │──→ Deployment (business-stack)│ └──────────────────────────────────────┘ │└─────────────────────────────────────────────┘Die Stacks werden sequenziell in Manifest-Reihenfolge deployed — das respektiert Abhängigkeiten zwischen Stacks (z.B. Datenbank vor Application Server).
Status-Lifecycle
Abschnitt betitelt „Status-Lifecycle“Product Deployments durchlaufen folgende Status:
Deploying ──→ Running (alle Stacks erfolgreich) ──→ PartiallyRunning (einige Stacks fehlgeschlagen) ──→ Failed (alle Stacks fehlgeschlagen)
Running ──→ Upgrading ──→ Running / PartiallyRunning / Failed ──→ Removing ──→ Removed (terminal) ──→ Stopped ──→ Running (Restart erfolgreich) ──→ PartiallyRunning (Restart teilweise) ──→ Removing / Upgrading
PartiallyRunning ──→ Stopped (Container stoppen)
Failed ──→ Upgrading (erneuter Versuch mit neuer Version) ──→ Removing (Aufräumen)| Status | Bedeutung |
|---|---|
Deploying | Deployment läuft, Stacks werden sequenziell ausgerollt |
Running | Alle Stacks erfolgreich deployed und aktiv |
PartiallyRunning | Einige Stacks laufen, andere sind fehlgeschlagen |
Stopped | Alle Container bewusst gestoppt (über Stop Containers) |
Failed | Deployment komplett fehlgeschlagen |
Upgrading | Upgrade auf eine neue Version läuft |
Removing | Alle Stacks werden entfernt |
Removed | Alle Stacks entfernt (Endzustand) |
Variablen-Konfiguration
Abschnitt betitelt „Variablen-Konfiguration“Product Deployment unterstützt ein dreistufiges Variablen-System:
- Stack Defaults — in der Stack-Definition hinterlegte Standardwerte
- Shared Variables — produktübergreifende Variablen (z.B. Datenbank-Host)
- Per-Stack Overrides — stack-spezifische Überschreibungen
Die Priorität aufsteigend: Stack Defaults → Shared Variables → Per-Stack Overrides.
API-Endpunkte
Abschnitt betitelt „API-Endpunkte“POST /api/environments/{environmentId}/product-deployments
Abschnitt betitelt „POST /api/environments/{environmentId}/product-deployments“Startet ein neues Product Deployment. Alle Stacks des Produkts werden sequenziell deployed.
Permission: Deployments.Create
Request:
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
productId | string | Ja | Produkt-ID aus dem Katalog (z.B. stacks:myproduct:1.0.0) |
stackConfigs | array | Ja | Konfiguration für jeden Stack |
stackConfigs[].stackId | string | Ja | Stack-ID aus dem Katalog |
stackConfigs[].deploymentStackName | string | Ja | Name für das Deployment |
stackConfigs[].variables | object | Nein | Stack-spezifische Variablen |
sharedVariables | object | Nein | Produktübergreifende Variablen |
sessionId | string | Nein | Client-generierte Session ID für SignalR Tracking |
continueOnError | boolean | Nein | Bei Fehler weitermachen (Standard: true) |
{ "productId": "stacks:ams.project:3.1.0", "stackConfigs": [ { "stackId": "stacks:ams.project:infrastructure:3.1.0", "deploymentStackName": "ams-infra", "variables": { "DB_PASSWORD": "secret123" } }, { "stackId": "stacks:ams.project:identity:3.1.0", "deploymentStackName": "ams-identity", "variables": {} }, { "stackId": "stacks:ams.project:business:3.1.0", "deploymentStackName": "ams-business", "variables": {} } ], "sharedVariables": { "DB_HOST": "postgres.local", "REDIS_URL": "redis://cache:6379" }, "continueOnError": true}Response (200):
{ "success": true, "productDeploymentId": "a1b2c3d4-...", "productName": "ams.project", "productVersion": "3.1.0", "status": "Running", "sessionId": "product-ams.project-20260217120000000", "stackResults": [ { "stackName": "infrastructure", "stackDisplayName": "Infrastructure", "success": true, "deploymentId": "d1e2f3...", "deploymentStackName": "ams-infra", "serviceCount": 3 }, { "stackName": "identity", "stackDisplayName": "Identity Access", "success": true, "deploymentId": "g4h5i6...", "deploymentStackName": "ams-identity", "serviceCount": 2 } ]}Fehlerantwort (400) — Produkt nicht gefunden:
{ "success": false, "message": "Product 'nonexistent:product:1.0.0' not found in catalog."}GET /api/environments/{environmentId}/product-deployments
Abschnitt betitelt „GET /api/environments/{environmentId}/product-deployments“Listet alle Product Deployments in einer Umgebung auf (ohne Removed).
Permission: Deployments.Read
Response (200):
{ "success": true, "productDeployments": [ { "productDeploymentId": "a1b2c3d4-...", "productGroupId": "stacks:ams.project", "productName": "ams.project", "productDisplayName": "AMS Project", "productVersion": "3.1.0", "status": "Running", "createdAt": "2026-02-17T12:00:00Z", "completedAt": "2026-02-17T12:05:30Z", "totalStacks": 3, "completedStacks": 3, "failedStacks": 0, "canUpgrade": true, "canRemove": true } ]}GET /api/environments/{environmentId}/product-deployments/{id}
Abschnitt betitelt „GET /api/environments/{environmentId}/product-deployments/{id}“Gibt ein spezifisches Product Deployment mit allen Stack-Details zurück.
Permission: Deployments.Read
Response (200):
{ "productDeploymentId": "a1b2c3d4-...", "environmentId": "env-123", "productGroupId": "stacks:ams.project", "productId": "stacks:ams.project:3.1.0", "productName": "ams.project", "productDisplayName": "AMS Project", "productVersion": "3.1.0", "status": "Running", "createdAt": "2026-02-17T12:00:00Z", "completedAt": "2026-02-17T12:05:30Z", "continueOnError": true, "totalStacks": 3, "completedStacks": 3, "failedStacks": 0, "upgradeCount": 0, "canUpgrade": true, "canRemove": true, "durationSeconds": 330.5, "stacks": [ { "stackName": "infrastructure", "stackDisplayName": "Infrastructure", "stackId": "stacks:ams.project:infrastructure:3.1.0", "deploymentId": "d1e2f3...", "deploymentStackName": "ams-infra", "status": "Running", "startedAt": "2026-02-17T12:00:01Z", "completedAt": "2026-02-17T12:02:15Z", "order": 0, "serviceCount": 3, "isNewInUpgrade": false } ], "sharedVariables": { "DB_HOST": "postgres.local", "REDIS_URL": "redis://cache:6379" }}GET /api/environments/{environmentId}/product-deployments/by-product/{groupId}
Abschnitt betitelt „GET /api/environments/{environmentId}/product-deployments/by-product/{groupId}“Gibt das aktive Product Deployment für eine bestimmte Product Group zurück.
Permission: Deployments.Read
Die Response hat das gleiche Format wie GET .../{id}.
POST /api/environments/{environmentId}/product-deployments/{id}/upgrade
Abschnitt betitelt „POST /api/environments/{environmentId}/product-deployments/{id}/upgrade“Aktualisiert ein laufendes Product Deployment auf eine neue Version. Alle Stacks werden sequenziell mit Variable-Merging aus dem bestehenden Deployment aktualisiert.
Permission: Deployments.Write
Request:
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
targetProductId | string | Ja | Produkt-ID der Zielversion (z.B. stacks:myproduct:2.0.0) |
stackConfigs | array | Ja | Konfiguration für jeden Stack der Zielversion |
stackConfigs[].stackId | string | Ja | Stack-ID aus dem Zielprodukt |
stackConfigs[].deploymentStackName | string | Ja | Name für das Deployment |
stackConfigs[].variables | object | Nein | Stack-spezifische Variable-Overrides |
sharedVariables | object | Nein | Neue Shared Variables für das Upgrade |
sessionId | string | Nein | Client-generierte Session ID für SignalR Tracking |
continueOnError | boolean | Nein | Bei Fehler weitermachen (Standard: true) |
Response (200):
{ "success": true, "productDeploymentId": "new-id-...", "productName": "ams.project", "previousVersion": "3.1.0", "newVersion": "4.0.0", "status": "Running", "sessionId": "product-upgrade-ams.project-20260217...", "stackResults": [ { "stackName": "infrastructure", "stackDisplayName": "Infrastructure", "success": true, "deploymentId": "d1e2f3...", "serviceCount": 3, "isNewInUpgrade": false } ]}GET /api/environments/{environmentId}/product-deployments/{id}/upgrade/check
Abschnitt betitelt „GET /api/environments/{environmentId}/product-deployments/{id}/upgrade/check“Prüft ob ein Upgrade für ein Product Deployment verfügbar ist, indem die deployed Version mit dem Katalog verglichen wird.
Permission: Deployments.Read
Response (200):
{ "success": true, "upgradeAvailable": true, "currentVersion": "3.1.0", "latestVersion": "4.0.0", "latestProductId": "stacks:ams.project:4.0.0", "availableVersions": [ { "version": "4.0.0", "productId": "stacks:ams.project:4.0.0", "sourceId": "stacks", "stackCount": 4 }, { "version": "3.2.0", "productId": "stacks:ams.project:3.2.0", "sourceId": "stacks", "stackCount": 3 } ], "newStacks": ["monitoring"], "removedStacks": [], "canUpgrade": true}POST /api/environments/{environmentId}/product-deployments/{id}/stop-containers
Abschnitt betitelt „POST /api/environments/{environmentId}/product-deployments/{id}/stop-containers“Stoppt alle laufenden Container eines Product Deployments. Optional kann auf einzelne Stacks gefiltert werden.
Permission: Deployments.Execute
Request (optionaler Body):
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
stackNames | string[] | Nein | Nur diese Stacks stoppen (Standard: alle) |
Response (200):
{ "success": true, "message": "Stopped 2 of 2 stacks successfully.", "totalStacks": 2, "stoppedStacks": 2, "failedStacks": 0, "stackResults": [ { "stackName": "frontend", "success": true, "containersStopped": 1 }, { "stackName": "backend", "success": true, "containersStopped": 2 } ]}POST /api/environments/{environmentId}/product-deployments/{id}/restart-containers
Abschnitt betitelt „POST /api/environments/{environmentId}/product-deployments/{id}/restart-containers“Startet alle Container eines Product Deployments neu (Stop + Start pro Stack sequenziell).
Permission: Deployments.Execute
Request (optionaler Body):
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
stackNames | string[] | Nein | Nur diese Stacks neu starten (Standard: alle) |
Response (200):
{ "success": true, "message": "Restarted 2 of 2 stacks successfully.", "totalStacks": 2, "restartedStacks": 2, "failedStacks": 0, "stackResults": [ { "stackName": "frontend", "success": true, "containersStopped": 1, "containersStarted": 1 }, { "stackName": "backend", "success": true, "containersStopped": 2, "containersStarted": 2 } ]}DELETE /api/environments/{environmentId}/product-deployments/{id}
Abschnitt betitelt „DELETE /api/environments/{environmentId}/product-deployments/{id}“Entfernt ein Product Deployment mit allen Stacks. Stacks werden in umgekehrter Manifest-Reihenfolge entfernt (Abhängigkeiten zuletzt).
Permission: Deployments.Delete
Request (optionaler Body):
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
sessionId | string | Nein | Client-generierte Session ID für SignalR Tracking |
Response (200):
{ "success": true, "productDeploymentId": "a1b2c3d4-...", "productName": "ams.project", "status": "Removed", "sessionId": "product-remove-ams.project-20260217...", "stackResults": [ { "stackName": "business", "stackDisplayName": "Business", "success": true, "serviceCount": 4 }, { "stackName": "identity", "stackDisplayName": "Identity Access", "success": true, "serviceCount": 2 }, { "stackName": "infrastructure", "stackDisplayName": "Infrastructure", "success": true, "serviceCount": 3 } ]}Health Sync
Abschnitt betitelt „Health Sync“Ein Hintergrund-Service synchronisiert periodisch den ProductDeployment-Status mit den zugrunde liegenden Deployment-Aggregaten. Dies korrigiert Abweichungen, wenn Container außerhalb der ReadyStackGo-Orchestrierung abstürzen oder sich erholen (z.B. Docker startet einen Container neu).
- Sync-Intervall: alle 60 Sekunden (nach 20 Sekunden Initialverzögerung)
- Scope: nur
RunningundPartiallyRunningDeployments - Transitions:
Running→PartiallyRunning(wenn ein Stack ausfällt) undPartiallyRunning→Running(wenn alle Stacks sich erholen)
Echtzeit-Fortschritt via SignalR
Abschnitt betitelt „Echtzeit-Fortschritt via SignalR“Während des Deployments sendet ReadyStackGo Echtzeit-Updates über SignalR:
- Vor jedem Stack: Fortschrittsmeldung mit Stack-Index und Gesamtanzahl
- Während jedes Stacks: Service-Level Fortschritt (vom bestehenden Stack Deployment)
- Nach Abschluss: Gesamtergebnis mit Statusmeldung
Verbinden Sie sich über die DeploymentHub und abonnieren Sie die Session ID:
const connection = new signalR.HubConnectionBuilder() .withUrl("/deploymentHub") .build();
connection.on("DeploymentProgress", (data) => { console.log(`${data.phase}: ${data.message} (${data.percentComplete}%)`);});
await connection.start();await connection.invoke("SubscribeToDeployment", sessionId);Fehlerbehandlung
Abschnitt betitelt „Fehlerbehandlung“| HTTP Status | Bedeutung |
|---|---|
| 200 | Erfolgreich |
| 400 | Ungültige Anfrage (Produkt nicht gefunden, aktives Deployment existiert, leere Stack-Konfiguration) |
| 401 | Nicht authentifiziert |
| 403 | Nicht autorisiert (fehlende Permission) |
| 404 | Product Deployment nicht gefunden (bei GET-Requests) |
ContinueOnError-Verhalten
Abschnitt betitelt „ContinueOnError-Verhalten“continueOnError | Bei Stack-Fehler |
|---|---|
true (Standard) | Nächster Stack wird trotzdem deployed. Endstatus: PartiallyRunning |
false | Deployment wird abgebrochen. Verbleibende Stacks bleiben auf Pending. Endstatus: Failed |