# GitHub

Record deploys from GitHub events through a signed webhook.

A GitHub webhook records deploys without changes to your CI workflow.

## Set it up

1. Generate a random secret, for example with `openssl rand -hex 32`. Set it in the
   environment and map the repository to an existing kogut service:

   ```toml title="kogut.toml"
   [github]
   secret = "${GITHUB_WEBHOOK_SECRET}"

   [[github.repo]]
   name = "acme/api"
   service = "api"
   ```

   Repository names are case-insensitive. kogut reloads the file automatically.
2. On GitHub, open **Settings → Webhooks → Add webhook**. Enter
   `https://kogut.acme.com/hooks/github`, select `application/json`, and paste the same
   secret. Exempt `/hooks/github` from any sign-in proxy.
3. Select the events that match when your code goes live:
   - `push` records non-deletion pushes to the default branch, using the full head hash,
     pusher, and commit link.
   - `release` records published, non-draft releases, using the tag, author, and release
     link.
   - `deployment_status` records successful production deployments, using the commit,
     deployment creator, and environment URL. Use it when a push does not mean the
     release is live; see [Deployments](#deployments).
4. Under **Recent Deliveries**, check that GitHub's initial `ping` receives `204`.
   After a matching event, check the service's **Deploys** card.

For an organisation webhook, add a mapping for each repository. To record several
services from one repository, repeat `[[github.repo]]` with the same name and a different
service. If only some services change, use the [deploy API](https://docs.kogut.dev/deploys/api/) from CI.

## Deployments

GitHub sends `deployment_status` for GitHub Actions jobs that set `environment:`, and for
hosts that report through GitHub's Deployments API, such as Vercel. The repository's
**Deployments** list shows each environment name.

By default, kogut records a deployment only when GitHub marks its environment as
production or it is named `production` in any case. Preview deployments are skipped.

To record another environment, name it on the mapping. Only deployments to that
environment, in any case, are then recorded for that service. `push` and `release`
events are not affected.

```toml title="kogut.toml"
[[github.repo]]
name = "acme/api"
service = "api"

[[github.repo]]
name = "acme/api"
service = "api-staging"
environment = "staging"
```

If your production environment has another name, such as `live`, and GitHub does not
mark it as production, set `environment = "live"`.

## Fix failed deliveries

- `404`: add the `[github]` section.
- `401`: check the shared secret. Every request needs an HMAC-SHA256 signature in
  `X-Hub-Signature-256`.
- `400`: check that the JSON body matches the event.
- `422`: add the repository mapping.

Ignored events return `204`. Recorded events return `201`, or `200` when merged with a
recent deploy ([merge rules](https://docs.kogut.dev/deploys/api/#responses)).

If CI also calls the API, send the full commit hash, such as `$GITHUB_SHA`. A short hash
does not match GitHub's version, so the two do not merge.
