automatic

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Nov 13, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package automatic is the daemon's scheduler for reviews nobody asked for: it turns new pull request heads and new review requests, seen after automatic generation was enabled, into jobs on the existing queue. It has no model backend and no GitHub client of its own; discovery feeds it snapshots and jobs.Queue.SubmitAutomatic prepares, refuses or queues each job with the same preparation and isolation as a confirmed one.

Index

Constants

View Source
const (
	GateOff               = "automatic_off"
	GateRepositoryOff     = "repository_automatic_off"
	GateRepositoryRemoved = "repository_removed"
	GateUnreadable        = jobs.ReasonSettingsUnreadable
)

Why Gate refuses an automatic job.

View Source
const NoticeUnavailable = "unavailable"

NoticeUnavailable is the notice of a repository whose triggered PR got no job because GitHub or the clone stayed unavailable; the most recent notice wins. A "daily_cap" notice an older baum saved is dropped on load.

View Source
const SetupCatchUp = 3

SetupCatchUp is how many pull requests desktop setup asks CatchUp for.

Variables

This section is empty.

Functions

func SavedHead

func SavedHead(ctx context.Context, clone repos.Clone, number int) (string, error)

SavedHead is the head of the PR's latest saved review in the clone's version store, "" when there is none.

Types

type Groups

type Groups interface {
	List(context.Context) ([]reviewgroups.Group, error)
	Summary(context.Context, string) (reviewgroups.Summary, error)
}

Groups is the review group store as the scheduler reads it.

type Overview

type Overview struct {
	Enabled bool `json:"enabled"`
	// PullRequests is which pull requests get automatic reviews: both,
	// authored, requested or all.
	PullRequests string   `json:"pull_requests"`
	Repositories []Status `json:"repositories"`
}

Overview is GET /api/automatic.

type Queue

type Queue interface {
	SubmitAutomatic(context.Context, jobs.AutomaticRequest) (jobs.Job, error)
	// Interrupted lists automatic jobs a daemon stop or restart cut short
	// that may be retried once.
	Interrupted() []jobs.Job
	// Refused lists automatic jobs cancelled before any model call without
	// using up their head (the PR turned draft, or its clone went away).
	Refused() []jobs.Job
	// CancelDisallowedAutomatic cancels queued automatic jobs the gate
	// (Scheduler.Gate) now refuses.
	CancelDisallowedAutomatic() []jobs.Job
	// QueuedAutomatic lists the automatic jobs waiting to start.
	QueuedAutomatic() []jobs.Job
}

type Registry

type Registry interface {
	Repositories(context.Context) ([]repos.Repository, error)
	Preferences(context.Context) (repos.Preferences, error)
	UpdatePreferences(context.Context, func(repos.Preferences) repos.Preferences) (repos.Preferences, error)
	RepositorySettings(ctx context.Context, repository string) (repos.Settings, bool, error)
}

type Scheduler

type Scheduler struct {
	Registry Registry
	Queue    Queue
	// Path is the application database recording what was already seen, so a
	// restart neither forgets pending work nor treats old heads as new.
	Path string
	// Discover polls one repository's open pull requests; Trigger and
	// CatchUp use it.
	Discover func(context.Context, github.Repository) (discovery.Snapshot, error)
	// Discovered, when set, receives CatchUp's polls in place of Observe: the
	// daemon passes background discovery's, which also brings the stack
	// groups up to date before CatchUp reads them.
	Discovered func(context.Context, discovery.Snapshot)
	// Reviewed returns the head of the PR's latest saved review, "" if none.
	// Nil uses SavedHead.
	Reviewed func(context.Context, repos.Clone, int) (string, error)
	// Groups holds the review groups; the reviews of stack groups follow
	// their members' (see passGroups). Nil generates no group review.
	Groups Groups
	// Hold reports that the daemon is stopping or waiting to restart as a
	// newer version; nothing is submitted meanwhile, and the new daemon's
	// passes submit what is pending.
	Hold func() bool
	// Notify publishes a repository's changed status (a notice) for the app
	// and the desktop app's notifications.
	Notify   func(Status)
	Now      func() time.Time
	Interval time.Duration
	Log      *slog.Logger
	// contains filtered or unexported fields
}

