Documentation
¶
Index ¶
- Constants
- Variables
- func DeriveOverallCIStatus(runs []*gh.CheckRun, combined *gh.CombinedStatus) string
- func DeriveReviewDecision(reviews []*gh.PullRequestReview) string
- func FilterWorkflowRunsAwaitingApproval(runs []*gh.WorkflowRun, pr PRSource) []*gh.WorkflowRun
- func IsNotModified(err error) bool
- func IsSyncBudgetContext(ctx context.Context) bool
- func NewProviderRegistry(clients map[string]Client, providers ...platform.Provider) (*platform.Registry, error)
- func NormalizeCIChecks(runs []*gh.CheckRun, combined *gh.CombinedStatus) string
- func NormalizeCheckRuns(runs []*gh.CheckRun) string
- func NormalizeCommentEvent(mrID int64, c *gh.IssueComment) db.MREvent
- func NormalizeCommitEvent(mrID int64, c *gh.RepositoryCommit) db.MREvent
- func NormalizeForcePushEvent(mrID int64, fp ForcePushEvent) db.MREvent
- func NormalizeIssue(repoID int64, ghIssue *gh.Issue) (*db.Issue, error)
- func NormalizeIssueCommentEvent(issueID int64, c *gh.IssueComment) db.IssueEvent
- func NormalizePR(repoID int64, ghPR *gh.PullRequest) (*db.MergeRequest, error)
- func NormalizeReviewEvent(mrID int64, r *gh.PullRequestReview) db.MREvent
- func NormalizeTimelineEvent(mrID int64, event PullRequestTimelineEvent) *db.MREvent
- func ParseHeadRepoFullName(cloneURL string) string
- func RateBucketKey(platformName, platformHost string) string
- func ResolveConfiguredRepo(ctx context.Context, clients map[string]Client, repo config.Repo) (ConfiguredRepoStatus, []RepoRef, error)
- func ResolveConfiguredRepoWithRegistry(ctx context.Context, registry *platform.Registry, repo config.Repo) (ConfiguredRepoStatus, []RepoRef, error)
- func WithSyncBudget(ctx context.Context) context.Context
- type BulkIssue
- type BulkPR
- type Client
- type ConfiguredRepoStatus
- type DiffSyncError
- type DiffSyncErrorCode
- type EditPullRequestOpts
- type ForcePushEvent
- type GraphQLFetcher
- func (g *GraphQLFetcher) FetchRepoIssues(ctx context.Context, owner, name string) (*RepoBulkResult, error)
- func (g *GraphQLFetcher) FetchRepoPRs(ctx context.Context, owner, name string) (*RepoBulkResult, error)
- func (f *GraphQLFetcher) RateTracker() *RateTracker
- func (g *GraphQLFetcher) ShouldBackoff() (bool, time.Duration)
- type PRSource
- type PullRequestTimelineEvent
- type QueueItem
- type QueueItemType
- type Rate
- type RateTracker
- type RepoBulkResult
- type RepoRef
- type RepoSyncResult
- type ResolveConfiguredReposResult
- type SyncBudget
- type SyncStatus
- type Syncer
- func (s *Syncer) Budgets() map[string]*SyncBudget
- func (s *Syncer) ClientForHost(host string) (Client, error)
- func (s *Syncer) ClientForRepo(owner, name string) (Client, error)
- func (s *Syncer) CommentMutator(kind platform.Kind, host string) (platform.CommentMutator, error)
- func (s *Syncer) GQLRateTrackers() map[string]*RateTracker
- func (s *Syncer) HasDiffSync() bool
- func (s *Syncer) HostForRepo(owner, name string) string
- func (s *Syncer) IsTrackedRepo(owner, name string) bool
- func (s *Syncer) IsTrackedRepoOnHost(owner, name, host string) bool
- func (s *Syncer) IssueMutator(kind platform.Kind, host string) (platform.IssueMutator, error)
- func (s *Syncer) MergeMutator(kind platform.Kind, host string) (platform.MergeMutator, error)
- func (s *Syncer) MergeRequestContentMutator(kind platform.Kind, host string) (platform.MergeRequestContentMutator, error)
- func (s *Syncer) ProviderCapabilities(kind platform.Kind, host string) (platform.Capabilities, error)
- func (s *Syncer) RateTrackers() map[string]*RateTracker
- func (s *Syncer) ReadyForReviewMutator(kind platform.Kind, host string) (platform.ReadyForReviewMutator, error)
- func (s *Syncer) RepositoryReader(kind platform.Kind, host string) (platform.RepositoryReader, error)
- func (s *Syncer) ResolveConfiguredRepo(ctx context.Context, repo config.Repo) (ConfiguredRepoStatus, []RepoRef, error)
- func (s *Syncer) ReviewMutator(kind platform.Kind, host string) (platform.ReviewMutator, error)
- func (s *Syncer) RunOnce(ctx context.Context)
- func (s *Syncer) SetFetchers(fetchers map[string]*GraphQLFetcher)
- func (s *Syncer) SetOnMRSynced(fn func(owner, name string, mr *db.MergeRequest))
- func (s *Syncer) SetOnStatusChange(fn func(status *SyncStatus))
- func (s *Syncer) SetOnSyncCompleted(fn func(results []RepoSyncResult))
- func (s *Syncer) SetParallelism(n int)
- func (s *Syncer) SetRepos(repos []RepoRef)
- func (s *Syncer) SetWatchInterval(d time.Duration)
- func (s *Syncer) SetWatchedMRs(mrs []WatchedMR)
- func (s *Syncer) Start(ctx context.Context)
- func (s *Syncer) StateMutator(kind platform.Kind, host string) (platform.StateMutator, error)
- func (s *Syncer) Status() *SyncStatus
- func (s *Syncer) Stop()
- func (s *Syncer) SyncIssue(ctx context.Context, owner, name string, number int) error
- func (s *Syncer) SyncIssueOnHost(ctx context.Context, host, owner, name string, number int) error
- func (s *Syncer) SyncIssueOnProvider(ctx context.Context, kind platform.Kind, host, owner, name string, number int) error
- func (s *Syncer) SyncItemByNumber(ctx context.Context, owner, name string, number int) (string, error)
- func (s *Syncer) SyncMR(ctx context.Context, owner, name string, number int) error
- func (s *Syncer) SyncMROnProvider(ctx context.Context, kind platform.Kind, host, owner, name string, number int) error
- func (s *Syncer) TrackedRepos() []RepoRef
- func (s *Syncer) TriggerRun(ctx context.Context)
- func (s *Syncer) WorkflowApprovalMutator(kind platform.Kind, host string) (platform.WorkflowApprovalMutator, error)
- type WatchedMR
- type WorkflowApprovalState
Constants ¶
const IssueDetailWorstCase = 2
IssueDetailWorstCase is the maximum API calls an issue detail fetch can make (detail + comments).
const PRDetailWorstCase = 8
PRDetailWorstCase is the maximum API calls a PR detail fetch can make (detail + GetUser + comments + reviews + commits + force-push events + combined status + check runs).
const RateReserveBuffer = ratelimit.RateReserveBuffer
Variables ¶
var ( ErrNilPullRequest = platformgithub.ErrNilPullRequest ErrNilIssue = platformgithub.ErrNilIssue )
var ErrConfiguredRepoArchived = errors.New("configured repo archived")
Functions ¶
func DeriveOverallCIStatus ¶
func DeriveOverallCIStatus( runs []*gh.CheckRun, combined *gh.CombinedStatus, ) string
DeriveOverallCIStatus computes an aggregate CI status from check runs and the legacy combined status API. The combined status API only reports on commit statuses (the older mechanism); repos using only GitHub Actions check runs will have an empty or "pending" combined state even when all checks pass. This function merges both sources to produce the correct overall status.
func DeriveReviewDecision ¶
func DeriveReviewDecision(reviews []*gh.PullRequestReview) string
DeriveReviewDecision computes the aggregate review decision from a list of reviews. It keeps the latest APPROVED or CHANGES_REQUESTED review per user. Returns "changes_requested" if any user has that state, "approved" if at least one approval exists, or "" if no actionable reviews are present.
func FilterWorkflowRunsAwaitingApproval ¶
func FilterWorkflowRunsAwaitingApproval( runs []*gh.WorkflowRun, pr PRSource, ) []*gh.WorkflowRun
FilterWorkflowRunsAwaitingApproval narrows action-required workflow runs to those that target the given PR.
Matching rules:
- Run must be at PRSource.HeadSHA.
- If the run's pull_requests array is populated (same-repo PRs), it must contain PRSource.Number.
- If pull_requests is empty (fork-triggered runs), the run's head repository full name and head branch must match PRSource. Two distinct fork PRs can share a head SHA, so head SHA alone is unsafe in the approval path. If HeadRepoFullName or HeadRef is empty we fail closed.
func IsNotModified ¶
IsNotModified returns true if the error represents a 304 Not Modified response from the GitHub API.
func IsSyncBudgetContext ¶
func NewProviderRegistry ¶
func NormalizeCIChecks ¶
func NormalizeCIChecks( runs []*gh.CheckRun, combined *gh.CombinedStatus, ) string
NormalizeCIChecks merges check runs and commit statuses into a single JSON string of CICheck objects. Commit statuses (used by GitHub Apps like roborev) use the older status API and need to be mapped into the same shape as check runs.
func NormalizeCheckRuns ¶
NormalizeCheckRuns converts GitHub check runs to a JSON string of CICheck objects.
func NormalizeCommentEvent ¶
func NormalizeCommentEvent(mrID int64, c *gh.IssueComment) db.MREvent
NormalizeCommentEvent converts a GitHub IssueComment to a db.MREvent.
func NormalizeCommitEvent ¶
func NormalizeCommitEvent(mrID int64, c *gh.RepositoryCommit) db.MREvent
NormalizeCommitEvent converts a GitHub RepositoryCommit to a db.MREvent. Author is taken from the GitHub user login if available, falling back to the git commit author name.
func NormalizeForcePushEvent ¶
func NormalizeForcePushEvent(mrID int64, fp ForcePushEvent) db.MREvent
func NormalizeIssue ¶
NormalizeIssue converts a GitHub Issue to a db.Issue.
func NormalizeIssueCommentEvent ¶
func NormalizeIssueCommentEvent(issueID int64, c *gh.IssueComment) db.IssueEvent
NormalizeIssueCommentEvent converts a GitHub IssueComment to a db.IssueEvent.
func NormalizePR ¶
func NormalizePR(repoID int64, ghPR *gh.PullRequest) (*db.MergeRequest, error)
NormalizePR converts a GitHub PullRequest to a db.MergeRequest. If the PR is merged, State is set to "merged". LastActivityAt is initialized to UpdatedAt.
func NormalizeReviewEvent ¶
func NormalizeReviewEvent(mrID int64, r *gh.PullRequestReview) db.MREvent
NormalizeReviewEvent converts a GitHub PullRequestReview to a db.MREvent.
func NormalizeTimelineEvent ¶
func NormalizeTimelineEvent(mrID int64, event PullRequestTimelineEvent) *db.MREvent
func ParseHeadRepoFullName ¶
ParseHeadRepoFullName extracts "owner/repo" from a GitHub clone URL. Accepts both HTTPS (https://host/owner/repo[.git]) and SSH (git@host:owner/repo[.git]) forms. Returns empty string if the URL does not match a recognized form.
func RateBucketKey ¶
func ResolveConfiguredRepo ¶
Types ¶
type BulkIssue ¶
type BulkIssue struct {
Issue *gh.Issue
Comments []*gh.IssueComment
CommentsComplete bool
}
BulkIssue holds an issue and its nested comments from a single GraphQL query. CommentsComplete indicates whether the comments connection was fully paginated.
type BulkPR ¶
type BulkPR struct {
PR *gh.PullRequest
Comments []*gh.IssueComment
Reviews []*gh.PullRequestReview
Commits []*gh.RepositoryCommit
TimelineEvents []PullRequestTimelineEvent
CheckRuns []*gh.CheckRun
Statuses []*gh.RepoStatus
CommentsComplete bool
ReviewsComplete bool
CommitsComplete bool
TimelineComplete bool
CIComplete bool
}
BulkPR holds a PR and its nested data from a single GraphQL query. The *Complete flags indicate whether each nested connection was fully paginated. When false, the data is partial and the detail drain should fill in via REST.
type Client ¶
type Client interface {
ListOpenPullRequests(ctx context.Context, owner, repo string) ([]*gh.PullRequest, error)
GetPullRequest(ctx context.Context, owner, repo string, number int) (*gh.PullRequest, error)
GetUser(ctx context.Context, login string) (*gh.User, error)
ListRepositoriesByOwner(ctx context.Context, owner string) ([]*gh.Repository, error)
ListReleases(ctx context.Context, owner, repo string, perPage int) ([]*gh.RepositoryRelease, error)
ListTags(ctx context.Context, owner, repo string, perPage int) ([]*gh.RepositoryTag, error)
ListOpenIssues(ctx context.Context, owner, repo string) ([]*gh.Issue, error)
GetIssue(ctx context.Context, owner, repo string, number int) (*gh.Issue, error)
CreateIssue(ctx context.Context, owner, repo, title, body string) (*gh.Issue, error)
ListIssueComments(ctx context.Context, owner, repo string, number int) ([]*gh.IssueComment, error)
ListIssueCommentsIfChanged(ctx context.Context, owner, repo string, number int) ([]*gh.IssueComment, error)
ListReviews(ctx context.Context, owner, repo string, number int) ([]*gh.PullRequestReview, error)
ListCommits(ctx context.Context, owner, repo string, number int) ([]*gh.RepositoryCommit, error)
ListPullRequestTimelineEvents(ctx context.Context, owner, repo string, number int) ([]PullRequestTimelineEvent, error)
ListForcePushEvents(ctx context.Context, owner, repo string, number int) ([]ForcePushEvent, error)
GetCombinedStatus(ctx context.Context, owner, repo, ref string) (*gh.CombinedStatus, error)
ListCheckRunsForRef(ctx context.Context, owner, repo, ref string) ([]*gh.CheckRun, error)
ListWorkflowRunsForHeadSHA(ctx context.Context, owner, repo, headSHA string) ([]*gh.WorkflowRun, error)
ApproveWorkflowRun(ctx context.Context, owner, repo string, runID int64) error
CreateIssueComment(ctx context.Context, owner, repo string, number int, body string) (*gh.IssueComment, error)
EditIssueComment(ctx context.Context, owner, repo string, commentID int64, body string) (*gh.IssueComment, error)
GetRepository(ctx context.Context, owner, repo string) (*gh.Repository, error)
CreateReview(ctx context.Context, owner, repo string, number int, event string, body string) (*gh.PullRequestReview, error)
MarkPullRequestReadyForReview(ctx context.Context, owner, repo string, number int) (*gh.PullRequest, error)
MergePullRequest(ctx context.Context, owner, repo string, number int, commitTitle, commitMessage, method string) (*gh.PullRequestMergeResult, error)
EditPullRequest(ctx context.Context, owner, repo string, number int, opts EditPullRequestOpts) (*gh.PullRequest, error)
EditIssue(ctx context.Context, owner, repo string, number int, state string) (*gh.Issue, error)
ListPullRequestsPage(ctx context.Context, owner, repo, state string, page int) ([]*gh.PullRequest, bool, error)
ListIssuesPage(ctx context.Context, owner, repo, state string, page int) ([]*gh.Issue, bool, error)
// InvalidateListETagsForRepo drops cached conditional-GET
// validators for the given repo's list endpoints so the next
// list call issues an unconditional fetch. The endpoints
// parameter selects which caches to clear ("pulls", "issues",
// "comments"); passing no endpoints clears every supported
// repo-scoped list path. Used to recover from a partial-failure
// sync.
InvalidateListETagsForRepo(owner, repo string, endpoints ...string)
}
Client is the interface for interacting with the GitHub API.
func NewClient ¶
func NewClient( token string, platformHost string, rateTracker *RateTracker, budget *SyncBudget, ) (Client, error)
NewClient creates a GitHub Client authenticated with the given token. platformHost selects the API endpoint: "" or "github.com" uses the public API; any other value creates an Enterprise client. rateTracker and budget may be nil.
type ConfiguredRepoStatus ¶
type DiffSyncError ¶
type DiffSyncError struct {
Code DiffSyncErrorCode
Err error
}
DiffSyncError reports a non-fatal failure to compute or update the diff SHAs for a PR. SyncMR returns this when only the diff portion of the sync failed: the PR row, timeline, and CI status were updated successfully, so callers should still treat the PR data as fresh, but the diff view will be stale or missing until the underlying problem is fixed.
Code categorizes the failure for client-facing messaging via UserMessage. Err preserves the underlying detail for server-side logging only — never expose Err.Error() to API clients, since it can contain clone paths, refs, SHAs, and git stderr.
func (*DiffSyncError) Error ¶
func (e *DiffSyncError) Error() string
func (*DiffSyncError) Unwrap ¶
func (e *DiffSyncError) Unwrap() error
func (*DiffSyncError) UserMessage ¶
func (e *DiffSyncError) UserMessage() string
UserMessage returns a sanitized message safe to surface to API clients. It never includes clone paths, refs, SHAs, or other internal details from the underlying error.
type DiffSyncErrorCode ¶
type DiffSyncErrorCode string
DiffSyncErrorCode categorizes the reason a diff sync failed. The frontend uses this category to render a user-facing message that does not leak local clone paths, refs, SHAs, or git stderr.
const ( // created or updated (network failure, disk full, permission denied). DiffSyncCodeCloneUnavailable DiffSyncErrorCode = "clone_unavailable" // DiffSyncCodeCommitUnreachable means a commit needed to compute the diff // (PR head, merge commit, or its first parent) is not present in the local // clone and could not be fetched. DiffSyncCodeCommitUnreachable DiffSyncErrorCode = "commit_unreachable" // DiffSyncCodeMergeBaseFailed means git merge-base could not compute the // fork point between the PR head and the base. DiffSyncCodeMergeBaseFailed DiffSyncErrorCode = "merge_base_failed" // DiffSyncCodeInternal covers database failures and other unexpected // internal errors during diff computation. DiffSyncCodeInternal DiffSyncErrorCode = "internal" )
type EditPullRequestOpts ¶
EditPullRequestOpts holds optional fields for editing a pull request. Nil pointer fields are omitted from the GitHub API call.
type ForcePushEvent ¶
type GraphQLFetcher ¶
type GraphQLFetcher struct {
// contains filtered or unexported fields
}
GraphQLFetcher fetches PR data via GitHub's GraphQL API (v4).
func NewGraphQLFetcher ¶
func NewGraphQLFetcher( token string, platformHost string, rateTracker *RateTracker, budget *SyncBudget, ) *GraphQLFetcher
NewGraphQLFetcher creates a fetcher for the given host. budget may be nil.
func NewGraphQLFetcherWithClient ¶
func NewGraphQLFetcherWithClient( client *githubv4.Client, rateTracker *RateTracker, ) *GraphQLFetcher
NewGraphQLFetcherWithClient wraps a pre-built githubv4.Client as a GraphQLFetcher. Used by tests that need to point the fetcher at a mock HTTP backend.
func (*GraphQLFetcher) FetchRepoIssues ¶
func (g *GraphQLFetcher) FetchRepoIssues( ctx context.Context, owner, name string, ) (*RepoBulkResult, error)
func (*GraphQLFetcher) FetchRepoPRs ¶
func (g *GraphQLFetcher) FetchRepoPRs( ctx context.Context, owner, name string, ) (*RepoBulkResult, error)
func (*GraphQLFetcher) RateTracker ¶
func (f *GraphQLFetcher) RateTracker() *RateTracker
RateTracker returns the GraphQL rate tracker, or nil if none (or if called on a nil receiver).
func (*GraphQLFetcher) ShouldBackoff ¶
func (g *GraphQLFetcher) ShouldBackoff() (bool, time.Duration)
type PRSource ¶
PRSource identifies a pull request's head for matching workflow runs. HeadSHA is required. HeadRepoFullName ("owner/repo") and HeadRef (branch name) are required to disambiguate fork-triggered runs whose pull_requests array is empty; without them the filter fails closed.
type PullRequestTimelineEvent ¶
type PullRequestTimelineEvent struct {
NodeID string
EventType string
Actor string
CreatedAt time.Time
BeforeSHA string
AfterSHA string
Ref string
PreviousTitle string
CurrentTitle string
PreviousRefName string
CurrentRefName string
SourceType string
SourceOwner string
SourceRepo string
SourceNumber int
SourceTitle string
SourceURL string
IsCrossRepository bool
WillCloseTarget bool
}
type QueueItem ¶
type QueueItem struct {
Type QueueItemType
Platform platform.Kind
RepoOwner string
RepoName string
Number int
PlatformHost string
Score float64
// Scoring inputs
UpdatedAt time.Time
DetailFetchedAt *time.Time
CIHadPending bool
Starred bool
Watched bool
IsOpen bool
}
QueueItem holds scoring inputs and result for a single item that may need a detail fetch.
func BuildQueue ¶
BuildQueue filters items by staleness, scores eligible ones, and returns them sorted by score descending.
func (*QueueItem) WorstCaseCost ¶
WorstCaseCost returns the maximum API calls this item's detail fetch could require.
type QueueItemType ¶
type QueueItemType int
QueueItemType distinguishes PRs from issues for cost estimation.
const ( QueueItemPR QueueItemType = iota QueueItemIssue )
type RateTracker ¶
type RateTracker = ratelimit.RateTracker
func NewPlatformRateTracker ¶
func NewRateTracker ¶
func NewRateTracker( database *db.DB, platformHost string, apiType string, ) *RateTracker
type RepoBulkResult ¶
RepoBulkResult holds all open PRs and issues fetched via GraphQL for a repo.
type RepoRef ¶
type RepoRef struct {
Platform platform.Kind
Owner string
Name string
PlatformHost string
RepoPath string
PlatformRepoID int64
PlatformExternalID string
WebURL string
CloneURL string
DefaultBranch string
}
RepoRef identifies a repository on a configured provider.
type RepoSyncResult ¶
type RepoSyncResult struct {
Platform platform.Kind
Owner string
Name string
PlatformHost string
Error string // empty on success
}
RepoSyncResult holds the outcome of syncing a single repo.
type ResolveConfiguredReposResult ¶
type ResolveConfiguredReposResult struct {
Configured []ConfiguredRepoStatus
Expanded []RepoRef
Warnings []error
}
func ResolveConfiguredRepos ¶
type SyncBudget ¶
type SyncBudget struct {
// contains filtered or unexported fields
}
SyncBudget tracks hourly API call spend for background detail fetches on a single host.
func NewSyncBudget ¶
func NewSyncBudget(limit int) *SyncBudget
func (*SyncBudget) CanSpend ¶
func (b *SyncBudget) CanSpend(n int) bool
func (*SyncBudget) Limit ¶
func (b *SyncBudget) Limit() int
func (*SyncBudget) Refund ¶
func (b *SyncBudget) Refund(n int)
Refund returns n calls back to the budget.
func (*SyncBudget) Remaining ¶
func (b *SyncBudget) Remaining() int
func (*SyncBudget) Reset ¶
func (b *SyncBudget) Reset()
func (*SyncBudget) Spend ¶
func (b *SyncBudget) Spend(n int)
func (*SyncBudget) Spent ¶
func (b *SyncBudget) Spent() int
func (*SyncBudget) TrySpend ¶
func (b *SyncBudget) TrySpend(n int) bool
TrySpend atomically checks and increments the budget. Returns true if the spend was successful.
type SyncStatus ¶
type SyncStatus struct {
Running bool `json:"running"`
CurrentRepo string `json:"current_repo,omitempty"`
Progress string `json:"progress,omitempty"`
LastRunAt time.Time `json:"last_run_at,omitzero"`
LastError string `json:"last_error,omitempty"`
}
SyncStatus holds the current state of the sync engine.
type Syncer ¶
type Syncer struct {
// contains filtered or unexported fields
}
Syncer periodically pulls PR data from GitHub into SQLite.
func NewSyncer ¶
func NewSyncer( clients map[string]Client, database *db.DB, clones *gitclone.Manager, repos []RepoRef, interval time.Duration, rateTrackers map[string]*RateTracker, budgets map[string]*SyncBudget, ) *Syncer
NewSyncer creates a Syncer that polls the given repos on the given interval. clients maps host -> Client; rateTrackers maps host -> RateTracker. Both may contain nil values. clones may be nil. budgets maps host -> SyncBudget; nil or empty disables detail drain and backfill. Budgets are created by the caller (typically main.go) and wired into each Client's HTTP transport at construction time so every sync-context RoundTrip is automatically counted.
func NewSyncerWithRegistry ¶
func (*Syncer) Budgets ¶
func (s *Syncer) Budgets() map[string]*SyncBudget
Budgets returns the per-host sync budgets map.
func (*Syncer) ClientForHost ¶
ClientForHost returns the Client for a specific host, or an error if no client is configured for that host.
func (*Syncer) ClientForRepo ¶
ClientForRepo returns the Client for a tracked repo by owner/name, or an error if the repo is not tracked.
func (*Syncer) CommentMutator ¶
func (*Syncer) GQLRateTrackers ¶
func (s *Syncer) GQLRateTrackers() map[string]*RateTracker
GQLRateTrackers returns per-provider/host GraphQL rate trackers extracted from the registered GraphQL fetchers. Hosts with nil fetchers or trackers are skipped.
func (*Syncer) HasDiffSync ¶
HasDiffSync reports whether the syncer has a clone manager configured and is therefore expected to populate diff SHAs for tracked PRs. The HTTP layer uses this to decide whether a missing diff is a sync issue worth warning about, or simply a deployment that opted out of diffs.
func (*Syncer) HostForRepo ¶
HostForRepo returns the platform host for a tracked repo. Thread-safe.
func (*Syncer) IsTrackedRepo ¶
IsTrackedRepo checks whether the given repo is in the configured list.
func (*Syncer) IsTrackedRepoOnHost ¶
IsTrackedRepoOnHost checks whether the given repo on a specific host is in the configured list.
func (*Syncer) IssueMutator ¶
func (*Syncer) MergeMutator ¶
func (*Syncer) MergeRequestContentMutator ¶
func (*Syncer) ProviderCapabilities ¶
func (*Syncer) RateTrackers ¶
func (s *Syncer) RateTrackers() map[string]*RateTracker
RateTrackers returns the per-host rate trackers map.
func (*Syncer) ReadyForReviewMutator ¶
func (*Syncer) RepositoryReader ¶
func (*Syncer) ResolveConfiguredRepo ¶
func (*Syncer) ReviewMutator ¶
func (*Syncer) RunOnce ¶
RunOnce performs a single sync pass across all configured repos. If a sync is already in progress it returns immediately (single-flight).
Repos are synced in parallel using a bounded worker pool sized by SetParallelism (default defaultParallelism). The bound keeps the per-host GitHub rate limit and abuse-detection thresholds happy while still capturing most of the wall-clock win on network I/O.
func (*Syncer) SetFetchers ¶
func (s *Syncer) SetFetchers(fetchers map[string]*GraphQLFetcher)
SetFetchers registers GitHub GraphQL fetchers keyed by platform host.
func (*Syncer) SetOnMRSynced ¶
func (s *Syncer) SetOnMRSynced( fn func(owner, name string, mr *db.MergeRequest), )
SetOnMRSynced registers a callback invoked after each MR is upserted during a sync pass.
Concurrency: RunOnce processes repos in parallel (see SetParallelism), so the callback may be invoked from up to `parallelism` goroutines concurrently. Implementations must be safe for concurrent use. The callback also runs on the goroutine that is mid-sync for a repo, so it must not block indefinitely or it will stall sync progress.
Call SetOnMRSynced before Start/RunOnce. Mutating the hook while a sync is in flight is not safe.
func (*Syncer) SetOnStatusChange ¶
func (s *Syncer) SetOnStatusChange(fn func(status *SyncStatus))
SetOnStatusChange registers a callback invoked whenever the sync status transitions (start, per-repo progress, rate-limit wait, completion). Used by the server to broadcast live sync state over SSE.
func (*Syncer) SetOnSyncCompleted ¶
func (s *Syncer) SetOnSyncCompleted( fn func(results []RepoSyncResult), )
SetOnSyncCompleted registers a callback invoked at the end of each RunOnce pass with per-repo sync results.
Concurrency: this hook fires once per RunOnce pass on the goroutine that drives RunOnce, so it is not invoked concurrently with itself. Call SetOnSyncCompleted before Start/RunOnce; mutating the hook while a sync is in flight is not safe.
func (*Syncer) SetParallelism ¶
SetParallelism sets the maximum number of repos synced concurrently in RunOnce. Values <= 0 are clamped to 1 (sequential).
func (*Syncer) SetWatchInterval ¶
SetWatchInterval sets the fast-sync interval for watched MRs. Must be called before Start.
func (*Syncer) SetWatchedMRs ¶
SetWatchedMRs replaces the fast-sync watch list. Each watched MR is synced on the watch interval via SyncMR, independent of the bulk sync cycle.
func (*Syncer) Start ¶
Start runs an immediate sync then launches a background ticker. It returns as soon as the goroutine is started; call Stop to shut it down. A second goroutine runs watched-MR fast-syncs on a shorter interval.
The caller's ctx and the syncer's internal lifetime ctx (canceled by Stop) are both honored: either one unblocks any in-flight work.
func (*Syncer) StateMutator ¶
func (*Syncer) Status ¶
func (s *Syncer) Status() *SyncStatus
Status returns a snapshot of the current sync state.
func (*Syncer) Stop ¶
func (s *Syncer) Stop()
Stop signals the background goroutine to exit. Safe to call multiple times. Cancels the syncer's lifetime context first so blocked RunOnce and TriggerRun goroutines can observe the cancellation and unwind their GitHub calls, then waits for the wait group up to stopGracePeriod. The bounded wait prevents Stop from hanging the process in pathological cases where a client ignores ctx.
func (*Syncer) SyncIssue ¶
SyncIssue fetches fresh data for a single issue from GitHub and updates the DB. Returns an error if the repo is not in the configured repo list.
func (*Syncer) SyncIssueOnHost ¶
func (s *Syncer) SyncIssueOnHost( ctx context.Context, host, owner, name string, number int, ) error
SyncIssueOnHost fetches fresh issue data for a specific tracked host.
func (*Syncer) SyncIssueOnProvider ¶
func (s *Syncer) SyncIssueOnProvider( ctx context.Context, kind platform.Kind, host, owner, name string, number int, ) error
SyncIssueOnProvider fetches fresh issue data for a specific configured provider host.
func (*Syncer) SyncItemByNumber ¶
func (s *Syncer) SyncItemByNumber( ctx context.Context, owner, name string, number int, ) (string, error)
SyncItemByNumber fetches an item by number from GitHub, determines whether it is a PR or issue, syncs it into the DB, and returns the item type ("pr" or "issue"). Returns an error if the repo is not in the configured repo list.
func (*Syncer) SyncMR ¶
SyncMR fetches fresh data for a single MR from GitHub and updates the DB. Unlike the periodic sync, this always does a full fetch (details, timeline, CI). Returns an error if the repo is not in the configured repo list.
func (*Syncer) SyncMROnProvider ¶
func (s *Syncer) SyncMROnProvider( ctx context.Context, kind platform.Kind, host, owner, name string, number int, ) error
SyncMROnProvider fetches fresh data for a single MR from a specific configured provider host.
func (*Syncer) TrackedRepos ¶
TrackedRepos returns a snapshot of the tracked repositories.
func (*Syncer) TriggerRun ¶
TriggerRun kicks off a non-blocking ad-hoc sync on the Syncer's wait group so callers can request an immediate run without blocking the caller. Ad-hoc runs bypass the normal nextSyncAfter cadence gate, but still respect hard rate-limit pauses and the syncer's lifecycle: Stop cancels the merged context so any in-flight GitHub call unblocks, then waits for the goroutine to exit. The caller's ctx is honored too, so per-request deadlines still apply.
func (*Syncer) WorkflowApprovalMutator ¶
type WatchedMR ¶
type WatchedMR struct {
Owner string
Name string
Number int
Platform platform.Kind
PlatformHost string
}
WatchedMR identifies a merge request to sync on a fast interval.
type WorkflowApprovalState ¶
WorkflowApprovalState describes whether workflow approval is needed for a PR.
func WorkflowApprovalStateFromRuns ¶
func WorkflowApprovalStateFromRuns(runs []*gh.WorkflowRun) WorkflowApprovalState
WorkflowApprovalStateFromRuns converts matched workflow runs into state.