Documentation
¶
Overview ¶
Package pullrequest holds the domain model for GitHub pull-request events and the handlers that update Slack in response. Adding a new event trigger means: write a new file in this package implementing EventHandler, register it in the composition root, add a unit test. The dispatcher and the rest of the pipeline do not change.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ApproveHandler ¶
type ApproveHandler struct {
// contains filtered or unexported fields
}
ApproveHandler adds a reaction when a review is submitted with state "approved".
func NewApproveHandler ¶
func NewApproveHandler( messages SlackMessages, mappings RepoMappings, slackClient SlackClient, logger *slog.Logger, emoji string, detector *aireview.Detector, ) *ApproveHandler
NewApproveHandler builds an ApproveHandler. detector must be non-nil; pass aireview.NewDetector(false) for the disabled state.
func (*ApproveHandler) Applicable ¶
type CloseHandler ¶
type CloseHandler struct {
// contains filtered or unexported fields
}
CloseHandler reacts to a PR being closed (merged or not). It updates the original Slack message with a [Merged]/[Closed] decoration and, if enabled, adds the corresponding reaction emoji.
func NewCloseHandler ¶
func NewCloseHandler( messages SlackMessages, mappings RepoMappings, slackClient SlackClient, composer *slack.Composer, logger *slog.Logger, opts CloseOptions, ) *CloseHandler
NewCloseHandler builds a CloseHandler.
func (*CloseHandler) Applicable ¶
func (h *CloseHandler) Applicable(e Event) bool
Applicable returns true when the action is "closed".
type CloseOptions ¶
CloseOptions tunes the CloseHandler. Reactions on close are toggleable because that's how the legacy PHP service exposed them.
type CommentedHandler ¶
type CommentedHandler struct {
// contains filtered or unexported fields
}
CommentedHandler adds a reaction when a review is submitted or edited with state "commented".
func NewCommentedHandler ¶
func NewCommentedHandler( messages SlackMessages, mappings RepoMappings, slackClient SlackClient, logger *slog.Logger, emoji string, detector *aireview.Detector, ) *CommentedHandler
NewCommentedHandler builds a CommentedHandler. detector must be non-nil; pass aireview.NewDetector(false) for the disabled state.
func (*CommentedHandler) Applicable ¶
type Dispatcher ¶
type Dispatcher struct {
// contains filtered or unexported fields
}
Dispatcher routes an Event to the first registered EventHandler whose Applicable returns true. Handlers are checked in the order they were registered. If no handler matches, Dispatch logs a Debug line and returns nil (no error) so the HTTP layer still responds 200 OK.
func NewDispatcher ¶
func NewDispatcher(logger *slog.Logger, handlers ...EventHandler) *Dispatcher
NewDispatcher builds a Dispatcher with the given handlers. Registration order is preserved. The logger receives one Debug record per event with no applicable handler — operators enable LOG_LEVEL=debug to triage silent 200 OK deliveries.
type DraftHandler ¶
type DraftHandler struct {
// contains filtered or unexported fields
}
DraftHandler reacts to a PR being converted back to draft. It removes the Slack notification and forgets the message TS — the PR will be re-announced when it's marked ready_for_review again.
func NewDraftHandler ¶
func NewDraftHandler( messages SlackMessages, mappings RepoMappings, slackClient SlackClient, logger *slog.Logger, ) *DraftHandler
NewDraftHandler builds a DraftHandler.
func (*DraftHandler) Applicable ¶
func (h *DraftHandler) Applicable(e Event) bool
Applicable returns true when the action is "converted_to_draft".
type Event ¶
type Event struct {
GitHubEvent string
Action string
Repository string
PR PR
// Review is non-nil only for pull_request_review events.
Review *Review
// Sender identifies the actor that fired the webhook. Type is "User"
// for humans and "Bot" for GitHub Apps (Copilot, dependabot, …).
Sender Sender
}
Event is the immutable record of an incoming pull-request-related webhook, detached from any HTTP payload type. Handlers receive Event and decide via Applicable whether they should run.
type EventHandler ¶
EventHandler is implemented by each PR-lifecycle handler.
Applicable inspects an event and returns true if Handle should run. The dispatcher invokes the first handler whose Applicable returns true and skips the rest — handlers are mutually exclusive.
type OpenHandler ¶
type OpenHandler struct {
// contains filtered or unexported fields
}
OpenHandler reacts to a PR being opened (non-draft) or marked ready_for_review. It posts the first Slack message for the PR and records the message TS for later updates.
func NewOpenHandler ¶
func NewOpenHandler( messages SlackMessages, mappings RepoMappings, slackClient SlackClient, composer *slack.Composer, logger *slog.Logger, ) *OpenHandler
NewOpenHandler builds an OpenHandler.
func (*OpenHandler) Applicable ¶
func (h *OpenHandler) Applicable(e Event) bool
Applicable returns true for "ready_for_review", or "opened" on a non-draft PR.
type RepoMappings ¶
type RepoMappings interface {
Get(ctx context.Context, repository string) (store.RepoMapping, error)
}
RepoMappings reads the per-repository routing to a Slack channel.
type RequestChangeHandler ¶
type RequestChangeHandler struct {
// contains filtered or unexported fields
}
RequestChangeHandler adds a reaction when a review is submitted with state "changes_requested".
func NewRequestChangeHandler ¶
func NewRequestChangeHandler( messages SlackMessages, mappings RepoMappings, slackClient SlackClient, logger *slog.Logger, emoji string, detector *aireview.Detector, ) *RequestChangeHandler
NewRequestChangeHandler builds a RequestChangeHandler. detector must be non-nil; pass aireview.NewDetector(false) for the disabled state.
func (*RequestChangeHandler) Applicable ¶
type Review ¶
type Review struct {
State string
}
Review carries the review state (approved | commented | changes_requested).
type Sender ¶ added in v0.5.0
Sender identifies the actor on the webhook payload (the reviewer for review events, the PR author for `pull_request` opened events, etc.).
type SlackClient ¶
type SlackClient interface {
PostMessage(ctx context.Context, channel, text string) (ts string, err error)
UpdateMessage(ctx context.Context, channel, ts, text string) error
DeleteMessage(ctx context.Context, channel, ts string) error
AddReaction(ctx context.Context, channel, ts, name string) error
}
SlackClient is the subset of the slack package's client that handlers use.
type SlackMessages ¶
type SlackMessages interface {
Save(ctx context.Context, m store.SlackMessage) error
Get(ctx context.Context, repository string, prNumber int) (store.SlackMessage, error)
Delete(ctx context.Context, repository string, prNumber int) error
}
SlackMessages reads and writes the per-PR Slack message TS record.