Documentation
¶
Overview ¶
Package infrastructure holds the review adapters: the code-reviews repository over the store, the Slack message decorator, and the Slack interactions inbound receiver.
Index ¶
- Constants
- Variables
- func NewInteractionsHandler(sink InteractionSink, logger *slog.Logger) http.Handler
- func SignatureMiddleware(verifier security.SignatureVerifier) func(http.Handler) http.Handler
- type Action
- type Channel
- type CodeReviewsRepo
- func (r *CodeReviewsRepo) Finish(ctx context.Context, repository string, prNumber int) error
- func (r *CodeReviewsRepo) GetActive(ctx context.Context, repository string, prNumber int) (notificationdomain.ReviewSession, error)
- func (r *CodeReviewsRepo) HasActiveReview(ctx context.Context, repository string, prNumber int, userID string) (bool, error)
- func (r *CodeReviewsRepo) Reviewers(ctx context.Context, repository string, prNumber int) ([]notificationdomain.ReviewSession, error)
- func (r *CodeReviewsRepo) Start(ctx context.Context, repository string, prNumber int, userID, userName string) error
- type Interaction
- type InteractionSink
- type Message
- type MessageChecker
- type SlackDecorator
- type User
Constants ¶
const MaxBodyBytes int64 = 1 << 20 // 1 MiB
MaxBodyBytes caps the size of an accepted interaction body. Slack's interaction payloads are small, so 1 MiB is generous and guards against memory exhaustion.
Variables ¶
var ErrMissingPayload = errors.New("review: missing payload field")
ErrMissingPayload is returned when the form body has no `payload` field.
Functions ¶
func NewInteractionsHandler ¶
func NewInteractionsHandler(sink InteractionSink, logger *slog.Logger) http.Handler
NewInteractionsHandler returns an http.Handler that parses a Slack interaction body and forwards it to sink. It assumes the body was verified by SignatureMiddleware. Slack retries any non-2xx within ~3s, so the handler always responds 200 once the signature is trusted: a malformed or unactionable payload is logged and ignored. A sink error is logged but does not change the response.
func SignatureMiddleware ¶
SignatureMiddleware returns an HTTP middleware that rejects oversized bodies (413) and requests with a missing/invalid/stale Slack signature (401), passing a fresh body reader to next. The signature is verified over the raw bytes before any form parsing.
Types ¶
type Channel ¶
type Channel struct {
ID string
}
Channel is the conversation the interactive message lives in.
type CodeReviewsRepo ¶
type CodeReviewsRepo struct {
// contains filtered or unexported fields
}
CodeReviewsRepo adapts the store's CodeReviews repository to the review domain's Recorder port and — because review owns review sessions — to the notification ReviewSessions port the notification handlers consume. No gorm-tagged type crosses a port.
func NewCodeReviewsRepo ¶
func NewCodeReviewsRepo(codeReviews *persistence.CodeReviews) *CodeReviewsRepo
NewCodeReviewsRepo wraps the store's CodeReviews repository.
func (*CodeReviewsRepo) GetActive ¶
func (r *CodeReviewsRepo) GetActive(ctx context.Context, repository string, prNumber int) (notificationdomain.ReviewSession, error)
GetActive implements notificationdomain.ReviewSessions.
func (*CodeReviewsRepo) HasActiveReview ¶
func (r *CodeReviewsRepo) HasActiveReview(ctx context.Context, repository string, prNumber int, userID string) (bool, error)
HasActiveReview implements reviewdomain.Recorder.
func (*CodeReviewsRepo) Reviewers ¶
func (r *CodeReviewsRepo) Reviewers(ctx context.Context, repository string, prNumber int) ([]notificationdomain.ReviewSession, error)
Reviewers implements notificationdomain.ReviewSessions.
type Interaction ¶
type Interaction struct {
Type string
User User
Channel Channel
Message Message
Actions []Action
ResponseURL string
TriggerID string
}
Interaction is the parsed view of a Slack interaction envelope, holding only the fields notifycat uses.
func ParseInteraction ¶
func ParseInteraction(body []byte) (Interaction, error)
ParseInteraction decodes a Slack interaction request body (an application/x-www-form-urlencoded body with a single `payload` field holding URL-encoded JSON).
type InteractionSink ¶
type InteractionSink func(ctx context.Context, interaction Interaction) error
InteractionSink receives a parsed Interaction.
func NewStartReviewSink ¶
func NewStartReviewSink(handler reviewdomain.StartReview, logger *slog.Logger) InteractionSink
NewStartReviewSink adapts the review StartReview use case to an InteractionSink: it maps a "start_review" block_actions click to a StartReviewCommand and invokes the use case. Non-actionable interactions (wrong type, wrong action, malformed value) are ignored.
type Message ¶
type Message struct {
TS string
Text string
RawBlocks json.RawMessage
}
Message identifies the message that carried the interactive component. RawBlocks is the original blocks array echoed back by Slack for passthrough.
type MessageChecker ¶
type MessageChecker struct {
// contains filtered or unexported fields
}
MessageChecker adapts the store's PullRequests repository to the review MessageChecker port: an untracked PR reports false rather than erroring.
func NewMessageChecker ¶
func NewMessageChecker(pullRequests *persistence.PullRequests) *MessageChecker
NewMessageChecker wraps the store's PullRequests repository.
func (*MessageChecker) HasMessages ¶
func (c *MessageChecker) HasMessages(ctx context.Context, repository string, prNumber int) (bool, error)
HasMessages implements reviewdomain.MessageChecker.
type SlackDecorator ¶
type SlackDecorator struct {
// contains filtered or unexported fields
}
SlackDecorator implements the review MessageDecorator port over the Slack composer and client. It appends a "reviewing" marker to the PR message, passing the original blocks through untouched.
func NewSlackDecorator ¶
func NewSlackDecorator(composer *slack.Composer, client *slack.Client) *SlackDecorator
NewSlackDecorator wraps the Slack composer and client.
func (*SlackDecorator) AppendReviewingMarker ¶
func (d *SlackDecorator) AppendReviewingMarker(ctx context.Context, message reviewdomain.MessageRef, reviewer reviewdomain.Reviewer, since time.Time) error
AppendReviewingMarker composes the reviewing marker for the reviewer, inserts it immediately before the message's actions (button) block, and updates the message in place.