bot

package
v0.0.0-...-229e418 Latest Latest
Warning

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

Go to latest
Published: Jan 18, 2026 License: GPL-3.0 Imports: 21 Imported by: 0

Documentation

Overview

Package bot provides the core bot coordinator logic.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FormatPRURL

func FormatPRURL(owner, repo string, number int) string

FormatPRURL creates a GitHub PR URL from components.

Types

type Action

type Action struct {
	Kind   string `json:"kind"`
	Reason string `json:"reason"`
}

Action represents what a user needs to do.

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.

func (*CommitPRCache) RecordPR

func (c *CommitPRCache) RecordPR(owner, repo string, prNumber int, commits []string)

RecordPR records all commits for a PR.

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

type PRSearchResult struct {
	UpdatedAt time.Time
	URL       string
	Owner     string
	Repo      string
	Number    int
}

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

type PRURLInfo struct {
	Owner  string
	Repo   string
	Number int
}

PRURLInfo contains parsed PR URL components.

func ParsePRURL

func ParsePRURL(rawURL string) (PRURLInfo, bool)

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.

func (*SprinklerClient) Start

func (c *SprinklerClient) Start(ctx context.Context) error

Start begins the connection with automatic reconnection.

func (*SprinklerClient) Stop

func (c *SprinklerClient) Stop()

Stop gracefully stops the client.

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

type TokenProvider interface {
	InstallationToken(ctx context.Context) (string, error)
}

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.

type UserMapper

type UserMapper interface {
	DiscordID(ctx context.Context, githubUsername string) string
	Mention(ctx context.Context, githubUsername string) string
}

UserMapper defines user mapping operations.

Jump to

Keyboard shortcuts

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