Interpolation reference

Action triggers support {{ ... }} interpolation in payloads, headers, auth values, URLs, PR titles, PR bodies, file contents, branch names, and labels. The same syntax works in every interpolation-aware field.

Available variables

VariableAvailable when
{{ secrets.<name> }}Always — resolves and decrypts the named Terrantula Secret
{{ parameters.<name> }}Always — values supplied when the Action was triggered
{{ recommendations.<name>.id }}Action has recommendations
{{ recommendations.<name>.name }}Action has recommendations
{{ recommendations.<name>.properties.<prop> }}Action has recommendations
{{ entity.id }}Action scope: instance
{{ entity.name }}Action scope: instance
{{ entity.properties.<prop> }}Action scope: instance
{{ entity.labels.<label> }}Action scope: instance
{{ run.id }}Always — the ActionRun UUID
{{ run.callbackUrl }}Always — where the external workflow POSTs completion
{{ run.callbackToken }}Always — HMAC-signed token for that callback (see below)
{{ operation.entity.id }}Inside createRelationship on a create-entity operation — refers to the just-created entity

Callback token security

{{ run.callbackToken }} is HMAC-SHA256 signed using the server encryption key. The token is bound to:

  • The specific ActionRun UUID
  • The expiry timestamp (defaults to the Action's timeout, or 60 minutes if unset)

Format: {runId}:{expiresAtMs}:{hmac}. The callback endpoint validates with constant-time comparison and a status guard — a token issued for one run cannot be replayed against another run, even within the expiry window.

This token is not a credential by itself. It can be embedded in PR bodies, log messages, or anywhere safe to display — the HMAC binds it to a specific run and expiry, and the status guard prevents replay.

Run ID safety

{{ run.id }} (the bare UUID without HMAC) is always safe to embed in PR bodies, commit messages, or logs. It identifies a run for human reference but cannot authorize a callback on its own.

Examples

Webhook payload

trigger:
  type: webhook
  url: https://workflows.example.com/onboard
  auth:
    type: bearer
    token: "{{ secrets.onboarding-webhook-token }}"
  payload:
    customerId: "{{ entity.id }}"
    customerName: "{{ entity.properties.companyName }}"
    targetCluster: "{{ recommendations.targetCluster.id }}"
    namespace: "{{ parameters.namespace }}"
    callbackUrl: "{{ run.callbackUrl }}"
    callbackToken: "{{ run.callbackToken }}"

Pull-request trigger

trigger:
  type: pull-request
  repo: my-org/infrastructure
  auth:
    type: token
    token: "{{ secrets.github-token }}"
  title: "Onboard {{ entity.properties.companyName }} → {{ recommendations.targetCluster.name }}"
  body: |
    Triggered by Terrantula ActionRun `{{ run.id }}`.

    Tenant: {{ entity.properties.companyName }}
    Target cluster: {{ recommendations.targetCluster.name }}
    Region: {{ recommendations.targetCluster.properties.region }}
  head: "terrantula/onboard-{{ entity.id }}"
  base: main
  reviewers:
    - "{{ parameters.approver }}"
  files:
    - path: "tenants/{{ entity.id }}.yaml"
      content: |
        apiVersion: v1
        kind: Tenant
        metadata:
          name: "{{ entity.properties.companyName }}"
          cluster: "{{ recommendations.targetCluster.id }}"
  webhookSecret: "{{ secrets.github-webhook-secret }}"

Action withcreateRelationship

operation:
  type: create-entity
  entityType: Tenant
  onTrigger: provisioning
  onSuccess: active
  onFailure: failed
  properties:
    customer_id: "{{ parameters.customer_id }}"
  createRelationship:
    relationshipType: runs_on
    to: "{{ recommendations.target-cluster.id }}"
    onSuccess: active
    onFailure: removing
    properties:
      namespace: "tenant-{{ operation.entity.id }}"  # The just-created Tenant's ID

In createRelationship, the special variable {{ operation.entity.id }} resolves to the entity that was just created by the parent create-entity operation. This lets you compose entity creation and relationship creation atomically without two separate calls.