← Back to Guides

GitHub Apps in Canopy#

Canopy supports GitHub App installations and ordinary GitHub OAuth users. This guide focuses on App setup, webhooks, and event workflows, while identifying the separate OAuth setup.

Three things to understand#

A GitHub App registration is the App's identity: its name, IDs, private key, permissions, and webhook settings. An installation grants that App access to selected repositories in a personal account or organization. A Canopy connection points to that installation so workflows know which GitHub account and repositories to use.

github is a GitHub App installation connection. github_oauth is an ordinary GitHub OAuth user connection. App installations provide repository-scoped permissions and webhook deliveries; OAuth connections authorize the user and request exactly repo or public_repo. Do not paste a PAT into either connection type.

Where to create the App#

For a personal account, open GitHub → Settings → Developer settings → GitHub Apps → New GitHub App: https://github.com/settings/apps.

For an organization-owned App, open that organization's Settings → Developer settings → GitHub Apps. The direct URL is usually https://github.com/organizations/<organization>/settings/apps; you may need organization-owner or administrator access.

Canopy supports independent environment defaults and separate custom App entries in Settings → Custom Apps for GitHub App and GitHub OAuth. Use an environment default when one registration serves the deployment; use a custom entry when a workspace needs its own registration.

Configure the GitHub App#

${APP_URL} means the Canopy backend origin. ${FRONTEND_URL} means the visible Canopy application origin. Prefer the URLs that Canopy displays in Settings when they are available.

1. Register the App in GitHub#

Create the App in the personal account or organization where it should live. Set its homepage to ${FRONTEND_URL} if GitHub asks for one. Set the App user authorization callback to ${APP_URL}/api/oauth/connections/github/callback and Setup URL to ${APP_URL}/api/oauth/connections/github/setup/callback.

Enable Setup URL and leave Request user authorization (OAuth) during installation off.

Choose the minimum permissions for the workflows you plan to run. Create and download the private key PEM, then record the App ID, client ID, client secret, and App slug. Custom-App private keys and secrets are write-only in Canopy.

2. Choose and configure the App source#

Environment-default source: the deployment operator supplies the values below and restarts or redeploys Canopy:

GITHUB_APP_CLIENT_ID=<github-app-client-id>
GITHUB_APP_CLIENT_SECRET=<github-app-client-secret>
GITHUB_APP_ID=<numeric-github-app-id>
GITHUB_APP_SLUG=<github-app-slug>
GITHUB_APP_PRIVATE_KEY_PATH=<path-to-private-key-pem>
GITHUB_APP_WEBHOOK_SECRET=<github-app-webhook-secret>

After Canopy is running, configure the GitHub App webhook: set Webhook URL to ${APP_URL}/api/webhooks/github/default, set Webhook secret to the same value as GITHUB_APP_WEBHOOK_SECRET, subscribe to the required events, turn Active on, and keep SSL verification enabled.

Workspace custom source: leave the GitHub webhook inactive while the source is being created. Generate a webhook secret with openssl rand -hex 32. Open Settings → Custom Apps and save the App ID, slug, client ID, client secret, private key PEM, Permissions JSON, and webhook secret. These secret fields are write-only. Canopy then displays the custom webhook callback; copy it back to GitHub as the Webhook URL, enter the same Webhook secret, subscribe to the required events, turn Active on, and keep SSL verification enabled.

Saving the custom source before its callback exists is expected. GitHub's webhook form has Active, Webhook URL, Webhook secret, and SSL verification; it has no content-type control. GitHub allows one webhook URL per App registration, so use separate App registrations for deployments or workspaces that need different callbacks.

Ordinary GitHub OAuth#

In Settings → Custom Apps, create or select the separate GitHub OAuth custom App entry and register ${APP_URL}/api/oauth/connections/github_oauth/callback in GitHub. Its independent environment default uses:

GITHUB_OAUTH_CLIENT_ID=<github-oauth-client-id>
GITHUB_OAUTH_CLIENT_SECRET=<github-oauth-client-secret>
GITHUB_OAUTH_REPOSITORY_SCOPE=repo|public_repo

