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
- Variables
- func NewGitHubHandler(dispatcher domain.EventDispatcher) http.Handler
- func SignatureMiddleware(verifier security.SignatureVerifier) func(http.Handler) http.Handler
- type MessageRepo
- func (r *MessageRepo) AddMessage(ctx context.Context, repository string, prNumber int, ...) error
- func (r *MessageRepo) Delete(ctx context.Context, repository string, prNumber int) error
- func (r *MessageRepo) MarkClosed(ctx context.Context, repository string, prNumber int) error
- func (r *MessageRepo) Messages(ctx context.Context, repository string, prNumber int) ([]domain.Message, error)
- func (r *MessageRepo) Touch(ctx context.Context, repository string, prNumber int) error
- type Payload
- type PullRequest
- type Review
- type Sender
- type SlackMessenger
- func (m *SlackMessenger) AddReaction(ctx context.Context, channel, messageID, emoji string) error
- func (m *SlackMessenger) Delete(ctx context.Context, channel, messageID string) error
- func (m *SlackMessenger) PostOpen(ctx context.Context, channel string, req domain.OpenRequest) (string, error)
- func (m *SlackMessenger) UpdateClosed(ctx context.Context, channel, messageID string, req domain.ClosedRequest) error
- func (m *SlackMessenger) UpdateReviewFinished(ctx context.Context, channel, messageID string, ...) error
Constants ¶
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 ¶
var ErrMissingPRNumber = errors.New("notification: missing pull_request.number")
ErrMissingPRNumber is returned when the payload lacks a pull request number.
Functions ¶
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 ¶
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) MarkClosed ¶
MarkClosed 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 ¶
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 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.