GitHub
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)
Create a GitHub App. Permissions: Contents (read), Pull requests (read and write), Issues (read and write), Deployments (read), Metadata (read). Subscribe to
Deployment statusandInstallationevents.Webhook URL
https://<WT_PUBLIC_URL>/connect/github/webhookand a webhook secret. Setup URLhttps://<WT_PUBLIC_URL>/connect/github/setup, with "Request user authorization (OAuth) during installation" on.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 sharedWT_PUBLIC_URL,WT_INTERNAL_TOKEN,WT_API_INTERNAL_URLandWT_SECRET_KEY. For GitHub Enterprise Server alsoWT_GITHUB_API_BASE(https://ghe.example.com/api/v3) andWT_GITHUB_WEB_BASE(https://ghe.example.com). Both must behttps.
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-256before the body is parsed; a wrong signature is a 401. A redelivery of the sameX-GitHub-Deliveryis ignored. A deployment that can never succeed (unknown environment, lost role, unmapped repository) is answered 202 and counted in thescm_webhook_errorsexpvar; only a transient failure is answered 5xx so GitHub retries it.Commits. A release created with a
refgets its commits (at most 250, with the files of each) from the compare API between the previous release'srefand 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_statuswith statesuccessbecomes a deployment in the environment of the same name. The release is the existing one with thatref, else a new one named by the first 12 characters of the sha. Use this orwtctl release create --deploy, not both (seeci.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 afteriss_in the issue's id (shown on the issue page asWT-...).Fixed,ResolvesandResolvedwork 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.