pkg

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2026 License: BSD-2-Clause Imports: 21 Imported by: 0

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

View Source
const DefaultCursorPath = "/data/cursor.json"

DefaultCursorPath is the default path for cursor state persistence.

View Source
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.

View Source
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,
	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

func DeriveTaskID(owner, repo string, number int, sha string) uuid.UUID

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

func DeriveTaskIDForce(owner, repo string, number int, sha, nonce string) uuid.UUID

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

func NewMemDB() libkv.DB

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

func ParseBotAllowlist(raw string) []string

ParseBotAllowlist splits a comma-separated allowlist string into a slice of trimmed, non-empty entries.

func ParseTrustedAuthors

func ParseTrustedAuthors(raw string) []string

ParseTrustedAuthors splits a comma-separated trusted-authors string into a slice of trimmed, non-empty entries. Mirrors ParseBotAllowlist in behavior.

func SaveCursor

func SaveCursor(ctx context.Context, path string, state Cursor) error

SaveCursor persists cursor state to path atomically via a temp file + rename.

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.

func LoadCursor

func LoadCursor(ctx context.Context, path string, startTime libtime.DateTime) (Cursor, error)

LoadCursor reads cursor state from path. Returns cold-start state with startTime if the file is missing or corrupt.

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
}

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

type Watcher interface {
	Poll(ctx context.Context) error
}

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.

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.

Jump to

Keyboard shortcuts

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