Webhook icon
Assert icon
Template icon
Upgrade icon
Status icon
Request icon
If icon
Log icon
Pause icon
SlackIncomingWebhook icon
Uninstall icon
Fail icon

Helm Preview Environment Lifecycle and Ephemeral Teardown Gate

Deploy a per-PR Helm preview into its own namespace, smoke test it through its ingress, keep it for a review window, then uninstall it with Kestra.

Categories
Infrastructure

Diagram unavailable

We could not build the topology for this blueprint. The flow itself is valid, use the YAML on the left to run it.

Gives every pull request its own preview of your application on Kubernetes and makes sure it does not outlive its purpose. CI calls a webhook with the pull request number and image tag. The flow checks the values, renders the chart offline, installs it with Helm into a namespace named after the pull request, requests the preview through its ingress, keeps it for a review window, and then uninstalls it.

Preview environments that nobody removes keep pods, disks and ingress rules running long after the pull request is merged. Here the cleanup is part of the same execution, in a finally step that runs after success and after failure, and a preview that fails its smoke test is removed immediately.

How it works

  1. ci_preview_webhook (io.kestra.plugin.core.trigger.Webhook) receives a JSON body with pr_number and image_tag. Manual runs use the matching inputs. The values only name the release and fill chart values, and validate_parameters (io.kestra.plugin.core.execution.Assert) rejects anything that is not a plain number or tag, including values with trailing whitespace, before the cluster is touched.
  2. render_and_lint_chart (io.kestra.plugin.helm.Template) renders the chart offline with the preview values, so a template error fails before anything is deployed.
  3. deploy_preview_release (io.kestra.plugin.helm.Upgrade) installs or updates release preview-pr-<number> in namespace preview-pr-<number> with createNamespace, wait: WATCHER and rollbackOnFailure, and sets image.tag and the ingress host pr-<number>.<preview_domain>.
  4. verify_preview_status (io.kestra.plugin.helm.Status) reads the release back from the cluster.
  5. smoke_test_preview_endpoint (io.kestra.plugin.core.http.Request, allowFailure: true) requests health_path on the preview host and retries up to six times while the ingress comes up.
  6. evaluate_smoke_test_result (io.kestra.plugin.core.flow.If) handles the answer:
    • HTTP 200: with auto_teardown on, review_window (io.kestra.plugin.core.flow.Pause) holds the execution for preview_ttl_minutes. Resuming it early ends the review sooner.
    • Anything else: alert_smoke_test_failed posts to Slack, teardown_failed_preview (io.kestra.plugin.helm.Uninstall) removes the release, and fail_execution (Fail) fails the run so that CI sees it.
  7. The flow-level finally step teardown_preview uninstalls the release when this execution deployed it and auto_teardown is on, with ignoreNotFound so an already removed release is fine. notify_teardown then tells Slack.

What you get

  • A per-pull-request preview that is removed on schedule, after a failure, and when you resume the pause.
  • Checks on the webhook values, so a request cannot choose another team's namespace or inject chart values.
  • A smoke test through the real ingress, with retries while it starts.
  • A failed render or an earlier failure cannot remove a healthy preview from a previous push, because teardown only happens when this execution deployed the release.

Who it's for

  • Platform Engineers: Teams that offer preview environments and want to cap their cost.
  • DevOps & SRE Teams: Teams that run Kubernetes clusters shared by many branches.
  • QA Engineers: Teams that need a temporary URL per feature branch.

Why orchestrate this with Kestra

  • Cleanup in the same run: A finally step removes the release whatever happens in between.
  • Review window without a scheduler: A Pause keeps the execution open for the retention window and can be resumed by hand.
  • Helm tasks instead of shell: Template, Upgrade, Status and Uninstall run helm in a container and keep their output in the execution.

Prerequisites

  • A Kubernetes cluster and a ServiceAccount token that can create namespaces and manage the chart's resources.
  • A Helm chart that accepts the values image.tag, ingress.enabled and ingress.hosts (the layout used by charts such as podinfo).
  • An ingress controller, and DNS that resolves pr-<number>.<preview_domain> from the Kestra worker.
  • A Docker daemon for the Kestra worker, to run the Helm container.
  • A Slack Incoming Webhook URL.

Secrets

  • K8S_MASTER_URL: Kubernetes API server URL.
  • K8S_CA_CERT: Certificate authority data for the API server.
  • K8S_TOKEN: ServiceAccount bearer token.
  • HELM_PREVIEW_WEBHOOK_KEY: Key that protects the webhook URL.
  • SLACK_WEBHOOK_URL: Slack Incoming Webhook URL.

Quick start

  1. Add the five secrets to your Kestra namespace.
  2. Import this blueprint and run it manually with pr_number, image_tag, chart_repository, chart_name, chart_version and preview_domain set, and a short preview_ttl_minutes.
  3. Open the preview URL, then resume the paused execution to see the teardown.
  4. For CI, give the chart inputs defaults in the flow and have your pipeline POST {"pr_number": "108", "image_tag": "sha-abc123"} to the webhook URL shown for ci_preview_webhook.

How to extend

  • Comment on the pull request: Add a GitHub comment task with the preview URL after the smoke test.
  • Browser tests: Replace the HTTP check with a Playwright task.
  • Preview databases: Create a database branch before the deploy and delete it in finally.
  • Close events: Add a second webhook call from CI on pull request close that resumes the paused execution.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.