Zum Inhalt springen

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.

AspektEinzelnes Stack DeploymentProduct Deployment
DeployEin Stack pro VorgangAlle Stacks eines Produkts am Stück
VariablenPro Stack einzeln konfigurierenShared Variables einmal, dann pro Stack
FortschrittEin Stack mit eigener SessionEin SessionId, N Stacks mit Overall-Fortschritt
StatusKein aggregierter StatusProductDeploymentStatus mit State Machine
FehlerbehandlungStack-individuellContinueOnError — bei Teilfehlern weitermachen

Diese Anleitung zeigt den kompletten Workflow zum Deployment eines Multi-Stack Produkts über die Web-Oberfläche.

Navigieren Sie zum Stack Catalog. Multi-Stack Produkte werden mit einem Badge angezeigt, das die Anzahl der enthaltenen Stacks zeigt (z.B. „2 stacks”).

Multi-Stack Produkt im Katalog mit Stack-Badge


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.

Produkt-Detailseite mit Stack-Übersicht und Deploy All Button


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

Deployment-Konfigurationsseite mit Shared Variables und Stack-Konfiguration

In der Sidebar sehen Sie eine Zusammenfassung mit Product Info und dem Deploy All Stacks Button.


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

Split-View Deployment-Fortschritt mit Stack-Liste und Detail-Panel

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.


Nach Abschluss des Deployments wird das Ergebnis angezeigt — entweder Product Deployed Successfully oder Deployment Failed mit Details pro Stack.

Deployment-Ergebnis mit Stack-Resultaten

Von hier aus können Sie direkt zu den Deployments navigieren.


Auf der Deployments Seite erscheinen die einzelnen Stack-Deployments des Produkts. Jeder Stack kann separat verwaltet werden (Logs, Redeploy, etc.).

Deployments-Seite mit den deployed Product Stacks


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.

Produkt-Detailseite mit per-Stack Deployment Status


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.

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.

Stop und Restart Links auf der Product Deployment Detailseite


Klicken Sie auf Stop Containers, um zur Bestätigungsseite zu gelangen. Dort werden alle Stacks aufgelistet, die gestoppt werden.

Bestätigungsseite für Stop Containers

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

Ladeindikator während Stop-Vorgang

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

Ergebnis des Stop-Vorgangs


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.

Product Deployment im Stopped-Status mit orangenen Badges

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

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.

Bestätigungsseite für Restart Containers

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).

Ergebnis des Restart-Vorgangs


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

FeldTypPflichtBeschreibung
productIdstringJaProduct Group ID (z.B. e2e.test.platform)
stackDefinitionNamestringNeinEinzelnen Stack filtern (z.B. frontend)
environmentIdstringNeinEnvironment ID (Fallback: API Key env_id Claim)

Permissions: Hooks.StopContainers bzw. Hooks.RestartContainers

Terminal-Fenster
# Alle Container eines Produkts stoppen
curl -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 starten
curl -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"}'

Product Deployment arbeitet auf zwei Ebenen:

  1. ProductDeployment (Aggregate Root) — koordiniert alle Stacks, trackt den Gesamtstatus
  2. 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).


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)
StatusBedeutung
DeployingDeployment läuft, Stacks werden sequenziell ausgerollt
RunningAlle Stacks erfolgreich deployed und aktiv
PartiallyRunningEinige Stacks laufen, andere sind fehlgeschlagen
StoppedAlle Container bewusst gestoppt (über Stop Containers)
FailedDeployment komplett fehlgeschlagen
UpgradingUpgrade auf eine neue Version läuft
RemovingAlle Stacks werden entfernt
RemovedAlle Stacks entfernt (Endzustand)

Product Deployment unterstützt ein dreistufiges Variablen-System:

  1. Stack Defaults — in der Stack-Definition hinterlegte Standardwerte
  2. Shared Variables — produktübergreifende Variablen (z.B. Datenbank-Host)
  3. Per-Stack Overrides — stack-spezifische Überschreibungen

Die Priorität aufsteigend: Stack Defaults → Shared Variables → Per-Stack Overrides.


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:

FeldTypPflichtBeschreibung
productIdstringJaProdukt-ID aus dem Katalog (z.B. stacks:myproduct:1.0.0)
stackConfigsarrayJaKonfiguration für jeden Stack
stackConfigs[].stackIdstringJaStack-ID aus dem Katalog
stackConfigs[].deploymentStackNamestringJaName für das Deployment
stackConfigs[].variablesobjectNeinStack-spezifische Variablen
sharedVariablesobjectNeinProduktübergreifende Variablen
sessionIdstringNeinClient-generierte Session ID für SignalR Tracking
continueOnErrorbooleanNeinBei 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:

FeldTypPflichtBeschreibung
targetProductIdstringJaProdukt-ID der Zielversion (z.B. stacks:myproduct:2.0.0)
stackConfigsarrayJaKonfiguration für jeden Stack der Zielversion
stackConfigs[].stackIdstringJaStack-ID aus dem Zielprodukt
stackConfigs[].deploymentStackNamestringJaName für das Deployment
stackConfigs[].variablesobjectNeinStack-spezifische Variable-Overrides
sharedVariablesobjectNeinNeue Shared Variables für das Upgrade
sessionIdstringNeinClient-generierte Session ID für SignalR Tracking
continueOnErrorbooleanNeinBei 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):

FeldTypPflichtBeschreibung
stackNamesstring[]NeinNur 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):

FeldTypPflichtBeschreibung
stackNamesstring[]NeinNur 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):

FeldTypPflichtBeschreibung
sessionIdstringNeinClient-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
}
]
}

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 Running und PartiallyRunning Deployments
  • Transitions: RunningPartiallyRunning (wenn ein Stack ausfällt) und PartiallyRunningRunning (wenn alle Stacks sich erholen)

Während des Deployments sendet ReadyStackGo Echtzeit-Updates über SignalR:

  1. Vor jedem Stack: Fortschrittsmeldung mit Stack-Index und Gesamtanzahl
  2. Während jedes Stacks: Service-Level Fortschritt (vom bestehenden Stack Deployment)
  3. 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);

HTTP StatusBedeutung
200Erfolgreich
400Ungültige Anfrage (Produkt nicht gefunden, aktives Deployment existiert, leere Stack-Konfiguration)
401Nicht authentifiziert
403Nicht autorisiert (fehlende Permission)
404Product Deployment nicht gefunden (bei GET-Requests)
continueOnErrorBei Stack-Fehler
true (Standard)Nächster Stack wird trotzdem deployed. Endstatus: PartiallyRunning
falseDeployment wird abgebrochen. Verbleibende Stacks bleiben auf Pending. Endstatus: Failed