infrastructure

package
v0.22.2 Latest Latest
Warning

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

Go to latest
Published: Jul 7, 2026 License: MIT Imports: 17 Imported by: 0

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

View Source
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

View Source
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

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

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 Action

type Action struct {
	ActionID string
	Value    string
}

Action is a single interactive element the user activated.

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) Finish

func (r *CodeReviewsRepo) Finish(ctx context.Context, repository string, prNumber int) error

Finish implements notificationdomain.ReviewSessions.

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.

func (*CodeReviewsRepo) Start

func (r *CodeReviewsRepo) Start(ctx context.Context, repository string, prNumber int, userID, userName string) error

Start implements reviewdomain.Recorder, mapping the store's active-exists sentinel to the review domain's.

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.

type User

type User struct {
	ID       string
	Username string
}

User is the Slack user who triggered the interaction.

Jump to

Keyboard shortcuts

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