GitHub webhooks

DataMind Oda can receive GitHub webhook deliveries at an endpoint you set up. This page covers the endpoint's settings, the requests it accepts, the signature check, and the responses GitHub sees. What a delivery starts in Oda is on Webhook sessions.

Set up the endpoint

The endpoint is exactly one route on Oda's web address, at the path you configure. Set it up with these fields. Every one of them is required.

FieldWhat it is
sourceA name for this endpoint, for example primary-github. Each verified delivery carries it.
pathThe exact path of the endpoint, for example /github. It must start with /, must not be / alone, and must not end with a slash or carry a query or fragment.
secretEnvThe reference to the stored GitHub webhook secret. Oda resolves the reference for every request; the secret itself is not written here.
maxBodyBytesThe largest raw request body Oda accepts, in bytes. A positive whole number.

A value that fails a check refuses the endpoint before it registers, with messages such as webhook-github source must be a non-empty trimmed string and webhook-github path must be an absolute non-root pathname without a trailing slash, query, or fragment.

What a delivery must carry

How Oda verifies the signature

Every delivery is signed with your webhook secret. Oda resolves the secret for every request and verifies the signature over the raw body before it parses anything. A delivery with a wrong signature is answered invalid webhook signature (401), and its payload is never read. Oda never logs the secret, the signature or the payload.

Because the secret resolves for every request, rotating it takes effect on the next delivery; nothing is reloaded.

Responses GitHub sees

StatusWhen Oda returns itThe response body
202The delivery was verified and accepted in memory.Empty.
400A required header is missing or repeated, the body cannot be read as declared, or the payload fails its checks.missing <name> header, invalid Content-Length, request body was aborted, request body is not valid UTF-8, request body is not valid JSON, GitHub webhook payload must be a JSON object or GitHub webhook payload is not lossless JSON
401The signature does not match the secret.invalid webhook signature
405The request is not a POST.method not allowed, with the header allow: POST
413The declared or streamed body is larger than maxBodyBytes.request body is too large
415The media type is not application/json.content type must be application/json
503Oda cannot take the delivery: the secret reference does not resolve, the part of Oda that takes deliveries is unavailable, or the request could not be handled.GitHub webhook secret is unavailable, webhook runtime is unavailable or webhook ingress is unavailable

A 202 reports nothing about what the delivery starts in Oda; Webhook sessions covers that side.

Reaching the endpoint from GitHub

The endpoint has no TLS of its own. It is meant to run on a local address, behind a TLS reverse proxy or tunnel:

  1. Run the endpoint. By default it shares Oda's web address, the one that serves the interface (see Oda in the browser). It can also get a listener of its own, for example 127.0.0.1:3081, while the interface stays on its usual address.
  2. Put a TLS reverse proxy in front of that address.
  3. Give GitHub the public address the proxy serves, with the endpoint's path, and set GitHub's webhook secret to the secret the endpoint resolves.
Important

The endpoint adds no encryption of its own. Keep it on a local address and expose it only through a TLS reverse proxy or tunnel.

Questions, answered

Where do I point GitHub's webhook?

At the address that reaches your Oda webhook endpoint, with its path. If the endpoint runs on a local address, put a TLS reverse proxy in front and give GitHub the public address the proxy serves.

Which headers must a delivery carry?

X-Hub-Signature-256, X-GitHub-Delivery and X-GitHub-Event. Each must carry exactly one non-empty value; a missing or repeated header is refused with missing <name> header.

How does Oda check that a delivery is really from GitHub?

Oda verifies the delivery's signature against the webhook secret, over the raw body, before it parses anything. A wrong signature is answered invalid webhook signature (401), and the payload is never read.

Does rotating the webhook secret require a restart?

No. Oda resolves the secret for every request, so a rotated secret takes effect on the next delivery; nothing is reloaded.

What content type must GitHub send?

application/json. The media type may carry one parameter, and only charset=utf-8 is accepted. A form-encoded delivery is refused with content type must be application/json (415).

How large can a delivery be?

Up to maxBodyBytes. A larger body is refused with request body is too large (413), whether its size is declared in Content-Length or seen while the body is read. A declared length that is not a plain whole number is refused with invalid Content-Length (400).

Why did the endpoint answer 405?

The request was not a POST. The endpoint accepts only POST, and the answer is method not allowed with the header allow: POST.

What do the 503 responses mean?

Oda could not take the delivery. GitHub webhook secret is unavailable: the secret reference does not resolve, so check the credential. webhook runtime is unavailable: the part of Oda that takes deliveries is not available. webhook ingress is unavailable: the request could not be handled; try the delivery again later.

Does the endpoint check the fields of the event?

No. It checks the envelope only: that the delivery is authenticated and that the payload is lossless JSON. Checking the fields of a particular event, such as a pull_request, is up to the logic that acts on each delivery, not the endpoint.