Documentation
¶
Overview ¶
Package bot provides the core bot coordinator logic.
Index ¶
- func FormatPRURL(owner, repo string, number int) string
- type Action
- type Analysis
- type CheckResponse
- type Checks
- type CommitPRCache
- type ConfigManager
- type Coordinator
- type CoordinatorConfig
- type DiscordClient
- type PRInfo
- type PRSearchResult
- type PRSearcher
- type PRURLInfo
- type SprinklerClient
- type SprinklerConfig
- type SprinklerEvent
- type StateStore
- type TokenProvider
- type TurnClient
- type TurnHTTPClient
- type UserMapper
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FormatPRURL ¶
FormatPRURL creates a GitHub PR URL from components.
Types ¶
type Analysis ¶
type Analysis struct {
NextAction map[string]Action `json:"next_action"`
WorkflowState string `json:"workflow_state"`
Size string `json:"size"`
Tags []string `json:"tags"`
Checks Checks `json:"checks"`
UnresolvedComments int `json:"unresolved_comments"`
ReadyToMerge bool `json:"ready_to_merge"`
Approved bool `json:"approved"`
MergeConflict bool `json:"merge_conflict"`
}
Analysis contains the PR analysis result.
type CheckResponse ¶
type CheckResponse struct {
PullRequest PRInfo `json:"pull_request"`
Analysis Analysis `json:"analysis"`
}
CheckResponse represents the Turn API response.
type Checks ¶
type Checks struct {
Pending int `json:"pending"`
Passing int `json:"passing"`
Failing int `json:"failing"`
Waiting int `json:"waiting"`
}
Checks contains CI check status.
type CommitPRCache ¶
type CommitPRCache struct {
// contains filtered or unexported fields
}
CommitPRCache caches commit SHA → PR number mappings. This allows quick lookup when check events arrive with just a commit SHA, avoiding expensive GitHub API calls for recently-seen PRs.
func NewCommitPRCache ¶
func NewCommitPRCache() *CommitPRCache
NewCommitPRCache creates a new commit→PR cache.
func (*CommitPRCache) FindPRsForCommit ¶
func (c *CommitPRCache) FindPRsForCommit(owner, repo, commitSHA string) []int
FindPRsForCommit returns PR numbers associated with a commit SHA.
func (*CommitPRCache) MostRecentPR ¶
func (c *CommitPRCache) MostRecentPR(owner, repo string) int
MostRecentPR returns the most recent PR number seen for a repo.
type ConfigManager ¶
type ConfigManager interface {
LoadConfig(ctx context.Context, org string) error
ReloadConfig(ctx context.Context, org string) error
Config(org string) (*config.DiscordConfig, bool)
ChannelsForRepo(org, repo string) []string
ChannelType(org, channel string) string
DiscordUserID(org, githubUsername string) string
ReminderDMDelay(org, channel string) int
When(org, channel string) string
GuildID(org string) string
SetGitHubClient(org string, client any)
}
ConfigManager defines configuration operations.
type Coordinator ¶
type Coordinator struct {
UserMapper UserMapper
// contains filtered or unexported fields
}
Coordinator orchestrates event processing for a GitHub organization.
func NewCoordinator ¶
func NewCoordinator(cfg CoordinatorConfig) *Coordinator
NewCoordinator creates a new coordinator for an organization.
func (*Coordinator) CleanupLocks ¶
func (c *Coordinator) CleanupLocks()
CleanupLocks removes idle locks to prevent unbounded memory growth. Should be called periodically from the main event loop.
func (*Coordinator) PollAndReconcile ¶
func (c *Coordinator) PollAndReconcile(ctx context.Context)
PollAndReconcile queries GitHub for PRs and reconciles their state. This serves as a backup mechanism when sprinkler events are missed.
func (*Coordinator) ProcessEvent ¶
func (c *Coordinator) ProcessEvent(ctx context.Context, event SprinklerEvent)
ProcessEvent handles an incoming sprinkler event.
func (*Coordinator) Wait ¶
func (c *Coordinator) Wait()
Wait waits for all pending event processing to complete.
type CoordinatorConfig ¶
type CoordinatorConfig struct {
Discord DiscordClient
Config ConfigManager
Store StateStore
Turn TurnClient
UserMapper UserMapper
Searcher PRSearcher
Logger *slog.Logger
Org string
}
CoordinatorConfig holds configuration for creating a coordinator.
type DiscordClient ¶
type DiscordClient interface {
// Text channel operations
PostMessage(ctx context.Context, channelID, text string) (messageID string, err error)
UpdateMessage(ctx context.Context, channelID, messageID, text string) error
// Forum channel operations
PostForumThread(ctx context.Context, forumID, title, content string) (threadID, messageID string, err error)
UpdateForumPost(ctx context.Context, threadID, messageID, newTitle, newContent string) error
ArchiveThread(ctx context.Context, threadID string) error
// Direct message operations
SendDM(ctx context.Context, userID, text string) (channelID, messageID string, err error)
UpdateDM(ctx context.Context, channelID, messageID, newText string) error
// Lookup operations
ResolveChannelID(ctx context.Context, channelName string) string
LookupUserByUsername(ctx context.Context, username string) string
IsBotInChannel(ctx context.Context, channelID string) bool
IsUserInGuild(ctx context.Context, userID string) bool
IsUserActive(ctx context.Context, userID string) bool
IsForumChannel(ctx context.Context, channelID string) bool
// Guild info
GuildID() string
// Search operations (for cross-instance race prevention)
FindForumThread(ctx context.Context, forumID, prURL string) (threadID, messageID string, found bool)
FindChannelMessage(ctx context.Context, channelID, prURL string) (messageID string, found bool)
FindDMForPR(ctx context.Context, userID, prURL string) (channelID, messageID string, found bool)
MessageContent(ctx context.Context, channelID, messageID string) (string, error)
}
DiscordClient defines Discord operations needed by the bot.
type PRInfo ¶
type PRInfo struct {
Title string `json:"title"`
Author string `json:"author"`
State string `json:"state"`
UpdatedAt string `json:"updated_at"`
Commits []string `json:"commits,omitempty"`
Assignees []string `json:"assignees,omitempty"`
Draft bool `json:"draft"`
Merged bool `json:"merged"`
Closed bool `json:"closed"`
}
PRInfo contains pull request metadata.
type PRSearchResult ¶
PRSearchResult contains basic PR info for polling.
type PRSearcher ¶
type PRSearcher interface {
// ListOpenPRs returns open PRs for an org updated within the given hours.
ListOpenPRs(ctx context.Context, org string, updatedWithinHours int) ([]PRSearchResult, error)
// ListClosedPRs returns recently closed/merged PRs for catching terminal states.
ListClosedPRs(ctx context.Context, org string, closedWithinHours int) ([]PRSearchResult, error)
}
PRSearcher queries GitHub for PRs.
type PRURLInfo ¶
PRURLInfo contains parsed PR URL components.
func ParsePRURL ¶
ParsePRURL extracts owner, repo, and number from a GitHub PR URL. Uses proper URL parsing to prevent injection attacks.
type SprinklerClient ¶
type SprinklerClient struct {
// contains filtered or unexported fields
}
SprinklerClient manages the WebSocket connection to sprinkler. This is now a thin wrapper around the library client.
func NewSprinklerClient ¶
func NewSprinklerClient(ctx context.Context, cfg SprinklerConfig) (*SprinklerClient, error)
NewSprinklerClient creates a new sprinkler WebSocket client using the library.
type SprinklerConfig ¶
type SprinklerConfig struct {
Logger *slog.Logger
OnEvent func(SprinklerEvent)
OnConnect func()
OnDisconnect func(error)
ServerURL string
TokenProvider TokenProvider
Organization string
}
SprinklerConfig holds configuration for the sprinkler client.
type SprinklerEvent ¶
type SprinklerEvent struct {
Timestamp time.Time `json:"timestamp"`
Raw map[string]any `json:"-"` // Raw message for additional fields
Type string `json:"type"`
URL string `json:"url"`
DeliveryID string `json:"delivery_id"`
CommitSHA string `json:"commit_sha,omitempty"`
}
SprinklerEvent represents an event from the sprinkler WebSocket.
type StateStore ¶
type StateStore interface {
Thread(ctx context.Context, owner, repo string, number int, channelID string) (state.ThreadInfo, bool)
SaveThread(ctx context.Context, owner, repo string, number int, channelID string, info state.ThreadInfo) error
ClaimThread(ctx context.Context, owner, repo string, number int, channelID string, ttl time.Duration) bool
DMInfo(ctx context.Context, userID, prURL string) (state.DMInfo, bool)
SaveDMInfo(ctx context.Context, userID, prURL string, info state.DMInfo) error
ClaimDM(ctx context.Context, userID, prURL string, ttl time.Duration) bool
ListDMUsers(ctx context.Context, prURL string) []string // Returns all user IDs who received DMs for this PR
WasProcessed(ctx context.Context, eventKey string) bool
MarkProcessed(ctx context.Context, eventKey string, ttl time.Duration) error
QueuePendingDM(ctx context.Context, dm *state.PendingDM) error
PendingDMs(ctx context.Context, before time.Time) ([]*state.PendingDM, error)
RemovePendingDM(ctx context.Context, id string) error
DailyReportInfo(ctx context.Context, userID string) (state.DailyReportInfo, bool)
SaveDailyReportInfo(ctx context.Context, userID string, info state.DailyReportInfo) error
Cleanup(ctx context.Context) error
}
StateStore defines state persistence operations.
type TokenProvider ¶
TokenProvider provides fresh GitHub installation tokens.
type TurnClient ¶
type TurnClient interface {
Check(ctx context.Context, prURL, username string, updatedAt time.Time) (*CheckResponse, error)
}
TurnClient defines PR analysis operations.
type TurnHTTPClient ¶
type TurnHTTPClient struct {
// contains filtered or unexported fields
}
TurnHTTPClient implements TurnClient using HTTP.
func NewTurnClient ¶
func NewTurnClient(baseURL string, tokenProvider TokenProvider) *TurnHTTPClient
NewTurnClient creates a new Turn API client.
func (*TurnHTTPClient) Check ¶
func (c *TurnHTTPClient) Check(ctx context.Context, prURL, username string, updatedAt time.Time) (*CheckResponse, error)
Check calls the Turn API to analyze a PR with retry logic.