Skip to content

Lifecycle Hooks

Griffen Fargo edited this page Jul 3, 2026 · 2 revisions

Lifecycle Hooks

User-defined scripts that run at strut lifecycle points. Since v0.9.0.

Drop an executable script into stacks/<stack>/hooks/<event>.sh and strut runs it at the matching event. Hook files may use pre_deploy.sh (snake_case, preferred) or pre-deploy.sh (dash form) — both resolve.

Events

Hook Fires On non-zero
pre_deploy Before deploy_stack runs aborts deploy
post_deploy After deploy_stack succeeds warn, continue
pre_backup Before any backup runs aborts backup
post_backup After backup succeeds warn, continue
pre_migrate Before database migration runs (since v0.29.0) aborts migration
post_migrate After database migration succeeds (since v0.29.0) warn, continue
on_health_fail After a health check fails warn, continue
on_drift_detected When drift is detected warn, continue

pre_* hooks are enforcement gates — any non-zero exit stops the action before state changes. post_* and on_* hooks are advisory — they warn on failure but never abort the underlying flow.

Script Conventions

A hook script is a normal bash script. strut sets no positional args; all context arrives via environment variables that the caller has already exported:

Var Description
CMD_STACK Stack name
CMD_STACK_DIR Absolute path to stacks/<stack>/
CMD_ENV_NAME Environment name (prod, staging, …), may be empty
CMD_ENV_FILE Path to the active env file

Event-specific extras:

Event Extra vars
post_backup BACKUP_TARGETpostgres / neo4j / mysql / sqlite / all
on_health_fail UNHEALTHY_SERVICES — space-separated list of failing services (when available)

Hooks run with the same working directory as the strut invocation. Keep scripts idempotent: a retry after a transient failure should be safe.

Examples

stacks/my-stack/hooks/pre_deploy.sh — gate on schema drift

#!/usr/bin/env bash
set -euo pipefail

# Refuse to deploy while there's pending postgres drift.
if strut "$CMD_STACK" drift detect --env "$CMD_ENV_NAME" --quiet; then
  exit 0
fi

echo "Drift detected — run 'strut $CMD_STACK drift fix' first" >&2
exit 1

stacks/my-stack/hooks/post_deploy.sh — ping Slack

#!/usr/bin/env bash
set -euo pipefail

curl -fsS -X POST "$SLACK_WEBHOOK_URL" \
  -H 'content-type: application/json' \
  -d "{\"text\":\"Deployed $CMD_STACK to $CMD_ENV_NAME\"}"

(Or use the built-in Notifications subsystem and skip the hook.)

stacks/my-stack/hooks/post_backup.sh — rsync offsite

#!/usr/bin/env bash
set -euo pipefail

# Offsite-sync the artefact we just produced.
[ "$BACKUP_TARGET" = "postgres" ] || exit 0
rsync -a --partial "$CMD_STACK_DIR/backups/" offsite:/backups/"$CMD_STACK"/

(For S3/R2/B2 use Database Backups' built-in offsite sync instead.)

Idempotent Schema Application (since v0.29.0)

Set RUN_DB_SCHEMA_ON_DEPLOY=true in strut.conf to re-apply sql/init/*.sql on every deploy. The schema files should be written idempotently (CREATE TABLE IF NOT EXISTS, etc.) so repeated runs are safe. This fires the pre_migrate / post_migrate hooks.

Blue-Green Parity (since v0.29.0)

Blue-green deploys now fire the first_run hook on the new color, matching the behavior of standard deploys. Previously first_run only executed during in-place deployments.

Enabling & Disabling

Hooks are discovered at event time — no registration step. Make them executable:

chmod +x stacks/my-stack/hooks/pre_deploy.sh

Disable pre-deploy hooks globally in strut.conf:

PRE_DEPLOY_HOOKS=false

Or skip for one invocation:

strut my-stack deploy --env prod --skip-validation

Related

  • Deployment — where pre_deploy / post_deploy fit in the flow
  • Database Backupspre_backup / post_backup call sites
  • Notifications — built-in Slack / Discord / webhook events (often a better fit than a one-off hook)

Clone this wiki locally