Integrations

GitHub integration

StagingReservation is a GitHub App — it connects to your repos via GitHub's permission model, not via personal access tokens. Each workspace can install on a different account or org.

What about my source code?

It stays in your repo. We never fetch file contents — no source, no READMEs, no configuration, no git history beyond the SHA pointed to by each ref. The only Contents-scoped API calls we make are:

  • GET /repos/.../branches and /tags (ref names only)
  • GET /repos/.../git/ref/heads/<branch> (the SHA at a branch tip, only when creating a new branch/tag from the board)
  • POST / DELETE /repos/.../git/refs/... (branch + tag CRUD, triggered by explicit owner/admin click on the board)

If you grep our server code (src/server/github.ts) you will not find a single call to /repos/.../contents or any equivalent. Full list on the security page.

This applies to your private repos too. The guarantee is about the API calls we make, not repo visibility. One honest caveat: GitHub's permission model bundles branch/tag/ref access and file-content access under the same Contents scope — there is no narrower permission that exposes refs without also permitting file reads. So the promise is enforced by our code, not by the scope: we hold Contents to read refs (and optionally write branches), and never call the file-contents endpoint. Ways to verify or tighten it:

  • Read src/server/github.ts — there is no /contents call.
  • Install the App on a single repo instead of "All repositories".
  • Grant Contents: Read only (no write) if you don't need the create-branch / create-tag controls.

What permissions does the App need?

| Permission | Access | Why | |------------|--------|-----| | Contents | Read | List branches and tags so slot patterns can resolve to real refs. | | Contents | Read & write | Optional but recommended. Lets the app create or delete branches/tags from the board and Environments page. Without this, you can still mirror — but the "+ Create branch" controls return a "needs Contents: write" error. | | Metadata | Read | Required by every GitHub App install. | | Deployments | Read | Receive deployment_status events so slot status flows Deploying → Live. | | Pull requests | Read | Useful for trunk-based templates that watch pr-* branches. |

The app stores no GitHub tokens long-term. Every API call mints a short-lived installation token from the App's private key + your installation ID.

Webhook events we listen to

| Event | What we do with it | |-------|--------------------| | push | Match the ref against every slot's branch pattern. If a slot matches, set currentRef = branch, currentSha, currentStatus = Deploying. | | create (ref type tag) | Same, but for tag slots. | | deployment_status | Match the deployment's environment against deployment slots. Set currentRef, currentUrl, status from the deployment's state. |

Every webhook delivery is HMAC-SHA256 verified against your App's webhook secret before any processing. Malformed or unsigned payloads return 401 and are not persisted.

What about protected branches?

The app refuses to create or delete any branch named main or develop, regardless of permissions. This is a hard-coded guard in the app — granting Contents: write doesn't override it. To work on those branches you do it on GitHub directly.

Installing for the first time

From a workspace's Repos page, click Connect GitHub. The flow:

  1. GitHub asks which account / org to install on.
  2. Pick "All repositories" or a specific list.
  3. Accept the permission scopes above.
  4. GitHub redirects back to the workspace's setup URL.

The setup URL is set on the App in GitHub: https://<your-host>/github/setup. Workspace owners shouldn't have to touch this — it's set up by whoever runs the StagingReservation deployment.

Adding or removing repos later

The same Connect GitHub button reopens the GitHub install configuration. You can add or remove repos at any time without disconnecting from the workspace. Repos you've already connected appear under Connected repos with a Disconnect button — that removes the repo from this workspace but does not uninstall the App from your GitHub account.

Uninstalling

Uninstall the App from GitHub's Settings → Applications → Installed GitHub Apps. This revokes all access immediately. Slots that were tracking repos via the uninstalled installation will stop receiving webhook events; their currentRef/currentSha stay at the last known value until you reconnect or rebind.

Troubleshooting

  • "The GitHub App can't write to this repo" — Contents is set to Read. Open the App's settings on GitHub, set Contents: Read & write, and re-approve the installation.
  • "That branch or tag already exists" — pick a different name or use the existing ref.
  • Repos page is empty under "Available to connect" — the App is installed on a different account than the repos you want; open Manage GitHub access and add the right org or specific repos.
  • Board shows no activity — confirm the App has webhook delivery enabled on GitHub, and that your CI emits deployment_status events. Webhooks land at /api/webhooks/github on this host.