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:
| Phase | Runs |
|---|---|
pre_init, post_init | every run, around tofu init |
pre_plan, post_plan | plan / destroy / refresh runs |
pre_apply, post_apply | apply 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_MODE—plan,apply,destroy, orrefreshGANTRYCD_PLAN_FILE— path to the plan file (available inpost_planand 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.