OAuth connections authorize an ordinary GitHub user and request exactly the configured repo or public_repo scope. They support shared GitHub nodes and AI tools, but not event triggers or App webhooks.

Operations targeting a specific repository accept an optional owner. A trimmed explicit owner wins; otherwise App connections use the installation account login and OAuth connections use the verified user login. Repository listing (list_repos / github_list_repositories) does not accept owner; it uses /installation/repositories for github and /user/repos for github_oauth.

3. Install and connect#

Open Settings → Connections, start the GitHub App (github) connection, and follow the installation flow. Choose the personal account or organization, select all repositories or only the repositories your workflows need, complete the Setup URL flow, and save the connection. For an ordinary user connection, select GitHub OAuth (github_oauth) and complete its OAuth flow.

4. Save and enable a workflow#

Select either connection type in a GitHub node or tools node. Select github for an event trigger. Configure the event subscription and typed or raw trigger filter, save the workflow, and enable it. For a failed-CI workflow, use the workflow_run subscription and filter for action completed, the desired branch, and conclusion failure.

Permissions and capabilities#

GitHub's exact permission levels are Read-only and Read & write. Start with Read-only and grant Read & write only where a workflow creates or comments on resources.

GitHub permission Canopy capability Minimum level
Metadata Installation and repository identity Read-only
Issues List issues and receive issues; create issues and comments Read-only; Read & write to create
Pull requests List pull requests and receive pull_request; create pull requests Read-only; Read & write to create
Actions Receive workflow_run events Read-only
Checks Receive check_run and check_suite events Read-only
Contents Receive push events Read-only

Canopy doesn't need Contents write or Workflows write. API-only use needs Metadata Read-only, plus Issues and Pull requests Read-only for list/get. Add Issues Read & write for issue creation or comments, and Pull requests Read & write for pull request creation.

Webhooks and event triggers#

Subscribe the App to the events required by your workflow. Canopy provides typed trigger presets for workflow_run, check_run, check_suite, pull_request, push, and issues. These require the matching subscription and permission: Actions Read-only for workflow_run, Checks Read-only for check events, Pull requests Read-only for pull_request, Contents Read-only for push, and Issues Read-only for issues.

A failed-CI trigger commonly filters workflow_run to action completed, branch main, and conclusion failure. Raw event mode matches the exact X-GitHub-Event name and optional action. It doesn't bypass GitHub permissions: subscribe to that event and grant the permission GitHub requires.

Permissions JSON for custom Apps#

In Settings → Custom Apps, Permissions JSON records the App permissions declared for the workspace; it doesn't grant permissions in GitHub by itself:

{
  "metadata": "read",
  "issues": "write",
  "pull_requests": "write",
  "actions": "read",
  "checks": "read",
  "contents": "read"
}

Workflows can now handle failed CI, issue and pull-request intake, push and check reactions, and list/get/create/comment/pull-request operations. Selected AI Agent GitHub tools are also available through the GitHub tools node; enable write tools deliberately and require confirmation for write actions.

Minimum configurations#

  • API operations: Metadata Read-only; Issues and Pull requests Read-only for list/get, with Read & write only for create/comment operations. No webhook is needed.
  • Failed CI: Metadata Read-only, Actions Read-only, and the workflow_run subscription.
  • Event automation: Metadata Read-only plus only the event permissions and subscriptions used by the workflow.

Troubleshooting#

  • Missing organization or repository: for an App, check the installation account, repository selection, organization approval, and selected installation. For OAuth, check the authorized user and repo or public_repo scope.
  • Webhook signature errors: verify the App source, callback URL, and exact secret on both GitHub and Canopy. Replace it on both sides if regenerated.
  • No workflow starts: check Active, event subscription, repository selection, exact owner/name, and event/action/branch/conclusion filters.
  • Permission errors: update the App permission, save it in GitHub, and refresh or approve the installation. Read-only cannot create issues, comments, or pull requests.
  • Private-key errors: use the downloaded PEM with line breaks intact; custom sources can save the field again in Settings → Custom Apps.
  • SAML or organization policy blocks access: authorize the GitHub user or App and ask an organization owner to approve the installation.