mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-07-26 11:49:16 +00:00
feat: health-gated updates and rollback readiness (#1354)
* feat: classify stack deploy and update failures with suggested next actions Failed deploy and update responses now carry a failure classification (cause category, headline, and suggested next step) derived from the compose error output. The recovery panel and chip render the classification and include it in copied diagnostics, and gateway-style failures surface as a node-unreachable cause. * feat: add update and rollback readiness reports for stacks Before a manual update, Sencho now shows an advisory readiness verdict computed from the stored preflight result, open drift findings, live container health, the pending image change, the rollback backup slot, and node disk headroom. The Stack Dossier gains a rollback readiness section that states what a rollback can restore and explicitly discloses that volume and bind-mounted data are not covered. Toolbar and sidebar updates now share one update path, and admins can create a fleet snapshot from the readiness dialog before updating. Nodes that do not advertise the capability keep the direct update flow. * feat: observe stack health after updates with a post-deploy health gate After a deploy or update succeeds, Sencho now watches the stack for a configurable observation window and records a passed, failed, or unknown verdict: containers must stay running, healthchecks must report healthy, and restart loops or disappearing containers fail the gate. The deploy panel shows the observation live and holds off auto-closing until the verdict lands, a failed gate surfaces the existing recovery actions including rollback, and the stack timeline records update started and gate verdict events. Scheduled, webhook, bulk, and git-source updates are gated the same way; rollbacks and installs are deliberately not. The gate is observational only and can be tuned or disabled per node under host alert settings. * docs: document health-gated updates and rollback readiness New operator page covering the update readiness dialog, the post-update health gate and its settings, the rollback readiness disclosure, and classified failures, with cross-links from the atomic deployments and deploy progress pages. The API reference gains the readiness and health-gate endpoints, the healthGateId success field, and the failure classification schema on deploy and update error responses. * feat: withhold the success verdict while the health gate observes An update used to show a green Succeeded that a failed health gate then contradicted moments later. The deploy modal now reports Verifying health while the gate observes, shows success only when the gate passes, and makes a failed or unknown gate the headline result; success toasts soften to a verifying message while a gate runs. The mobile recovery card groups its actions behind one bottom-right Take action menu so it stays compact on a phone, with the classified cause still visible on the card. A successful image update now also counts as the last known-good marker in rollback readiness, and the docs gain screenshots of the readiness dialog, gate states, dossier section, and settings. * fix: harden log format strings and the env existence path check Log calls that interpolated the stack name into the console format string now use constant format strings with placeholder arguments, and envExists validates path containment inline at its filesystem access, matching the established patterns used elsewhere in the same files. * test: adapt deploy modal success specs to the post-deploy health gate The deploy feedback modal now withholds its success verdict while the health gate observes the new containers, showing "Verifying health" until the gate passes. The two success-path E2E tests waited for "Succeeded" within the gate's 90s default window and timed out. Shorten the observation window to the 15s minimum for these tests via the settings API, assert the verify-then-succeed sequence the modal actually renders, and restore the default window afterward so the test value does not leak into later runs. * fix: serialize health gate polling and harden gate observation Address race conditions in the post-update health gate found in review. Backend: the gate poller used setInterval, so a Docker observe slower than the 5s tick could overlap the next poll and corrupt the restart and missing-container accounting, and a wedged socket could leave a poll pending forever. Polling is now single-flight: each cycle self-schedules the next only after it settles, and the observe is bounded by an 8s timeout so a hung probe counts as a poll error and resolves the gate unknown after three in a row. Frontend: the gate poller could overlap requests, letting a slow earlier "observing" response overwrite an already-applied terminal verdict. It is now single-flight with a terminal latch, so a late response can never roll the UI back from passed or failed. Also reject a non-digit nodeId on the snapshot coverage route instead of letting parseInt coerce it, document that turning off the deploy progress panel opts out of the live gate UI while the gate still runs server-side, and add gate-coverage tests for the webhook, git source, and auto-update apply paths plus the new single-flight, observe-timeout, and recovery cases.
This commit is contained in:
@@ -116,6 +116,7 @@
|
||||
"pages": [
|
||||
"features/deploy-progress",
|
||||
"features/atomic-deployments",
|
||||
"features/health-gated-updates",
|
||||
"features/deploy-enforcement",
|
||||
"features/git-sources",
|
||||
"features/app-store",
|
||||
|
||||
@@ -5,7 +5,7 @@ description: Wrap every deploy and update in a backup, a 3-second health probe,
|
||||
|
||||
Sencho wraps every protected deploy in a four-step safety net: it copies the current `compose.yaml` and `.env` to a writable backup directory, runs the requested compose action, waits 3 seconds for the new containers to settle, then checks them for a non-zero exit code. If any container has crashed, Sencho restores the backed-up files and re-deploys automatically.
|
||||
|
||||
The same backup also powers the **Rollback** action in the stack editor, so you can roll a stack back to its last good configuration on demand.
|
||||
The same backup also powers the **Rollback** action in the stack editor, so you can roll a stack back to its last good configuration on demand. To see in advance whether that rollback would actually help, and to watch container health for longer than the 3-second probe, see [Health-Gated Updates](/features/health-gated-updates).
|
||||
|
||||
## How it works
|
||||
|
||||
@@ -54,7 +54,7 @@ A restore is a faithful revert, not an overlay. Sencho replaces the compose file
|
||||
A user without the `stack:deploy` permission will still see the menu entry; the rejection comes from the backend with a permission error after they click. Ask an admin to grant `stack:deploy` through **Settings · Roles & Access** if that happens.
|
||||
</Accordion>
|
||||
<Accordion title="The deploy succeeded but a service crashed seconds later">
|
||||
The health probe is a 3-second window after `docker compose up -d` returns. Crashes that happen after that window are out of scope for atomic rollback by design, because Sencho cannot tell whether a late exit is a real failure or a normal restart. For ongoing health, use **Auto-Heal Policies** to restart unhealthy containers automatically and **Alert Rules** to page you when a container exits unexpectedly.
|
||||
The health probe is a 3-second window after `docker compose up -d` returns. Crashes that happen after that window are out of scope for atomic rollback by design, because Sencho cannot tell whether a late exit is a real failure or a normal restart. The [health gate](/features/health-gated-updates) covers exactly this period: it observes the stack for a configurable window after the update, records a verdict on the stack timeline, and offers a manual rollback when containers do not stay healthy. For ongoing health beyond that, use **Auto-Heal Policies** to restart unhealthy containers automatically and **Alert Rules** to page you when a container exits unexpectedly.
|
||||
</Accordion>
|
||||
<Accordion title="The deploy progress modal showed 'Rollback failed - manual intervention may be required'">
|
||||
This message means the auto-rollback attempted to restore the backup and re-deploy, but the restore step or the re-deploy itself errored out. The backup files are still at `<DATA_DIR>/backups/<stack>/`. To recover:
|
||||
|
||||
@@ -58,6 +58,8 @@ Click **Raw output** in the footer to expand a 200 px raw terminal panel beneath
|
||||
|
||||
When an action completes successfully, the status indicator switches to `Succeeded · closes in <n>s` and a 4-second countdown begins. Hover anywhere over the modal to pause the countdown; moving the cursor away restarts a fresh 4 seconds. Clicking **Close** dismisses the modal immediately.
|
||||
|
||||
When the [health gate](/features/health-gated-updates) is observing the stack after a deploy or update, the modal withholds the success verdict: the status indicator shows **Verifying health** instead of **Succeeded**, and the auto-close waits for the gate. A passed gate shows the success state and resumes the countdown; a failed or unknown verdict becomes the headline result and keeps the modal open with the reason. Closing the modal never stops the observation.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/deploy-progress/modal-succeeded.png" alt="Deploy progress modal in the succeeded state with a green checkmark, the text 'Succeeded' and 'closes in 2s' in the header, and the full structured log body visible beneath" />
|
||||
</Frame>
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
---
|
||||
title: Health-Gated Updates
|
||||
description: Check update readiness before applying, watch container health after the update lands, and know exactly what a rollback can restore.
|
||||
---
|
||||
|
||||
Updating a stack is the highest-anxiety operation in a homelab: a pull-and-recreate can break containers, networking, env configuration, or storage assumptions, and `docker compose` alone gives you no answer to "is it safe to update this right now?". Sencho makes updates deliberate and reversible in three layers: a readiness check before the update, a health gate after it, and an always-honest rollback readiness report on the stack.
|
||||
|
||||
None of these layers blocks you. Readiness is advisory, the health gate is purely observational, and rollback is always an explicit action you confirm. The only thing that hard-blocks an update is a [deploy enforcement policy](/features/deploy-enforcement).
|
||||
|
||||
## Update readiness
|
||||
|
||||
When you trigger **Update** from the stack editor toolbar or the sidebar menu, Sencho first opens a readiness dialog with a single verdict and the signals behind it:
|
||||
|
||||
| Verdict | Meaning |
|
||||
|---------|---------|
|
||||
| Ready | Nothing stands out; the update can proceed. |
|
||||
| Ready with warnings | Proceed, but read the warnings first. |
|
||||
| Review required | Something needs a look: a high-risk preflight finding, an already-unhealthy container, a pending major version bump, or low disk. |
|
||||
| Blocked | A blocker was found, such as a Compose Doctor blocker or a scan policy that will stop the update. |
|
||||
| Unknown | Readiness could not be verified, for example when the node or Docker is unreachable. |
|
||||
|
||||
The verdict is computed from signals Sencho already tracks, so the check is fast and never re-runs anything heavy:
|
||||
|
||||
- **Compose Doctor**: the stored result of the last [preflight run](/features/compose-doctor). A blocker finding makes the verdict Blocked; high-risk findings ask for review. If Compose Doctor has never run, the dialog says so without dragging the verdict down.
|
||||
- **Drift**: open [drift findings](/features/stack-drift) warn you that the running state has diverged, so the rollback target may not match what is running.
|
||||
- **Current containers**: a container that is already unhealthy, restarting, or crashed before the update makes the result hard to evaluate; the dialog asks you to look first.
|
||||
- **Pending image change**: the [update preview](/features/auto-update-policies) classifies the pending change. A major version bump asks for review; patch updates and same-tag refreshes pass quietly.
|
||||
- **Rollback backup**: whether a backup slot exists and how old it is. A missing backup is only a note, because the update itself creates a fresh one when it starts.
|
||||
- **Node disk**: disk usage near or above the node's alert threshold warns you before a large pull fills the disk.
|
||||
- **Healthcheck coverage**: how many services define healthchecks, which determines how thoroughly the post-update health gate can verify the result.
|
||||
|
||||
Admins also see whether a [fleet snapshot](/features/fleet-backups) covers this stack and can tick **Create a fleet snapshot before updating** to capture one as part of proceeding. If the snapshot fails, the update does not start.
|
||||
|
||||
Every verdict keeps the **Update now** button enabled. The dialog informs the decision; it does not make it for you.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/health-gated-updates/readiness-dialog.png" alt="Update readiness dialog for a stack, showing the verdict chip, the signal rows for Compose Doctor, drift, containers, pending update, rollback backup and node disk, the fleet snapshot row with the create-snapshot checkbox, and the Cancel and Update now buttons" />
|
||||
</Frame>
|
||||
|
||||
## The post-update health gate
|
||||
|
||||
The 3-second crash probe from [atomic deployments](/features/atomic-deployments) catches instant failures. The health gate is the longer observational layer behind it: after a deploy or update succeeds, Sencho watches the stack's containers for an observation window (90 seconds by default) and records a verdict.
|
||||
|
||||
During the window, the gate checks every container that came up with the stack:
|
||||
|
||||
- all expected containers stay **running**,
|
||||
- Docker healthchecks report **healthy** wherever a service defines one,
|
||||
- no container **exits**, **disappears**, or enters a **restart loop**.
|
||||
|
||||
A clear failure ends the observation immediately. Passing requires the full window, and a healthcheck still in its start period when the window ends records the verdict as unknown rather than claiming success.
|
||||
|
||||
The deploy progress modal treats the gate verdict as the real result: while the gate observes, the status reads **Verifying health** rather than claiming success, and the auto-close waits. A passed gate shows the success state; a failed or unknown gate becomes the headline result with its reason. Closing the modal never stops the observation; the gate runs server-side and its result appears on the stack timeline either way, as **health gate passed** or **health gate failed** events alongside the **update started** marker.
|
||||
|
||||
The live verifying and recovery view is part of the deploy progress panel. If you have turned that panel off, the in-browser gate view does not appear, but the gate still runs on the node and records its verdict on the stack timeline.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/health-gated-updates/modal-verifying.png" alt="Deploy progress modal after an update finished, with the status indicator showing Verifying health and the health gate banner reading observing containers" />
|
||||
</Frame>
|
||||
|
||||
<Frame>
|
||||
<img src="/images/health-gated-updates/modal-gate-failed.png" alt="Deploy progress modal with the headline status Health gate failed and the banner naming the unhealthy container, with the hint that rollback options are available on the stack" />
|
||||
</Frame>
|
||||
|
||||
When the gate fails, the stack page surfaces the same [recovery actions](/features/deploy-progress#recovery-actions) as a failed update: retry, restart, roll back when a backup exists, refresh the container state, or copy diagnostics. Rolling back is always your call; the gate never rolls anything back on its own.
|
||||
|
||||
The gate also runs for updates you did not click: scheduled image updates, webhook-triggered deploys and pulls, bulk updates, and Git source applies all record gate verdicts on the stack timeline. Rollbacks, App Store installs, and Sencho's own automation loops are deliberately not gated.
|
||||
|
||||
### Tuning or disabling the gate
|
||||
|
||||
Open **Settings > Host Alerts > Update health gate** on the node you want to configure:
|
||||
|
||||
- **Observe health after updates** turns the gate on or off for that node. On by default; turning it off only stops the observation and its timeline events, never the update itself.
|
||||
- **Observation window** sets how long containers are watched, from 15 to 600 seconds. The default is 90 seconds; raise it for stacks that take a while to settle, since a healthcheck still starting at the end of the window records an unknown verdict instead of a pass.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/health-gated-updates/settings.png" alt="Host Alerts settings page with the Update health gate group, showing the Observe health after updates toggle and the Observation window field" />
|
||||
</Frame>
|
||||
|
||||
## Rollback readiness
|
||||
|
||||
The Stack Dossier carries a **Rollback readiness** section that answers one question honestly: if this update goes wrong, what can a rollback actually restore? It reports an overall state of Ready, Partial, or Not ready, built from:
|
||||
|
||||
- **Previous compose file**: whether a backup slot exists and how old it is.
|
||||
- **Previous env file**: whether the backup contains the stack's env file. Sencho lists how many variable names are covered; the values themselves are restored with the file and never displayed.
|
||||
- **Previous image tag**: the known rollback target from the update preview. When the compose file uses a moving tag, restoring files alone does not revert the image, so the report names the exact tag you would pin to be precise.
|
||||
- **Last successful deploy**: whether the backup reflects a configuration that actually deployed successfully.
|
||||
- **Healthchecks**: whether a rollback can be verified beyond run state.
|
||||
- **Application data**: always reported as not covered. Named volumes and bind-mounted data are not included in file backups; a rollback restores compose and env files only, and your application data keeps its current state. This row exists so the limit is stated where you decide, not discovered during an incident.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/health-gated-updates/dossier-rollback-readiness.png" alt="Rollback readiness section in the Stack Dossier with the overall Ready chip and the six rows: previous compose file, previous env file with variable names only, previous image tag, last successful deploy, healthchecks, and the application data non-coverage disclosure" />
|
||||
</Frame>
|
||||
|
||||
## Classified failures
|
||||
|
||||
When a deploy or update fails, Sencho classifies the failure from the compose output and shows the cause with a suggested next step in the recovery panel: an image pull failure, a missing environment variable, a host port conflict, a missing bind-mount path, a permission problem, a crashed container, a failed healthcheck, an unavailable dependency, an unreachable node or Docker daemon, or an invalid compose file. The classification also lands in **Copy details**, so a bug report carries the cause, not just the raw output.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="The readiness dialog shows Unknown">
|
||||
Unknown means one of the verdict-affecting signals could not be verified, most often because Docker or the node did not answer in time. The update path is never blocked by an unknown verdict; check the node's connection if it persists, and proceed when you are confident in the stack's state.
|
||||
</Accordion>
|
||||
<Accordion title="The health gate failed but my app seems fine">
|
||||
The gate fails on the first clear problem it observes: a container exit, an unhealthy healthcheck, a restart loop, or a container disappearing mid-window. Check the named container's logs from the stack page. If the container legitimately restarts during startup (a migration step, for example), raise the observation window under **Settings > Host Alerts > Update health gate** so the gate watches past the settle period.
|
||||
</Accordion>
|
||||
<Accordion title="The health gate result is unknown">
|
||||
Unknown means the observation could not finish: Sencho restarted mid-window, a newer update superseded the observation, Docker became unreachable, a healthcheck was still starting when the window ended, or no containers appeared to observe. The stack timeline records the reason. Check the containers directly; an unknown verdict makes no claim either way.
|
||||
</Accordion>
|
||||
<Accordion title="The modal stays open saying the gate is observing">
|
||||
The modal holds its auto-close while the gate observes so the verdict is not lost. You can close it at any time; the observation continues server-side and the verdict lands on the stack timeline. If the gate result repeatedly cannot be retrieved, the modal gives up with an unknown verdict instead of waiting forever.
|
||||
</Accordion>
|
||||
<Accordion title="Rollback readiness says my data is not covered">
|
||||
That is by design and true for every stack: file backups cover compose and env files, never named volumes or bind-mounted data. For point-in-time copies of stack files across the fleet, use [fleet snapshots](/features/fleet-backups); for application data, use a backup tool appropriate to the workload (database dumps, volume backups) before risky updates.
|
||||
</Accordion>
|
||||
<Accordion title="Updates from the sidebar menu now show a dialog first">
|
||||
The sidebar's per-stack **Update** action runs the same path as the editor toolbar, so it shows the same readiness dialog and deploy progress. One click on **Update now** proceeds. On nodes that do not advertise the capability, updates run directly without the dialog.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 179 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 152 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 162 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 161 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 158 KiB |
+232
-3
@@ -149,6 +149,32 @@ components:
|
||||
type: boolean
|
||||
example: true
|
||||
|
||||
FailureClassification:
|
||||
type: object
|
||||
description: Classified cause of a failed deploy or update, with a suggested next step.
|
||||
required: [reason, label, suggestion]
|
||||
properties:
|
||||
reason:
|
||||
type: string
|
||||
enum:
|
||||
- image_pull_failed
|
||||
- compose_render_failed
|
||||
- env_missing
|
||||
- port_conflict
|
||||
- bind_path_missing
|
||||
- permission_denied
|
||||
- container_exited
|
||||
- healthcheck_failed
|
||||
- dependency_unavailable
|
||||
- node_unreachable
|
||||
- unknown
|
||||
label:
|
||||
type: string
|
||||
description: Short display headline for the cause.
|
||||
suggestion:
|
||||
type: string
|
||||
description: Suggested next action, one sentence.
|
||||
|
||||
Container:
|
||||
type: object
|
||||
properties:
|
||||
@@ -945,9 +971,19 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SuccessMessage"
|
||||
example:
|
||||
message: Deployed successfully
|
||||
type: object
|
||||
required: [message]
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
example: Deployed successfully
|
||||
healthGateId:
|
||||
type: string
|
||||
nullable: true
|
||||
description: |
|
||||
Id of the post-deploy health gate observation started for
|
||||
this deploy, for use with the health-gate endpoint. Null
|
||||
when the health gate is disabled on the node.
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"500":
|
||||
@@ -963,6 +999,8 @@ paths:
|
||||
rolledBack:
|
||||
type: boolean
|
||||
description: Whether the stack was automatically rolled back.
|
||||
failure:
|
||||
$ref: "#/components/schemas/FailureClassification"
|
||||
|
||||
/api/stacks/{stackName}/down:
|
||||
post:
|
||||
@@ -1095,6 +1133,13 @@ paths:
|
||||
status:
|
||||
type: string
|
||||
example: Update completed
|
||||
healthGateId:
|
||||
type: string
|
||||
nullable: true
|
||||
description: |
|
||||
Id of the post-update health gate observation started for
|
||||
this update, for use with the health-gate endpoint. Null
|
||||
when the health gate is disabled on the node.
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"500":
|
||||
@@ -1109,6 +1154,8 @@ paths:
|
||||
type: string
|
||||
rolledBack:
|
||||
type: boolean
|
||||
failure:
|
||||
$ref: "#/components/schemas/FailureClassification"
|
||||
|
||||
/api/stacks/{stackName}/rollback:
|
||||
post:
|
||||
@@ -1169,6 +1216,188 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/InternalError"
|
||||
|
||||
/api/stacks/{stackName}/update-readiness:
|
||||
get:
|
||||
operationId: getStackUpdateReadiness
|
||||
tags: [Stacks]
|
||||
summary: Check update readiness
|
||||
description: |
|
||||
Computes an advisory readiness verdict for updating the stack right
|
||||
now, from the stored preflight result, open drift findings, live
|
||||
container health, the pending image change, the rollback backup slot,
|
||||
and node disk headroom. Advisory only: no verdict blocks an update.
|
||||
Requires `stack:read` permission.
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/stackName"
|
||||
- $ref: "#/components/parameters/nodeId"
|
||||
responses:
|
||||
"200":
|
||||
description: Readiness report.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [stack, computedAt, verdict, signals]
|
||||
properties:
|
||||
stack:
|
||||
type: string
|
||||
computedAt:
|
||||
type: integer
|
||||
description: Unix timestamp (ms) the report was computed.
|
||||
verdict:
|
||||
type: string
|
||||
enum: [ready, ready_with_warnings, review_required, blocked, unknown]
|
||||
signals:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [id, status, title, detail, affectsVerdict]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
enum: [ok, warning, attention, blocked, unknown]
|
||||
title:
|
||||
type: string
|
||||
detail:
|
||||
type: string
|
||||
affectsVerdict:
|
||||
type: boolean
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"500":
|
||||
$ref: "#/components/responses/InternalError"
|
||||
|
||||
/api/stacks/{stackName}/rollback-readiness:
|
||||
get:
|
||||
operationId: getStackRollbackReadiness
|
||||
tags: [Stacks]
|
||||
summary: Check rollback readiness
|
||||
description: |
|
||||
Reports what a rollback of this stack can actually restore: the backed
|
||||
up compose file, env coverage (variable names only, never values), the
|
||||
known previous image tag, and an explicit disclosure that volume and
|
||||
bind-mounted data are not covered by file backups.
|
||||
Requires `stack:read` permission.
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/stackName"
|
||||
- $ref: "#/components/parameters/nodeId"
|
||||
responses:
|
||||
"200":
|
||||
description: Rollback readiness report.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [stack, computedAt, overall, items]
|
||||
properties:
|
||||
stack:
|
||||
type: string
|
||||
computedAt:
|
||||
type: integer
|
||||
overall:
|
||||
type: string
|
||||
enum: [ready, partial, not_ready]
|
||||
items:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [id, state, label, detail]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
state:
|
||||
type: string
|
||||
enum: [ready, missing, unknown, not_covered]
|
||||
label:
|
||||
type: string
|
||||
detail:
|
||||
type: string
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"500":
|
||||
$ref: "#/components/responses/InternalError"
|
||||
|
||||
/api/stacks/{stackName}/health-gate:
|
||||
get:
|
||||
operationId: getStackHealthGate
|
||||
tags: [Stacks]
|
||||
summary: Get post-update health gate result
|
||||
description: |
|
||||
Returns a post-deploy health gate observation for the stack: the run
|
||||
named by `gateId` (as returned in a deploy or update response), or the
|
||||
most recent run when omitted. Status `never-run` means no observation
|
||||
exists. Requires `stack:read` permission.
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/stackName"
|
||||
- $ref: "#/components/parameters/nodeId"
|
||||
- name: gateId
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
description: A specific gate run id to read instead of the latest.
|
||||
responses:
|
||||
"200":
|
||||
description: Health gate report.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [stack, status]
|
||||
properties:
|
||||
stack:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
nullable: true
|
||||
status:
|
||||
type: string
|
||||
enum: [observing, passed, failed, unknown, never-run]
|
||||
trigger:
|
||||
type: string
|
||||
nullable: true
|
||||
enum: [update, deploy, null]
|
||||
reason:
|
||||
type: string
|
||||
nullable: true
|
||||
windowSeconds:
|
||||
type: integer
|
||||
nullable: true
|
||||
startedAt:
|
||||
type: integer
|
||||
nullable: true
|
||||
endedAt:
|
||||
type: integer
|
||||
nullable: true
|
||||
containers:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [name, state, restarts]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
state:
|
||||
type: string
|
||||
description: Docker container state, or `missing` when it vanished mid-observation.
|
||||
health:
|
||||
type: string
|
||||
nullable: true
|
||||
restarts:
|
||||
type: integer
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"500":
|
||||
$ref: "#/components/responses/InternalError"
|
||||
|
||||
|
||||
# ── Containers ──────────────────────────────────────────
|
||||
/api/containers:
|
||||
|
||||
Reference in New Issue
Block a user