GitHub

Embed
Preview of the card
<a href="https://forumulate.com/p/watchtower/docs/github"><img src="https://forumulate.com/api/public/orgs/watchtower/spaces/docs/pages/9031852b-a08b-412e-92aa-9dd9d7b63ecc/social-card.svg?v=3e7ae33eec8b" alt="GitHub" width="600" height="315"></a>

The Watchtower GitHub App fills a release's commits, records deployments, comments on pull requests and opens issues. One App serves every organization; each organization installs it once.

Set up (operator)

  1. Create a GitHub App. Permissions: Contents (read), Pull requests (read and write), Issues (read and write), Deployments (read), Metadata (read). Subscribe to Deployment status and Installation events.

  2. Webhook URL https://<WT_PUBLIC_URL>/connect/github/webhook and a webhook secret. Setup URL https://<WT_PUBLIC_URL>/connect/github/setup, with "Request user authorization (OAuth) during installation" on.

  3. Set on the notifier: WT_GITHUB_APP_ID, WT_GITHUB_APP_SLUG, WT_GITHUB_APP_PRIVATE_KEY (PEM), WT_GITHUB_CLIENT_ID, WT_GITHUB_CLIENT_SECRET, WT_GITHUB_WEBHOOK_SECRET, plus the shared WT_PUBLIC_URL, WT_INTERNAL_TOKEN, WT_API_INTERNAL_URL and WT_SECRET_KEY. For GitHub Enterprise Server also WT_GITHUB_API_BASE (https://ghe.example.com/api/v3) and WT_GITHUB_WEB_BASE (https://ghe.example.com). Both must be https.

Install (organization admin)

The API gets an install link from POST /internal/connect/github/state {org_id, user_id} and sends the admin to it. The callback only trusts the installation id in the URL when the signed-in GitHub user can see that installation. A GitHub installation already connected to another organization is refused. Then map repositories to projects with POST /internal/scm/repos {installation_id, project_id, repos: ["owner/name"]} (the API authorizes ManageProject first).

Installation tokens last an hour; the current one is stored sealed (AES-256-GCM, key from WT_SECRET_KEY) and replaced five minutes before it ends. Secrets are never logged.

What it does

  • Webhooks are verified with X-Hub-Signature-256 before the body is parsed; a wrong signature is a 401. A redelivery of the same X-GitHub-Delivery is ignored. A deployment that can never succeed (unknown environment, lost role, unmapped repository) is answered 202 and counted in the scm_webhook_errors expvar; only a transient failure is answered 5xx so GitHub retries it.

  • Commits. A release created with a ref gets its commits (at most 250, with the files of each) from the compare API between the previous release's ref and this one, within about a minute. They feed suspect-commit scoring. The first release of a project has no previous ref and gets none. Only one notifier fills a release at a time. A failed fill is retried with a backoff (30 s doubling, at most 1 h) for up to 24 hours; a release that is gone or whose answer is over 16 MiB is not retried. When the provider reports less than 10% of the rate limit left, or refuses the token, the installation is paused until the limit resets (at least a minute, at most an hour). A release is filled only by an installation that maps a repository to its project; when none does, it is left alone.

  • Deployments. deployment_status with state success becomes a deployment in the environment of the same name. The release is the existing one with that ref, else a new one named by the first 12 characters of the sha. Use this or wtctl release create --deploy, not both (see ci.md).

  • Resolve by commit. A commit message Fixes WT-<issue id> marks that issue resolved in the release. The issue id is the 26 characters after iss_ in the issue's id (shown on the issue page as WT-...). Fixed, Resolves and Resolved work too, and a closed or ignored issue is never changed. The installing user's role must allow resolving.

  • Pull request comments. After a deployment each pull request in the release gets one comment with up to five issues first seen in the release (titles are stripped of links and mentions). The comment id is stored per installation, repository and pull request, so the next deployment updates it; a deleted comment is posted again.

  • Create an issue from an error or trace page: POST /internal/scm/issue {installation_id, user_id, project_id, repo, target, title, link} opens a GitHub issue with a prefilled title and a link back to Watchtower.

Delivery is at-least-once; a redelivered webhook or a repeated fill never adds a second commit, comment or resolution.

Updated