GitHub App

The Terrantula GitHub App is the recommended way to authorize PR-opening triggers against GitHub. Once installed and linked to a project, Terrantula mints short-lived installation tokens at dispatch time — you don't store long-lived personal access tokens. This page is the reference for the App's identity, permissions, install flow, and credential resolution.

INFO

The GitHub App only ever opens pull requests (and, optionally, fires repository_dispatch). It never runs terraform apply. Your CI applies the merged change; Terrantula observes the outcome via the webhook.

NOTE

The App is optional. A static trigger.auth.token (a PAT or {{ secrets.* }} reference) works without any App install — the Sam-cohort escape hatch for GHE-Server and no-App self-hosters. See Credential resolution.

Identity

FieldHosted (terrantula-io)Self-hosted
App ID3754472your numeric App ID
App slugterrantula-ioyour App slug
Ownerterrantula-io orgyou
Install URLhttps://github.com/apps/terrantula-io/installations/newhttps://github.com/apps/<your-slug>/installations/new
Webhook URLhttps://api.terrantula.io/webhooks/githubhttps://YOUR-DOMAIN/webhooks/github

Self-hosters register their own App and supply its credentials to the Terrantula API and worker (see Configuration).

Permissions

PermissionLevelWhy
contentswriteOpen PRs, push branches, fire repository_dispatch.
actionswriteTrigger repository_dispatch workflows.
pull_requestswriteOpen and update PRs.
issueswriteReserved for linking issues to action runs.
metadatareadRequired by GitHub for all Apps.

Webhook events

The App subscribes to the events that drive lifecycle and PR-trigger auto-completion:

EventUse
pull_requestTransition a PR-trigger ActionRun on merge/close.
pull_request_reviewReserved.
workflow_job, workflow_runReserved.
installationTrack install / suspend / delete lifecycle. Auto-delivered.
installation_repositoriesTrack repo-grant changes. Auto-delivered.

installation and installation_repositories are delivered automatically — no checkbox in the GitHub UI.

Install flow

  1. From project settings, Terrantula returns an install URL carrying a signed state JWT (POST /github/install-url, session-authed).
  2. You pick the org/account and the repositories to grant, then click Install.
  3. GitHub redirects to GET /github/install-callback?installation_id=…&state=…. The callback is authenticated by the signed state JWT — not a session or Bearer token. Terrantula validates the state, fetches installation metadata + granted repos, and upserts a github_installations row with status active.
  4. In parallel, GitHub fires an installation webhook to /webhooks/github. The callback is the source of truth for row creation; the webhook is acknowledged.

A cross-tenant install collision (an installation already claimed by another org) returns 409 and never leaks which org owns it.

TIP

If you close the install tab before the redirect lands, the row may be missing. An org owner/admin can claim it with POST /github/installations/recover ({ orgId, installationId }).

Credential resolution

PR-opening triggers (and postMergeDispatch) pick a GitHub credential at dispatch time:

  1. Linked installation, no auth.token → mint an installation token for the target repo (link read from project_github_repos). Preferred.
  2. No installation, auth.token supplied → use the static token (or the referenced {{ secrets.* }} value) as-is. The OSS / Sam-cohort escape hatch.
  3. Both → the installation token wins; a structured warning is logged (no token values).
  4. Neither → the Action fails with a message telling you to link the repo or supply trigger.auth.token.

Every dispatch emits a github-dispatch-attempted audit event with credential_type, repo, installation_id (when applicable), and outcome — no token values are ever logged.

WARNING

A static auth.token used for repository_dispatch must have contents:writescope on the target repo. Installation tokens get this automatically from the App's permissions.

Configuration

Self-hosters set four environment variables on the API and worker. The PR-opening surface is gated on TERRANTULA_DEPLOYMENT=cloud in the API; the OSS default uses static-token credentials only (no SaaS dependency).

Env varValue
GITHUB_APP_IDNumeric App ID.
GITHUB_APP_NAMEThe App slug (the /apps/<slug> URL segment), not the display name.
GITHUB_APP_PRIVATE_KEYThe full PEM (GitHub emits PKCS#1; PKCS#8 also accepted).
GITHUB_APP_WEBHOOK_SECRETThe webhook secret you set in App settings — must match exactly.

If any are missing, all GitHub routes return HTTP 503 — Terrantula does not crash; GitHub integration is simply unavailable. See the Configuration reference for the full env list.

Notes

  • Soft delete only. DELETE /github/installations/:id marks the row deleted in Terrantula; it does not uninstall the App on GitHub — that stays user-controlled. GitHub installation deleted/suspend webhooks also flip the row and revoke cached installation tokens.
  • Repo-grant changes (adding/removing repos from the install) arrive via the installation_repositories webhook and update the cached granted_repos.
  • Webhook 401 = secret mismatch between App settings and GITHUB_APP_WEBHOOK_SECRET. There is no grace period; restart the API after changing either.