githubhook

package
v0.13.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 5, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package githubhook authenticates and parses inbound GitHub webhook requests. It exposes a constant-time HMAC verifier, an HTTP middleware that gates a downstream handler, and a JSON parser for the pull request payloads we care about.

Index

Constants

View Source
const MaxBodyBytes int64 = 1 << 20 // 1 MiB

MaxBodyBytes caps the size of an accepted webhook body. GitHub limits its own webhook payloads to ~25 MiB but our handler should not need anywhere near that — a generous 1 MiB protects against memory exhaustion attacks.

View Source
const SignatureHeader = "X-Hub-Signature-256"

SignatureHeader is the HTTP header GitHub uses to carry the HMAC-SHA256 digest of the raw request body.

Variables

View Source
var ErrInvalidSignature = errors.New("githubhook: invalid signature")

ErrInvalidSignature is returned when the signature does not match.

View Source
var ErrMissingPRNumber = errors.New("githubhook: missing pull_request.number")

ErrMissingPRNumber is returned when the payload lacks a pull request number.

Functions

func NewHandler

func NewHandler(sink EventSink) http.Handler

NewHandler returns an http.Handler that parses the JSON body of an inbound GitHub webhook and forwards the parsed Payload to sink.

The handler assumes the body has already been validated by SignatureMiddleware. It returns:

  • 400 if the body is not valid JSON,
  • 400 if the payload has no pull_request.number,
  • 200 with body `"ok"` after the sink runs successfully,
  • 500 if the sink returns an error.

Response bodies are intentionally generic; details go to logs.

func Sign added in v0.11.0

func Sign(secret string, body []byte) string

Sign returns the "sha256=<hex>" HMAC of body under secret — the value GitHub puts in X-Hub-Signature-256. It is the inverse of Verify and shares the same scheme, so anything Sign produces, Verify accepts. Used by the smoke command to forge a correctly-signed request against the live endpoint.

func SignatureMiddleware

func SignatureMiddleware(v *Verifier) func(http.Handler) http.Handler

SignatureMiddleware returns an HTTP middleware that:

  • rejects any request whose body exceeds MaxBodyBytes (413),
  • rejects any request whose X-Hub-Signature-256 header does not match the HMAC of the body (401),
  • passes a fresh body reader to next, so downstream handlers can read the verified body without juggling the raw stream themselves.

Types

type EventSink

type EventSink func(ctx context.Context, p Payload) error

EventSink receives a parsed Payload. It is the seam between the HTTP layer and the pullrequest dispatcher; defining it here keeps githubhook unaware of any downstream package.

type Payload

type Payload struct {
	Event      string
	Action     string
	Repository string

	PullRequest PullRequest

	// Review is non-nil only for pull_request_review events.
	Review *Review

	// PRComment is true for issue_comment events fired on a pull request —
	// the payload carries an issue.pull_request reference. It is false for
	// comments on plain issues, which handlers ignore.
	PRComment bool

	// Sender is the actor who fired the event (GitHub's `sender` object).
	// Zero value when the field is absent in the payload.
	Sender Sender
}

Payload is the parsed view of an inbound GitHub webhook body, holding only the fields the notifier uses. Adding a new event-type usually means extending this struct rather than adding a new parser.

func ParsePayload

func ParsePayload(body []byte) (Payload, error)

ParsePayload decodes a raw GitHub webhook body into a Payload. It validates only what the dispatcher needs (PR number > 0); everything else is treated as best-effort and surfaced to handlers, which decide their own preconditions.

type PullRequest

type PullRequest struct {
	Number int
	Title  string
	URL    string
	Author string
	Merged bool
	Draft  bool
	// Body is the PR description. Used to tell a Dependabot/Renovate security
	// advisory apart from a routine bump (see internal/botpr).
	Body string
}

PullRequest holds the PR fields extracted from the payload.

type Review

type Review struct {
	State string
}

Review carries the review state (approved | commented | changes_requested).

type Sender added in v0.5.0

type Sender struct {
	Login string
	Type  string
}

Sender identifies the actor that fired the webhook. Type is "User" for humans and "Bot" for GitHub Apps or legacy bot accounts.

type Verifier

type Verifier struct {
	// contains filtered or unexported fields
}

Verifier checks HMAC-SHA256 signatures against a shared secret.

func NewVerifier

func NewVerifier(secret string) *Verifier

NewVerifier returns a Verifier configured with the given shared secret.

func (*Verifier) Verify

func (v *Verifier) Verify(body []byte, signature string) error

Verify checks that signature is a valid "sha256=<hex>" HMAC of body using the verifier's secret. Returns ErrInvalidSignature for any mismatch.

The comparison runs in constant time to prevent timing oracles.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL