Documentation
¶
Overview ¶
Package bot implements the coordination logic between GitHub, Slack, and notifications.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ConfigManager ¶
type ConfigManager interface {
Config(org string) (*config.RepoConfig, bool)
LoadConfig(ctx context.Context, org string) error
ReloadConfig(ctx context.Context, org string) error
Domain(org string) string
WorkspaceName(org string) string
ChannelsForRepo(org, repo string) []string
ReminderDMDelay(org, channelName string) int
When(org, channelName string) string
SetGitHubClient(org string, client any)
SetWorkspaceName(workspaceName string)
}
ConfigManager defines configuration operations.
type Coordinator ¶
type Coordinator struct {
// contains filtered or unexported fields
}
Coordinator coordinates between GitHub, Slack, and notifications for a single org.
func New ¶
func New( ctx context.Context, slackClient SlackClient, githubClient GitHubClient, configManager ConfigManager, notifier *notify.Manager, sprinklerURL string, stateStore StateStore, ) *Coordinator
New creates a new bot coordinator for a single GitHub organization.
func (*Coordinator) PollAndReconcile ¶
func (c *Coordinator) PollAndReconcile(ctx context.Context)
PollAndReconcile checks all open PRs and ensures notifications are sent. This runs every 5 minutes as a safety net to catch anything sprinkler missed.
func (*Coordinator) RunWithSprinklerClient ¶
func (c *Coordinator) RunWithSprinklerClient(ctx context.Context) error
RunWithSprinklerClient runs the bot using the official sprinkler client library.
func (*Coordinator) StartupReconciliation ¶
func (c *Coordinator) StartupReconciliation(ctx context.Context)
StartupReconciliation runs once at startup to catch up on any missed notifications. This ensures that if the service was down, we still notify about PRs that need attention.
type GitHubClient ¶
type GitHubClient interface {
InstallationToken(ctx context.Context) string
Organization() string
Client() any
FindPRsForCommit(ctx context.Context, owner, repo, commitSHA string) ([]int, error)
RefreshToken(ctx context.Context) error
}
GitHubClient defines GitHub operations needed by bot.
type PRSearcher ¶
type PRSearcher interface {
ListOpenPRs(ctx context.Context, org string, updatedSinceHours int) ([]github.PRSnapshot, error)
ListClosedPRs(ctx context.Context, org string, updatedSinceHours int) ([]github.PRSnapshot, error)
}
PRSearcher defines GitHub PR search operations for polling.
type SlackClient ¶
type SlackClient interface {
PostThread(ctx context.Context, channelID, text string, attachments []slack.Attachment) (string, error)
UpdateMessage(ctx context.Context, channelID, timestamp, text string) error
UpdateDMMessage(ctx context.Context, userID, prURL, text string) error
SendDirectMessage(ctx context.Context, userID, text string) (dmChannelID, messageTS string, err error)
SendDirectMessageWithBlocks(ctx context.Context, userID string, blocks []slack.Block) (dmChannelID, messageTS string, err error)
IsUserInChannel(ctx context.Context, channelID, userID string) bool
IsUserActive(ctx context.Context, userID string) bool
UserTimezone(ctx context.Context, userID string) (string, error)
FindDMMessagesInHistory(ctx context.Context, userID, prURL string, since time.Time) ([]slackapi.DMLocation, error)
ChannelHistory(ctx context.Context, channelID string, oldest, latest string, limit int) (*slack.GetConversationHistoryResponse, error)
ResolveChannelID(ctx context.Context, channelName string) string
IsBotInChannel(ctx context.Context, channelID string) bool
BotInfo(ctx context.Context) (*slack.AuthTestResponse, error)
WorkspaceInfo(ctx context.Context) (*slack.TeamInfo, error)
PublishHomeView(ctx context.Context, userID string, blocks []slack.Block) error
API() *slack.Client
}
SlackClient defines Slack operations needed by bot. Small interface - only methods we actually call.
type SprinklerMessage ¶
type SprinklerMessage struct {
Timestamp time.Time `json:"timestamp,omitempty"` // Event timestamp from sprinkler
Type string `json:"type,omitempty"` // Message type (e.g., "ping", "event")
Event string `json:"event,omitempty"` // GitHub event type
Repo string `json:"repo,omitempty"` // Repository name
URL string `json:"url,omitempty"` // GitHub URL for reference
PRNumber int `json:"pr_number,omitempty"` // PR number extracted from URL
}
SprinklerMessage represents a message from sprinkler.
type StateStore ¶
type StateStore interface {
Thread(ctx context.Context, owner, repo string, number int, channelID string) (cache.ThreadInfo, bool)
SaveThread(ctx context.Context, owner, repo string, number int, channelID string, info cache.ThreadInfo) error
LastDM(ctx context.Context, userID, prURL string) (time.Time, bool)
RecordDM(ctx context.Context, userID, prURL string, sentAt time.Time) error
DMMessage(ctx context.Context, userID, prURL string) (state.DMInfo, bool)
SaveDMMessage(ctx context.Context, userID, prURL string, info state.DMInfo) error
ListDMUsers(ctx context.Context, prURL string) []string
LastDigest(ctx context.Context, userID, date string) (time.Time, bool)
RecordDigest(ctx context.Context, userID, date string, sentAt time.Time) 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
WasProcessed(ctx context.Context, eventKey string) bool
MarkProcessed(ctx context.Context, eventKey string, ttl time.Duration) error
LastNotification(ctx context.Context, prURL string) time.Time
RecordNotification(ctx context.Context, prURL string, notifiedAt time.Time) error
LastReportSent(ctx context.Context, userID string) (time.Time, bool)
RecordReportSent(ctx context.Context, userID string, sentAt time.Time) error
Cleanup(ctx context.Context) error
Close() error
}
StateStore interface for persistent state - allows dependency injection for testing.
type UserMapper ¶
type UserMapper interface {
SlackHandle(ctx context.Context, githubUsername, organization, domain string) (string, error)
FormatUserMentions(ctx context.Context, githubUsernames []string, organization, domain string) string
}
UserMapper defines user mapping operations.
type UserTagInfo ¶
type UserTagInfo struct {
UserID string
IsInAnyChannel bool // True if user is member of at least one channel where they were tagged
}
UserTagInfo contains information about a user who was tagged in PR notifications.