Skip to content
GantryCD

Lifecycle hooks

Lifecycle hooks are bash scripts GantryCD runs on the runner around a run’s tofu init, plan, and apply — for the glue work that doesn’t belong in Terraform: connecting a VPN, installing a tool, gating on a policy or cost check, or backing up state after an apply. You set them on a stack and on contexts the stack references; at deploy time they merge and run in priority order.

A non-zero hook exit fails the run, so a hook can act as a gate.

Phases

Each run runs tofu init then one main command. A hook fires at one of six phases:

PhaseRuns
pre_init, post_initevery run, around tofu init
pre_plan, post_planplan / destroy / refresh runs
pre_apply, post_applyapply runs

(destroy and refresh are plan-style, so they use the *_plan phases. raw deployments run no hooks.)

Ordering

Each hook has a priority from 1 to 99 — lower runs first. Within a phase, every hook from the stack and its contexts runs in priority order. At the same priority, a context’s hook runs before the stack on pre_* phases and after it on post_* phases — so a shared context can set something up around what the stack does. Put shared setup/teardown in a context; stack-specific steps on the stack.

What a hook can use

A hook runs from the stack’s working directory with the same environment as tofu — your environment variables, cloud credentials, and the gantrycd-API token — plus:

  • GANTRYCD_RUN_MODEplan, apply, destroy, or refresh
  • GANTRYCD_PLAN_FILE — path to the plan file (available in post_plan and the apply phases)
  • GANTRYCD_HOOK_PHASE, GANTRYCD_WORKING_DIR, GANTRYCD_RUN_ID, GANTRYCD_STACK_ID, GANTRYCD_STACK_NAME

Hook output appears in the run log alongside the tofu output.

Keep secrets in environment variables. Hook scripts are stored in plaintext. Reference a secret through an environment variable (which is encrypted at rest); never paste a secret into a script.

Examples

Connect a VPN before anything else (pre_init, on a context shared by every stack in the network):

nohup openvpn --config /etc/vpn/client.conf --daemon
# wait until the tunnel is up...

Gate the plan on policy and cost (post_plan):

tofu show -json "$GANTRYCD_PLAN_FILE" > plan.json
conftest test plan.json        # fails the run (and blocks apply) on a violation
terracost breakdown --path .    # surfaces cost in the log

Back up state after a successful apply (post_apply):

aws s3 cp ./terraform.tfstate "s3://my-backups/$GANTRYCD_STACK_NAME/$(date +%s).tfstate"

Install a tool the plan needs (pre_init):

curl -sSL https://example.com/install.sh | bash   # installs onto $PATH

A hook that should never fail the run guards itself: some-command || true.

Configuring

Open a stack or context, go to the Hooks tab, and add rows (phase, priority, optional name, script). Editing hooks needs the same permission as editing the rest of the stack or context.