infrastructure

package
v0.22.0 Latest Latest
Warning

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

Go to latest
Published: Jul 6, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package infrastructure holds the notification adapters: the messages repository over the store, the Slack messenger over the platform client, and the GitHub inbound receiver.

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 needs nowhere near that — a generous 1 MiB protects against memory exhaustion.

Variables

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

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

Functions

func BitbucketSignatureMiddleware added in v0.22.0

func BitbucketSignatureMiddleware(verifier security.SignatureVerifier) func(http.Handler) http.Handler

BitbucketSignatureMiddleware returns an HTTP middleware that rejects any request whose body exceeds MaxBodyBytes (413) or whose X-Hub-Signature header does not match the HMAC of the body (401), and passes a fresh body reader to next so downstream handlers read the verified body. Bitbucket sends no signature header when no secret is configured, so a missing header is rejected 401 — unsigned deliveries are never trusted.

func NewBitbucketHandler added in v0.22.0

func NewBitbucketHandler(dispatcher domain.EventDispatcher) http.Handler

NewBitbucketHandler returns an http.Handler that parses the JSON body of an inbound Bitbucket webhook, maps it to a kernel.Event, and dispatches it. It assumes the body has already been validated by BitbucketSignatureMiddleware. It returns 400 if the body is not valid JSON or has no pullrequest.id, 200 with body "ok" after a successful dispatch, and 500 if dispatch returns an error.

func NewGitHubHandler

func NewGitHubHandler(dispatcher domain.EventDispatcher) http.Handler

NewGitHubHandler returns an http.Handler that parses the JSON body of an inbound GitHub webhook, maps it to a kernel.Event, and dispatches it. It assumes the body has already been validated by SignatureMiddleware. It returns 400 if the body is not valid JSON or has no pull_request.number, 200 with body "ok" after a successful dispatch, and 500 if dispatch returns an error.

func SignatureMiddleware

func SignatureMiddleware(verifier security.SignatureVerifier) func(http.Handler) http.Handler

SignatureMiddleware returns an HTTP middleware that rejects any request whose body exceeds MaxBodyBytes (413) or whose X-Hub-Signature-256 header does not match the HMAC of the body (401), and passes a fresh body reader to next so downstream handlers read the verified body.

Types

type MessageRepo

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

MessageRepo adapts the store's PullRequests repository to the notification MessageStore port, mapping store persistence models to domain DTOs at the boundary so no gorm-tagged type crosses a port. The "not found" sentinel passes through unchanged (persistence.ErrNotFound aliases the routing domain sentinel handlers compare against).

func NewMessageRepo

func NewMessageRepo(pullRequests *persistence.PullRequests) *MessageRepo

NewMessageRepo wraps the store's PullRequests repository.

func (*MessageRepo) AddMessage

func (r *MessageRepo) AddMessage(ctx context.Context, repository string, prNumber int, channel, messageID string) error

AddMessage implements domain.MessageStore.

func (*MessageRepo) Delete

func (r *MessageRepo) Delete(ctx context.Context, repository string, prNumber int) error

Delete implements domain.MessageStore.

func (*MessageRepo) MarkClosed

func (r *MessageRepo) MarkClosed(ctx context.Context, repository string, prNumber int) error

MarkClosed implements domain.MessageStore.

func (*MessageRepo) Messages

func (r *MessageRepo) Messages(ctx context.Context, repository string, prNumber int) ([]domain.Message, error)

Messages implements domain.MessageStore, mapping store rows to domain Messages.

func (*MessageRepo) Touch

func (r *MessageRepo) Touch(ctx context.Context, repository string, prNumber int) error

Touch implements domain.MessageStore.

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.
	PRComment bool

	// Sender is the actor who fired the event.
	Sender Sender
}

Payload is the parsed view of an inbound GitHub webhook body, holding only the fields the notifier uses.

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 (a PR number); everything else is best-effort.

type PullRequest

type PullRequest struct {
	Number    int
	Title     string
	URL       string
	Author    string
	Merged    bool
	Draft     bool
	Body      string
	CreatedAt time.Time
}

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

type Sender struct {
	Login string
	Type  string
}

Sender identifies the actor that fired the webhook.

type SlackMessenger

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

SlackMessenger implements the notification Messenger port over the Slack client and composer. It owns the message shaping: which composer template and which marker blocks each notification intent renders to. The application hands it domain intent; no Slack type crosses the port.

func NewSlackMessenger

func NewSlackMessenger(client *slack.Client, composer *slack.Composer) *SlackMessenger

NewSlackMessenger wraps the platform Slack client and composer.

func (*SlackMessenger) AddReaction

func (m *SlackMessenger) AddReaction(ctx context.Context, channel, messageID, emoji string) error

AddReaction implements domain.Messenger.

func (*SlackMessenger) Delete

func (m *SlackMessenger) Delete(ctx context.Context, channel, messageID string) error

Delete implements domain.Messenger.

func (*SlackMessenger) PostOpen

func (m *SlackMessenger) PostOpen(ctx context.Context, channel string, req domain.OpenRequest) (string, error)

PostOpen implements domain.Messenger.

func (*SlackMessenger) UpdateClosed

func (m *SlackMessenger) UpdateClosed(ctx context.Context, channel, messageID string, req domain.ClosedRequest) error

UpdateClosed implements domain.Messenger.

func (*SlackMessenger) UpdateReviewFinished

func (m *SlackMessenger) UpdateReviewFinished(ctx context.Context, channel, messageID string, req domain.ReviewFinishedRequest) error

UpdateReviewFinished implements domain.Messenger.

Jump to

Keyboard shortcuts

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