TerragruntCLI icon
Log icon
If icon
SlackIncomingWebhook icon

Ephemeral Terragrunt Preview Stacks with Guaranteed Teardown

Spin up a Terragrunt preview stack, run checks, and guarantee teardown with a Kestra finally block. run-all destroy runs even when the tests fail.

Categories
Infrastructure

Preview environments are only cheap when they reliably disappear. This blueprint applies a Terragrunt preview folder, runs a placeholder test step, and then destroys the stack from a finally block, the part of a Kestra flow that runs whether the tasks before it succeeded or failed. The interesting mechanics are in the state handoff: each Kestra task runs in its own container, so the apply task exports its Terraform state files as outputFiles, and the teardown task restores them via inputFiles before running run-all destroy.

To make that handoff deterministic, root.hcl pins state to a predictable path with a remote_state block, state/preview/network/terraform.tfstate and state/preview/app/terraform.tfstate, instead of letting it live inside Terragrunt's cache directories. The demo modules only create local_file resources, so the whole lifecycle runs without cloud credentials.

How it works

  1. apply_preview (io.kestra.plugin.terragrunt.cli.TerragruntCLI) materializes the repo from inputFiles and runs terragrunt run-all apply --non-interactive --working-dir live/preview, bringing up both preview units.
  2. The remote_state block in root.hcl writes each unit's state under a top-level state/ folder, and the task exports those files with outputFiles: state/**/*.tfstate.
  3. run_preview_checks is a placeholder Log task standing in for your real test suite against the preview stack.
  4. In the finally block, teardown_when_applied (io.kestra.plugin.core.flow.If) checks that the apply actually exported state, then destroy_preview recreates the same repo layout, restores both state files through inputFiles, and runs terragrunt run-all destroy --non-interactive.
  5. The errors block posts a Slack alert on any failure, noting that teardown already ran.

What you get

  • Preview stacks that cannot outlive their execution, teardown runs on success, on test failure, and on most crashes.
  • A worked example of passing Terraform state between isolated Kestra tasks with outputFiles and inputFiles.
  • A guard condition that skips teardown cleanly when the apply never produced state.
  • A Slack alert for failed runs so leaked-resource suspicion triggers a manual check.

Who it's for

  • Teams reviewing infrastructure or application changes against short-lived, real stacks instead of shared staging.
  • Platform engineers who have been burned by orphaned preview environments quietly accruing cost.
  • Anyone building apply-test-destroy loops around Terragrunt.

Why orchestrate this with Kestra

Shell scripts implement this pattern with trap, until the runner dies, the step times out, or someone ctrl-c's the pipeline. Kestra's finally block is a first-class flow construct: it runs server-side regardless of upstream task state, its guard condition is declarative, and the execution history shows the apply, the checks, and the destroy as separate, individually logged tasks. The state handoff through Kestra's internal storage also means no shared runner disk is required between steps.

Prerequisites

  • A Slack incoming webhook for failure alerts.
  • No cloud credentials are needed for the demo. For real preview stacks, use a real remote state backend such as S3 or GCS in root.hcl, then the teardown task no longer needs the state file handoff, and pass provider credentials through task env from {{ secret('...') }}.

Secrets

  • SLACK_WEBHOOK_URL: Slack incoming webhook URL.

Quick start

  1. Add the SLACK_WEBHOOK_URL secret to your Kestra namespace.
  2. Execute the flow and watch the apply, the placeholder checks, and the destroy run in order.
  3. Make the checks fail on purpose, for example by replacing the Log task with a failing script, and confirm the destroy still runs.

How to extend

  • Replace run_preview_checks with a real test runner, an HTTP health check task, or a container running your end-to-end suite.
  • Move state to a real backend in root.hcl, then drop the state entries from the teardown task's inputFiles, the backend becomes the handoff.
  • Trigger the flow from a pull request webhook and name the preview folder after the branch.
  • Switch the underlying binary to OpenTofu with an image that ships tofu and the TERRAGRUNT_TFPATH environment variable in the task env.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.