Scheduler decides which pull requests get automatic jobs. Run it once in the daemon; Observe and Trigger may be called from other goroutines.

func (*Scheduler) BeginIdentityChange

func (s *Scheduler) BeginIdentityChange() func(bool)

BeginIdentityChange stops submission before credentials change. The returned function must be called once to release the fence, even on failed sign-in.

func (*Scheduler) CatchUp

func (s *Scheduler) CatchUp(ctx context.Context, n int) error

CatchUp queues automatic reviews of the n most recently updated open pull requests automatic generation covers, across its repositories, though they were open before it was enabled. Desktop setup asks for it once, so the first reviews run while the person takes the tour. Each repository is polled now, and the poll is its baseline when it has none yet; the chosen pull requests become pending with jobs.TriggerSetup and the next pass submits them like any other, skipping a head already reviewed or queued. A pull request in a stack group counts with its group as one and the group's eligible members are caught up together, so the group review can follow theirs (passGroups).

func (*Scheduler) Gate

func (s *Scheduler) Gate(j jobs.Job) jobs.Admission

Gate reads the current settings for an automatic job, for jobs.Queue.SetAutomaticGate: the queue asks it when the job is submitted and again before it starts, so turning generation off (globally or for the repository) stops jobs that are queued but not started. It reads only the registry database, never the scheduler's state or the queue: the queue's mutex is held.

func (*Scheduler) Handler

func (s *Scheduler) Handler() http.Handler

Handler serves GET and PUT /api/automatic and POST /api/automatic/catch-up (CatchUp). Like the registry handler it does not authenticate: mount it only behind the daemon's authenticated, Host/Origin-checked middleware.

func (*Scheduler) Observe

func (s *Scheduler) Observe(ctx context.Context, snapshot discovery.Snapshot)

Observe records a complete discovery snapshot. The first one after a repository is enabled is its baseline; afterwards a new head, or a new review request, on an eligible PR leaves a pending job for the next pass. Background discovery calls it after every successful poll, and Trigger after its own; a snapshot fetched before the newest one observed for its repository is ignored.

func (*Scheduler) Overview

func (s *Scheduler) Overview(ctx context.Context) (Overview, error)

Overview reports the preferences and every registered repository.

func (*Scheduler) Pass

func (s *Scheduler) Pass(ctx context.Context)

Pass submits every pending job that is due. Exposed for tests.

func (*Scheduler) ResetIdentity

func (s *Scheduler) ResetIdentity()

ResetIdentity forgets account-dependent PR baselines while preserving repository preferences and saved reviews.

func (*Scheduler) Run

func (s *Scheduler) Run(ctx context.Context)

Run submits pending jobs until ctx ends: at once, whenever woken, and every Interval (30 s by default) to retry refusals.

func (*Scheduler) Trigger

func (s *Scheduler) Trigger(ctx context.Context, repository string) error

Trigger looks at one repository again now and feeds what it finds through Observe, the only way pull requests become automatic jobs. The daemon calls it when a hook event showed a pull request's head moved (internal/ hookrefresh), with Discover polling before discovery's deadline but within its rate budget.

func (*Scheduler) Wake

func (s *Scheduler) Wake()

Wake runs a pass soon: settings changed or a job finished.

type Status

type Status struct {
	Repository string `json:"repository"`
	// Enabled is effective: the repository's explicit choice, else the
	// global preference.
	Enabled bool `json:"enabled"`
	// Notice is the latest reason a triggered PR got no job:
	// NoticeUnavailable or a jobs.NotAutomaticError reason.
	Notice  string `json:"notice,omitempty"`
	Pending int    `json:"pending"`
}

Status is one repository's automatic generation as the app shows it.

Jump to

Keyboard shortcuts

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