Actions fire one of the following trigger types when triggered. The trigger does the actual work of dispatching to an external system and tracking the outcome.
| Type | Status | Description |
|---|---|---|
webhook | Shipped | POST to any HTTP endpoint with retry + jitter. Callback signals completion. |
pull-request | Shipped | Open a GitHub PR via the Git Data API; auto-completes on merge or close. |
terraform-cloud | Shipped | Fire a TFC / HCP Terraform run natively. Polls until terminal state and transitions the ActionRun on completion. |
atmos-workflow | Shipped | Invoke an Atmos workflow via a customer-deployed runner. HTTP-POSTs a structured payload to the customer's runner; the runner clones their Atmos repo, runs atmos workflow <name> -s <stack>, and POSTs back to Terrantula's callback. |
atlantis | Shipped | Talk to a customer-hosted Atlantis instance via its API. Two modes: pull-request (default) and api-dispatch. |
For interpolation syntax in trigger fields, see Interpolation.
POSTs (or GETs / PUTs / etc.) to an HTTP endpoint. The external workflow does the actual provisioning and POSTs back to {{ run.callbackUrl }} with Authorization: Bearer {{ run.callbackToken }} to signal completion.
Auth types. bearer (Authorization: Bearer …), basic (Authorization: Basic base64(user:pass)), header (custom header name + value), jwt (signs a JWT with the named secret and includes claims).
Retry behavior. Retries on 5xx, 429, and network errors with exponential backoff + jitter. 4xx (except 429) fails immediately — retrying a misconfigured URL won't help. Delivery failures are distinguished from callback-reported failures via a [delivery] prefix on the ActionRun's error field.
Completion. The external workflow POSTs to {{ run.callbackUrl }} with Authorization: Bearer {{ run.callbackToken }} and a JSON body indicating success or failure. The ActionRun transitions to succeeded or failed, and the entity / relationship transitions to its onSuccess or onFailure state.
If the callback never arrives, the reaper transitions the ActionRun to failed after the Action's timeout (defaults to 60 minutes if unset).
Opens a GitHub PR and waits for a human to merge or close it. The branch, commits, title, body, files, labels, and reviewers all support interpolation.
When the action fires:
base via the Git Data APIfiles to that branch{ prNumber, prUrl, repo } in the ActionRun's metadata fieldrunningWhen the PR closes:
succeeded; entity/relationship transitions to onSuccessfailed; entity/relationship transitions to onFailureFor automatic state transitions, set webhookSecret and configure a GitHub webhook on the repo pointing to POST /webhooks/github with that secret. Terrantula verifies X-Hub-Signature-256 per-PR using the action-specific secret stored in Terrantula Secrets — there is no global webhook configuration. Different repos can use different secrets without coordination.
If webhookSecret is omitted, the PR will still be created — but Terrantula won't auto-complete the run. State transitions then need to happen manually via the entity/relationship API or via a GitHub Actions workflow that POSTs to the callback URL. {{ run.id }} (the ActionRun UUID — safe to embed anywhere) can be put in the PR body for reference.
If neither auto-completion nor manual transition happens, the reaper will time the run out after the Action's timeout.
For organizations with siloed engineering teams, the PR-based approval pattern is the critical feature: a requesting team triggers an action, the owning team gets a PR in their own repo in their normal review queue, their existing pipeline handles provisioning, and Terrantula tracks the outcome. No new tools for the owning team. No process changes for either side.
Fires a Terraform Cloud / HCP Terraform run against a pre-existing workspace. Terrantula never executes terraform — TFC runs the plan/apply, Terrantula tracks the outcome.
When the action fires:
workspaceName to a workspace ID via GET /api/v2/organizations/:org/workspaces/:name (skipped when workspaceId is set directly).POSTs /api/v2/runs with run-scoped variables (JSON-stringified as HCL literal strings), the auto-apply flag, an optional message, and the workspace relationship.{ runId, runUrl, workspaceId, workspaceName, organization, status } in the ActionRun's metadata field.waitForCompletion=true (default), worker polls GET /api/v2/runs/:id every pollIntervalSeconds. The action's timeout (default 60min) is the upper bound — the reaper marks the run failed if TFC stalls.applied, planned_and_finished, planned_and_saved, planned, policy_checked → ActionRun succeeded.errored, discarded, canceled, force_canceled, policy_soft_failed → ActionRun failed with Terraform Cloud run '<status>' — see <runUrl> as the error.autoApply: false and theplanned statusWhen autoApply: false (the default), TFC completes the plan and waits for a human operator to click "Confirm & Apply" before applying. Terrantula considers the Action complete when the TFC run reaches planned — meaning the plan has finished but the infrastructure has not yet been provisioned. The entity will transition to its onSuccess state (e.g., active) at this point, before TFC has actually applied any changes.
This is intentional plan-only semantics: Terrantula's job is to track that the provisioning workflow was initiated and the plan succeeded. If your OnboardTenant Action requires the tenant infrastructure to actually exist before the entity transitions to active, set autoApply: true. With autoApply: true, TFC applies immediately after planning and the entity only transitions once the run reaches applied.
planned_and_finished (no changes required) and planned_and_saved are genuinely terminal — they mean TFC found nothing to do or saved the plan for later. Both count as success.
Variable values passed via variables: { ... } are sent to TFC with sensitive: false and will appear as cleartext in the TFC UI's run details panel — including values resolved from Terrantula Secrets.
Do not pass sensitive values (API keys, passwords, tokens) as run-scoped variables. Instead, configure them as workspace-level sensitive variables directly in TFC. Workspace-level sensitive variables are never exposed in the UI or API responses. Run-scoped variables are appropriate for non-sensitive routing data such as tenant IDs, regions, and plan tier names.
waitForCompletion: false)When waitForCompletion: false, the worker dispatches the TFC run and returns immediately. The ActionRun stays running until either the customer manually POSTs a callback or the reaper fires at the Action's timeout.
On dispatch, Terrantula stores the TFC run details in the ActionRun's metadata field:
The callback URL and token are available in the ActionRun's interpolation context when the action is triggered ({{ run.callbackUrl }} and {{ run.callbackToken }}).
apiToken accepts a Terrantula Secret reference ({{ secrets.tfc-api-token }}). The token must have permission to queue runs in the target workspace. TFC supports user, team, and organization tokens — any of them work.
The apiBaseUrl is validated against the same SSRF blocklist as the Atlantis trigger — see the Atlantis trigger SSRF guard section for the full list of blocked ranges.
terraform apply. TFC runs the plan/apply; Terrantula triggers and observes.configSource field is informational — there is no upload mode.Invokes an Atmos workflow on a customer-deployed runner. Atmos workflows mirror Terrantula Actions architecturally — both are named, parameterized invocations against a deployment target. The trigger HTTP-POSTs a structured payload to the customer's runner endpoint; the runner clones their Atmos repo, runs atmos workflow <name> -s <stack>, and callbacks Terrantula.
Customers deploy a runner — either the reference terrantula-atmos-runner Docker container, or a GitHub Actions / GitLab CI workflow template — and point the trigger at it. The runner is open source and customer-deployed; Terrantula never hosts it.
The runner.endpoint is validated against the same SSRF blocklist as the Atlantis trigger — see the Atlantis trigger SSRF guard section for the full list of blocked ranges.
Talks to a customer-hosted Atlantis instance. Two integration modes:
Pull-request mode (default) — Terrantula opens a GitHub PR with the file changes; Atlantis picks it up via its own webhook subscription and runs plan/apply. This mode is identical in behavior to the generic pull-request trigger but is explicitly labeled for Atlantis workflows and produces { mode: 'pull-request', prNumber, prUrl, repo } metadata on the ActionRun.
API-dispatch mode — Terrantula calls Atlantis's /api/plan or /api/apply endpoint directly, without a PR cycle. Returns structured project results including Terraform output. Useful for automation flows that don't require PR review.
createPullRequest with the nested pullRequest config — identical to the generic pull-request trigger flow.{ mode: 'pull-request', prNumber, prUrl, repo } in the ActionRun's metadata.succeeded.repo, ref, project.<endpoint>/api/plan or <endpoint>/api/apply with X-Atlantis-Token auth.ProjectResults.{ mode: 'api-dispatch', command, projectResults, planOutput } in the ActionRun's metadata.succeeded.Atlantis uses a custom header: X-Atlantis-Token: <api-secret>. The api-secret must be configured in Atlantis server settings (--api-secret flag or config file). The auth.token field accepts a Terrantula Secret reference ({{ secrets.atlantis-token }}).
The endpoint URL is validated before any HTTP call is made. https:// is required. The shared validateInternalAddress() guard blocks: loopback (localhost, 127.0.0.0/8, ::1, 0.0.0.0), link-local (169.254.*), RFC 1918 (10.*, 172.16–31.*, 192.168.*), CGNAT (100.64.0.0/10), IPv6 ULA (fc00::/7), IPv6 multicast (ff00::/8), and IPv4-mapped IPv6 forms (::ffff:*).
Retries on 5xx, 429, and network errors with exponential backoff. 4xx (except 429) fails immediately. Default: 3 attempts, 1000ms initial delay (doubles each attempt).
atlantis.yaml in the customer's repo is managed by the customer (or patched via the pull-request trigger's file-patch operation).terraform apply directly. In api-dispatch mode, Terrantula asks Atlantis to run apply; Atlantis runs it on its own infrastructure.A single Action can override trigger fields per environment via envOverrides. Useful when the same Action targets different webhook URLs / TFC workspaces / Atlantis instances / GitHub repos in dev vs prod.
At dispatch time, override fields are shallow-merged on top of the base trigger. The type must match the base trigger's type — enforced at apply.