New to Kestra?
Use blueprints to kickstart your first workflows.
Orchestrate staged VM patching with Kestra. UAT is patched and validated first; production proceeds only on success, with rollback and Slack reporting.
Never let a patch reach production before UAT proves it. This orchestrator calls a patching subflow against the UAT VM, where the patch is applied over SSH, a human validates it, and a rejection or failure triggers automatic rollback. Only when UAT reports actionPerformed: PATCH with actionState: SUCCESS does the same subflow run against the production VM. The final Return task assembles a per-stage summary (applied or not, and why) that is posted to Slack and exposed as a flow output.
patchId input is a SELECT whose options come from a KV-stored list via expression: {{ kv('approvedPatches') }}, so operators can only pick patches your team has pre-approved.processUatVM task (io.kestra.plugin.core.flow.Subflow with wait: true and transmitFailed: true) runs the companion ssh-patch-vm-approval-rollback flow against the UAT VM. That subflow patches, pauses for validation, and rolls back on rejection.processProdVM task uses runIf on the UAT subflow's outputs: production is patched only when UAT performed a patch (not a rollback) and its state is SUCCESS.logResult task (io.kestra.plugin.core.debug.Return) renders the two-stage summary with a Pebble {% if %} block that marks production as "Stage Skipped" when UAT did not validate.notifyResult task (io.kestra.plugin.notifications.slack.SlackIncomingWebhook) posts the summary, and the result flow output returns it to any caller.Staged rollouts require carrying state across environments: what was applied, whether a human validated it, and what happened on rollback. Kestra subflows return typed outputs that the orchestrator consumes in runIf conditions, giving you promotion logic as declarative YAML instead of brittle glue scripts. Every stage is a separate execution with its own logs, retries, and approval trail.
ssh-patch-vm-approval-rollback deployed in the same namespace (adjust flowId if renamed).SSH_VM_USER and SSH_VM_PASSWORD secrets).approvedPatches containing the list of patch identifier strings.SLACK_WEBHOOK_URL: Slack incoming webhook for the rollout summary (the subflow also uses it for approval notifications).approvedPatches.Subflow calls with chained runIf conditions.io.kestra.plugin.core.flow.ForEach around the prod subflow.io.kestra.plugin.core.trigger.Schedule trigger.