GitHub App setup
Octopus uses a GitHub App (not OAuth, not the gh CLI) to receive PR webhooks and post review comments as a bot identity. This page walks you through creating one. Estimated time: 5 minutes.
Why a GitHub App and not the gh CLI
Three things only the App model gives you, and they matter for a continuous-review tool:
- Webhooks. GitHub pushes
pull_requestevents to your server when PRs open or get new commits. TheghCLI has no webhook registration; you'd have to poll, which is slow and rate-limited. - Bot identity. Review comments appear as
your-app[bot], distinct from any human reviewer. User-OAuth comments show up under whoever's token you used. - Per-repo scoped permissions. An org admin picks exactly which repos Octopus can see. Survives users leaving the org and key rotations.
For one-off octp review --pr <PR> from the CLI, a personal token works fine. The web app + auto-review-every-PR flow needs the App.
Step-by-step
- Open github.com/settings/apps/new (or for an org:
Settings → Developer settings → GitHub Apps → New GitHub App). - GitHub App name — pick anything; this is what shows up as the comment author. Examples:
octopus-reviewfor production,octopus-stagingfor staging. Names must be globally unique on GitHub. - Homepage URL — your deployment URL, eg.
https://octopus.example.com. - Callback URL — leave blank.
- Setup URL (under Post installation) — set to
https://your-domain/api/github/callback, and check Redirect on update. GitHub redirects users here after install, carrying theinstallation_idand signedstatethe callback needs to link the installation back to the org. Without it the install completes on github.com, the callback never fires, and reviews never start. - Webhook — check Active. URL:
Generate a random webhook secret (any high-entropy string, eg.https://your-domain/api/github/webhookopenssl rand -hex 32) and paste it. Keep a copy — you'll need it forGITHUB_WEBHOOK_SECRET. - Permissions — repository permissions:
Contents: Read-only (Octopus clones to index)Pull requests: Read & write (post review comments)Checks: Read & write (set the review status check)Metadata: Read-only (automatic — leave default)
- Subscribe to events:
Pull request— main triggerPull request review— to react to human reviewer actions
- Where can this App be installed? — pick Any account if you want other orgs to install it; pick Only on this account for a private/self-hosted setup.
- Click Create GitHub App. You'll land on the App's settings page.
- Note the App ID at the top — this is your
GITHUB_APP_ID. - Note the slug from the URL bar (
github.com/settings/apps/this-part) — this is yourNEXT_PUBLIC_GITHUB_APP_SLUG. - Scroll to Private keys → Generate a private key. A
.pemfile downloads. Open it; the contents are yourGITHUB_APP_PRIVATE_KEY(paste with newlines preserved).
Env vars
Drop these into your .env:
GITHUB_APP_ID=123456
GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...lines from the .pem file...
-----END RSA PRIVATE KEY-----"
GITHUB_WEBHOOK_SECRET=<the secret you generated above>
NEXT_PUBLIC_GITHUB_APP_SLUG=<the slug from the App's URL>Restart the server. The "Install GitHub App" button on /settings/integrations should now appear and link to https://github.com/apps/<slug>/installations/new.
Installing the App into your repos
From /settings/integrations click Install GitHub App. GitHub asks the user (must be a repo or org admin) to pick:
- All repositories — every repo the org has, now and in the future. Simplest; fine when Octopus runs reviews for the whole org.
- Only select repositories — explicit allowlist. Recommended for shared orgs where you only want Octopus on a subset.
After approval GitHub redirects back to /api/github/callback, Octopus stores the installation_id on your Organization row, and reviews start flowing on the next PR push.
Staging vs production — use separate Apps
Don't share one App across environments.Webhook URLs are fixed per-App, and you don't want production traffic hitting your staging server (or vice versa). Create one App per environment with a distinct webhook URL:
- Production:
octopus-review→https://octopus.example.com/api/github/webhook - Staging:
octopus-staging→https://staging.example.com/api/github/webhook - Local dev:
octopus-dev→https://your-ngrok-tunnel.app/api/github/webhook
Each App has its own App ID, private key, slug, and webhook secret — set them as distinct env values per environment. Test orgs install the staging App; real orgs install production. Local development installs the dev App into a sandbox org (eg. a personal account with one test repo).
Troubleshooting
Webhook deliveries failing
Open your App's Advanced tab on GitHub → Recent deliveries. Failed deliveries show the response status. Common causes:
401 invalid signature— webhook secret mismatch. The secret you set on the App must equal the env varGITHUB_WEBHOOK_SECRET.404— wrong webhook URL on the App, or your server isn't reachable from GitHub's IPs.500— check your server logs. Often a database not being reachable.
Reviews aren't posting
Webhooks are arriving but no review comment shows up. Check:
- App has
Pull requests: Read & write— not just read. - App is actually installed on the repo (it's possible for an org to install for "selected repos" that excludes the one you're testing).
- The review worker is running — if jobs are never picked up, set
ENABLE_REVIEW_WORKERS=trueon the review-engine process.
"GitHub App not configured" on /settings/integrations
NEXT_PUBLIC_GITHUB_APP_SLUGisn't set. Restart the server after editing .env — Next.js inlines NEXT_PUBLIC_*vars at build time, so a hot reload isn't enough.