Documentation
¶
Overview ¶
Package pkg provides the core domain types and logic for the maintainer-watcher-github-pr service: GitHub API integration, pull-request filtering, cursor persistence, and Kafka command publishing.
Index ¶
- Constants
- func BuildCreateCommand(pr PullRequest, details PRDetails, taskIDStr string, stage string, ...) task.CreateCommand
- func DeriveTaskID(owner, repo string, number int, sha string) uuid.UUID
- func DeriveTaskIDForce(owner, repo string, number int, sha, nonce string) uuid.UUID
- func NewMemDB() libkv.DB
- func ParseBotAllowlist(raw string) []string
- func ParseTrustedAuthors(raw string) []string
- func SaveCursor(ctx context.Context, path string, state Cursor) error
- type Cursor
- type GitHubClient
- type Metrics
- type PRDetails
- type PullRequest
- type SearchResult
- type TaskConfig
- type TaskPublisher
- type Watcher
Constants ¶
const DefaultCursorPath = "/data/cursor.json"
DefaultCursorPath is the default path for cursor state persistence.
const DefaultMaxSlugLen = 80
DefaultMaxSlugLen is the default cap for the slugified PR-title segment alone. Bumped from 50 to 80 (2026-05-08) — 50 cut typical PR titles mid-word. Override via MAX_SLUG_LEN.
const DefaultMaxTitleLen = 200
DefaultMaxTitleLen is the default safety cap for the whole title, including segments and separators. Crosses Windows MAX_PATH=260 and ext4 NAME_MAX=255 with margin. Override via MAX_TITLE_LEN.
Variables ¶
This section is empty.
Functions ¶
func BuildCreateCommand ¶
func BuildCreateCommand( pr PullRequest, details PRDetails, taskIDStr string, stage string, maxSlugLen int, maxTitleLen int, taskSuffix string, targetVault string, trustResult trust.Result, ) task.CreateCommand
BuildCreateCommand builds a CreateTaskCommand for a PR given its details and trust result. It is used by both the poll path (via PublishCreate) and the single-PR trigger handler.
func DeriveTaskID ¶
DeriveTaskID returns a deterministic task identifier for a (PR, SHA) pair. Input: "<owner>/<repo>#<number>@<sha>", e.g. "bborbe/maintainer#42@abc123...". The full SHA is used (not truncated) to keep the dedup keyspace collision-free.
func DeriveTaskIDForce ¶
DeriveTaskIDForce returns a salted task identifier for a (PR, SHA) pair plus an extra nonce. Used when an operator explicitly requests a forced re-review (HTTP /trigger?force=true) so the executor can publish a CreateTaskCommand with a TaskIdentifier that the controller has not already seen — bypassing the dedup-skip in the agent controller.
For the same (owner, repo, number, sha) the result is always different from DeriveTaskID(...): the key includes the nonce segment "<nonce>", e.g. "bborbe/maintainer#42@abc123...!1700000000000000000".
The nonce resolution is the caller's responsibility. Callers should derive it from an injected libtime.CurrentDateTimeGetter; the helper itself is a pure function over its inputs.
func NewMemDB ¶
NewMemDB returns a session-scoped, in-process libkv.DB implementation. It exists because libkv itself does not ship a public NewMemDB constructor (the upstream bborbe/kv package exposes only NewDBWithMetrics). The github-pr watcher's command consumer needs an offset store; this in-memory implementation gives it one without requiring a PVC (see spec 066 AC 9 rationale: replay-from-OffsetOldest on restart is safe because the downstream CreateTaskCommand is idempotent via derived task_id).
The implementation is intentionally minimal — it implements only the methods the offset-store / consumer wiring touches: Update, View, Sync, Close, Remove, Stats, StatsDetailed. Iterator / ListBucketNames return empty results because no caller in this package uses them.
func ParseBotAllowlist ¶
ParseBotAllowlist splits a comma-separated allowlist string into a slice of trimmed, non-empty entries.
func ParseTrustedAuthors ¶
ParseTrustedAuthors splits a comma-separated trusted-authors string into a slice of trimmed, non-empty entries. Mirrors ParseBotAllowlist in behavior.
Types ¶
type Cursor ¶
type Cursor struct {
LastUpdatedAt libtime.DateTime `json:"last_updated_at"`
HeadSHAs map[string]string `json:"head_shas"`
}
Cursor holds the watcher's persisted poll state, including the last-seen update time and a map of task-identifier to head SHA for force-push detection.
type GitHubClient ¶
type GitHubClient interface {
// SearchPRs issues a GitHub Search query for open PRs updated since cursor.
// page=1 for the first call; use SearchResult.NextPage for subsequent calls.
// PullRequest.HeadSHA in the result is empty — call GetPRDetails to fetch it.
SearchPRs(
ctx context.Context,
scope string,
since libtime.DateTime,
page int,
) (SearchResult, error)
// GetPRDetails fetches the head SHA, clone URL, and base ref for a single PR.
// The Search API does NOT return any of these, so the poll loop must call
// this for every PR before publishing a task command.
GetPRDetails(ctx context.Context, owner, repo string, number int) (PRDetails, error)
}
GitHubClient abstracts the GitHub API calls.
func NewGitHubClient ¶
func NewGitHubClient(httpClient *http.Client) GitHubClient
NewGitHubClient returns a GitHubClient backed by the real GitHub API. The httpClient must already carry authentication (App auth via lib/githubapp.NewClient).
type Metrics ¶
type Metrics interface {
// IncPollCycle increments the poll cycle counter with the given result label.
// result: "success", "rate_limited", "github_error"
IncPollCycle(result string)
// IncPRPublished increments the PR-published counter with the given command label.
// command: "create", "update_frontmatter", "skipped", "error"
IncPRPublished(command string)
}
Metrics exposes counters for observable watcher behaviour.
func NewMetrics ¶
func NewMetrics() Metrics
NewMetrics returns a Metrics implementation backed by Prometheus counters.
type PRDetails ¶
type PRDetails struct {
// HeadSHA is the commit hash of the PR's head branch. Used for force-push
// detection and as the `ref` the agent checks out for review.
HeadSHA string
// CloneURL is the HTTPS clone URL of the head repo (e.g.
// `https://github.com/owner/repo.git`). Used as the `clone_url` the
// agent's execution phase passes to git clone.
CloneURL string
// BaseRef is the base branch name (e.g. `master`, `main`). Used as
// the `base_ref` the execution phase diffs against.
BaseRef string
// AuthorLogin is the GitHub author login; empty for deleted accounts.
AuthorLogin string
// Title is the PR title.
Title string
// IsDraft indicates whether the PR is a draft.
IsDraft bool
// UpdatedAt is the PR last-updated timestamp; required for AgeFilter.
UpdatedAt libtime.DateTime
}
PRDetails holds the per-PR fields the watcher needs to materialize a task the execution phase can act on. The Search API does not expose any of these; they require a follow-up PullRequests.Get call.
type PullRequest ¶
type PullRequest struct {
GlobalID int64
Number int
Owner string
Repo string
Title string
HTMLURL string
HeadSHA string
AuthorLogin string
IsDraft bool
UpdatedAt libtime.DateTime
}
PullRequest holds the fields the watcher needs from a GitHub PR.
type SearchResult ¶
type SearchResult struct {
PullRequests []PullRequest
HasNextPage bool
NextPage int
RateRemaining int
RateResetAt libtime.DateTime
}
SearchResult is the result of a single paginated search call.
type TaskConfig ¶
type TaskConfig struct {
Stage string
MaxSlugLen int
MaxTitleLen int
TaskSuffix string
// TargetVault routes the CreateTaskCommand to a specific vault controller
// (matched verbatim against the controller's VAULT_NAME). Empty leaves
// TargetVault unset, so the controller's legacy default-vault fallback
// applies — preserving pre-TARGET_VAULT behaviour.
TargetVault string
}
TaskConfig groups the per-task publishing configuration.
type TaskPublisher ¶
type TaskPublisher interface {
PublishCreate(ctx context.Context, pr PullRequest, taskIDStr string, details PRDetails) bool
}
TaskPublisher publishes create-task commands for a given PR + details pair. Returns true on successful publish, false on trust check failure or send failure.
func NewTaskPublisher ¶
func NewTaskPublisher( createSender task.CreateCommandSender, trustDecision trust.Trust, metrics Metrics, cfg TaskConfig, ) TaskPublisher
NewTaskPublisher returns a TaskPublisher that performs trust evaluation then publishes a CreateTaskCommand via the given CreateCommandSender.
type Watcher ¶
Watcher polls GitHub and publishes task commands to Kafka.
func NewWatcher ¶
func NewWatcher( ghClient GitHubClient, publisher TaskPublisher, metrics Metrics, cursorPath string, startTime libtime.DateTime, scope string, taskCreationFilter filter.TaskCreationFilter, ) Watcher
NewWatcher returns a Watcher that polls GitHub and publishes commands.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package command defines the TriggerPRReviewCommand payload and its Kafka sender for the github-pr watcher's request topic.
|
Package command defines the TriggerPRReviewCommand payload and its Kafka sender for the github-pr watcher's request topic. |
|
Package factory wires concrete dependencies for the maintainer-watcher-github-pr binary.
|
Package factory wires concrete dependencies for the maintainer-watcher-github-pr binary. |
|
Package filter implements the TaskCreationFilter chain.
|
Package filter implements the TaskCreationFilter chain. |
|
Package trust provides the boolean-combinator trust-decision framework for the maintainer-watcher-github-pr.
|
Package trust provides the boolean-combinator trust-decision framework for the maintainer-watcher-github-pr. |