control

package
v1.13.3 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2026 License: 0BSD Imports: 38 Imported by: 0

Documentation

Overview

Package control implements the forge control commands executed over SSH. Every command here is reachable from bare OpenSSH: argv in, JSON or plain text on stdout, diagnostics on stderr, exit code out.

Index

Constants

View Source
const BlameSpan = 1000

BlameSpan caps one blame request, and is the page size the web renders. An unbounded blame on a large file is a slow query for every surface.

Variables

View Source
var EventKinds = []string{
	"build.cancelled",
	"build.failure",
	"build.success",
	"issue.assigned",
	"issue.closed",
	"issue.commented",
	"issue.created",
	"issue.edited",
	"issue.labeled",
	"issue.milestoned",
	"issue.open",
	"mr.closed",
	"mr.commented",
	"mr.created",
	"mr.draft",
	"mr.edited",
	"mr.merged",
	"mr.milestoned",
	"mr.retargeted",
	"mr.reviewed",
	"push",
	"release.created",
	"release.deleted",
	"repo.archived",
	"repo.imported",
	"repo.unarchived",
	"status",
}

EventKinds is every event this forge records, and so every value a webhook's `--events` filter may name. It is the published list: the API wiki page renders it, and TestEventKindsAreRecorded asserts the code still emits exactly these, so the documentation cannot drift from the server (#112).

Not here, deliberately: repo.deleted. events.repo_id and webhooks.repo_id both cascade from repos, so recording one would delete it and every webhook that could have received it in the same statement.

Functions

func ActivityWindow added in v1.0.1

func ActivityWindow() string

ActivityWindow is the span a profile reports: the start of the web's 53-week calendar, so every surface shows the same year.

func ByteLimit added in v1.7.0

func ByteLimit(st *store.Store, cfg configLimits, userID int64) int64

ByteLimit is the account's storage cap in bytes, 0 for none.

func DetectLicense added in v1.0.1

func DetectLicense(dir, ref string) string

DetectLicense reports the repo's license name from a conventional file at the ref root, or "". It lives here because profile show and the web's repo listings both report it.

func Dispatch

func Dispatch(c *Ctx, argv []string) int

Dispatch runs argv for an authenticated session. The dispatcher — not the handlers — enforces key scope: control commands require a full-scope key.

func HooksDir

func HooksDir(root string) string

HooksDir is the shared core.hooksPath directory.

func MatchesRepo added in v1.11.0

func MatchesRepo(q, path, desc string, topics []string) bool

MatchesRepo is the one rule for matching a repository against a text query: its path, its description, or any of its topics. The web's /explore filter and /search page call it too, so the three surfaces cannot answer the same query differently.

func OwnedBytes added in v1.7.0

func OwnedBytes(st *store.Store, root string, userID int64) int64

OwnedBytes is the disk taken by the repositories a user owns directly.

func ProcessCommitMessages added in v0.2.0

func ProcessCommitMessages(st *store.Store, dir string, repo store.Repo, actorID int64, old, new string)

ProcessCommitMessages acts on issue references in commits that just landed on the default branch (old..new): closing keywords close the issue, bare #N leaves a reference comment. Each (issue, sha) pair acts at most once, ever. actorID — the pusher or merger — authorizes and signs the resulting comments; failures are logged, never fatal, because this runs after the push or merge already succeeded.

func ProcessMRDescription added in v1.0.1

func ProcessMRDescription(st *store.Store, repo store.Repo, mr store.MR, actorID int64)

ProcessMRDescription acts on closing keywords in a merged merge request's title and body. Commit messages remain the primary record — they are what lands — but the intent is written in the merge request just as often, and a "Closes #N" there used to close nothing.

Acting once is guaranteed by the state check, not by the dedup key: a commit that closed the issue leaves it closed, and this skips it. The key is per merge request rather than the merged sha, because sharing the sha let a bare "#N" in a commit message claim it first and silently suppress the close.

func QueueBranchBuilds added in v1.2.1

func QueueBranchBuilds(
	st *store.Store, root, siteURL string,
	repo store.Repo, userID int64, branch, sha string, now time.Time,
)

QueueBranchBuilds reads .gitbay/ci.yml at sha and creates one pending build per push job, with a pending commit status the runner resolves. A broken config surfaces as a failed "ci/config" status, not silence.

Both paths that move a branch call this: post-receive for a push, and the merge path for a merge, which updates the ref directly and so never reaches a hook.

func QueueMRBuilds added in v1.9.0

func QueueMRBuilds(
	st *store.Store, root, siteURL string,
	repo store.Repo, userID, n int64, sha string,
)

QueueMRBuilds queues the push jobs for a merge request head fetched from another repository, which the target holds at refs/merge-requests/<n>/head, so a fork's merge request has ci/<job> statuses for require-checks to gate on (#98). The head is untrusted: its build runs without the target's secrets. A same-repository head is the branch push's job and is not queued here; a failed one is rebuilt when it lands, not when it is proposed.

func QuotaConfig added in v1.7.0

func QuotaConfig(cfg config.Config) configLimits

QuotaConfig is what sshd passes: the limits section of the config.

func RecordLandedCommits added in v0.3.0

func RecordLandedCommits(st *store.Store, dir string, repo store.Repo, old, new string)

RecordLandedCommits attributes commits that just landed on the default branch to accounts by verified author email, for the activity graph. Dedup by (repo, sha) makes rebases and re-runs harmless; unresolvable authors are simply not activity.

func RegisterAccount added in v0.2.0

func RegisterAccount(cfg config.Config, st *store.Store, pub ssh.PublicKey, username, email, invite string) (string, string, int)

RegisterAccount creates an account for pub under the instance's registration mode. On success it returns the human message and ExitOK; otherwise an error message and the classifying exit code. Shared by the SSH register command and the web signup form.

func RepoDir

func RepoDir(root, owner, name string) string

RepoDir returns the on-disk path for a repository.

func RepoLimit added in v1.7.0

func RepoLimit(st *store.Store, cfg configLimits, userID int64) int64

RepoLimit is the account's repository cap, 0 for none.

func ReviewersWhoCount added in v1.13.3

func ReviewersWhoCount(st *store.Store, repo store.Repo, reviews []store.MRReview) map[string]bool

reviewersWhoCount is the set of reviewers whose verdict decides a merge gate: those with write access to the repository.

Write, rather than a separate reviewer role, because it is the same question the gates already answer — a person who could push this change themselves is the person whose approval means the repository accepts it. Someone named in CODEOWNERS without write is a misconfiguration the owner should fix rather than a case to special-case here: they could not merge what they approved. Exported because the web renders the same distinction: a page that showed an approval the gate ignores would differ from the gate, and the difference would only surface when a merge was refused.

func RunRegister

func RunRegister(cfg config.Config, st *store.Store, pub ssh.PublicKey, argv []string,
	stdout, stderr io.Writer) int

RunRegister handles the one command an UNAUTHENTICATED key may run. It is dispatched outside the normal registry: the caller has already checked that registration is enabled and that argv[0] == "register".

func SearchMarker added in v1.11.0

func SearchMarker(kind string) string

SearchMarker is the sigil a result's number carries, shared with the web so a hit reads the same in both places.

func VerifyCommitCached

func VerifyCommitCached(st *store.Store, repo store.Repo, parsed *sig.Commit, sha string) (sig.Result, error)

VerifyCommitCached verifies one commit with the epoch cache. Shared with the web UI.

Types

type ActivityDay added in v1.12.0

type ActivityDay struct {
	Date  string `json:"date"`
	Count int    `json:"count"`
}

ActivityDay is one day's contribution count. Days with nothing are omitted; a client fills the calendar it wants to draw.

type BuildOut added in v1.12.0

type BuildOut struct {
	Number     int64  `json:"number"`
	Job        string `json:"job"`
	Status     string `json:"status"`
	SHA        string `json:"sha"`
	Ref        string `json:"ref"`
	CreatedAt  string `json:"created_at"`
	FinishedAt string `json:"finished_at,omitempty"`
}

type CheckOut added in v1.10.0

type CheckOut struct {
	Context   string `json:"context"`
	State     string `json:"state"`
	URL       string `json:"url,omitempty"`
	UpdatedAt string `json:"updated_at"`
	Duration  string `json:"duration,omitempty"` // CI checks only, once finished
}

CheckOut is one commit status on a merge request head.

type Command

type Command struct {
	Path []string // e.g. ["keys", "add"]
	// Summary is one line of prose: what the command does, no argument
	// syntax. Usage is the argument syntax, opening with the command path.
	// help renders them separately, so neither may carry the other's job.
	Summary    string
	Usage      string
	ReadsStdin bool
	ReadOnly   bool // safe for read-scoped API tokens
	SSHOnly    bool // refused over the HTTP API (credential minting)
	Run        func(c *Ctx, args []string) int
}

func Commands

func Commands() []Command

Commands returns the registry, for the bare-ssh reachability test.

func Lookup

func Lookup(argv []string) (Command, []string, bool)

Lookup resolves argv to a command by longest path match, returning the command and the remaining arguments.

type CommitOut added in v1.10.0

type CommitOut struct {
	SHA     string `json:"sha"`
	Subject string `json:"subject"`
}

CommitOut is one commit a merge request carries.

type Created added in v1.10.0

type Created struct {
	Number int64 `json:"number"`
}

Created is what issue create, issue comment and mr comment emit.

type Ctx

type Ctx struct {
	User   store.User
	Scope  string // scope of the key that authenticated this session
	Store  *store.Store
	Cfg    config.Config
	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer
	JSON   bool
	// ViaAPI marks requests arriving over the HTTP token API. Some
	// commands (token management) are SSH-only: an API token must never
	// mint further credentials.
	ViaAPI bool
	// ReadOnly is set for read-scoped API tokens.
	ReadOnly bool
	// Source identifies the credential behind this session for the audit
	// log: an SSH key fingerprint, or "api" for token requests.
	Source string
}

type DashboardBuild added in v1.12.0

type DashboardBuild struct {
	Repo       string `json:"repo"`
	Number     int64  `json:"number"`
	Job        string `json:"job"`
	Status     string `json:"status"`
	SHA        string `json:"sha"`
	Ref        string `json:"ref"`
	CreatedAt  string `json:"created_at"`
	FinishedAt string `json:"finished_at,omitempty"`
}

DashboardBuild is a build with its repository resolved, which is what separates it from BuildOut: the dashboard spans repositories.

type DashboardItem added in v1.12.0

type DashboardItem struct {
	Repo      string `json:"repo"`
	Number    int64  `json:"number"`
	Title     string `json:"title"`
	Author    string `json:"author"`
	State     string `json:"state"`
	UpdatedAt string `json:"updated_at"`
}

DashboardItem is one open issue or MR row, with its repo resolved so a client renders the aggregate without further reads.

type DashboardOut added in v1.12.0

type DashboardOut struct {
	Reviews  []DashboardItem  `json:"review_queue"`
	Assigned []DashboardItem  `json:"assigned_issues"`
	MRs      []DashboardItem  `json:"open_mrs"`
	Issues   []DashboardItem  `json:"open_issues"`
	Pinned   []PinnedOut      `json:"pinned"`
	Activity []FeedOut        `json:"recent_activity"`
	Builds   []DashboardBuild `json:"builds"`
	// Unread is the notification inbox badge, so a client showing one
	// does not need a second read to fill it.
	Unread int        `json:"unread"`
	Server *ServerOut `json:"server,omitempty"`
	// Queues is admin-only: every background worker's backlog and
	// failures, the operator's view of what is stuck.
	Queues *store.Queues `json:"queues,omitempty"`
}

DashboardOut is what dashboard emits: the whole account aggregate in one read.

type FeedOut added in v1.12.0

type FeedOut struct {
	ID        int64           `json:"id"`
	Repo      string          `json:"repo"`
	Actor     string          `json:"actor,omitempty"`
	Kind      string          `json:"kind"`
	Data      json.RawMessage `json:"data,omitempty"`
	CreatedAt string          `json:"created_at"`
}

type IssueShow added in v1.10.0

type IssueShow struct {
	Comments []commentOut `json:"comments,omitempty"`
	// contains filtered or unexported fields
}

IssueShow is issue show's payload: the issue and its comments.

type IssueTemplate added in v0.2.0

type IssueTemplate struct {
	Name string `json:"name"`
	Body string `json:"body"`
}

func IssueTemplates added in v0.2.0

func IssueTemplates(dir, ref string) []IssueTemplate

IssueTemplates reads .gitbay/issue-template*.md from ref. Missing directory or unreadable files yield an empty list, never an error.

type JobOut added in v1.12.0

type JobOut struct {
	Name     string `json:"name"`
	Schedule string `json:"schedule,omitempty"`
	Tags     string `json:"tags,omitempty"`
}

type MRCreated added in v1.10.0

type MRCreated struct {
	Number    int64     `json:"number"`
	HeadSHA   string    `json:"head_sha"`
	StackedOn *stackRef `json:"stacked_on,omitempty"`
}

MRCreated is what mr create emits.

type MRShow added in v1.10.0

type MRShow struct {
	Checks            []CheckOut   `json:"checks,omitempty"`
	Combined          string       `json:"checks_combined,omitempty"`
	UnresolvedThreads int          `json:"unresolved_threads,omitempty"`
	Commits           []CommitOut  `json:"commits,omitempty"`
	Comments          []commentOut `json:"comments,omitempty"`
	Reviews           []ReviewOut  `json:"reviews,omitempty"`
	// contains filtered or unexported fields
}

MRShow is mr show's payload.

type PinnedOut added in v1.12.0

type PinnedOut struct {
	Path        string `json:"path"`
	Visibility  string `json:"visibility"`
	Description string `json:"description,omitempty"`
	Archived    bool   `json:"archived,omitempty"`
}

PinnedOut is one pinned repository on the dashboard.

type ProfileMember added in v1.12.0

type ProfileMember struct {
	Name string `json:"name"`
	Role string `json:"role,omitempty"`
}

type ProfileOut added in v1.12.0

type ProfileOut struct {
	Name        string `json:"name"`
	Kind        string `json:"kind"`
	Description string `json:"description,omitempty"`
	Website     string `json:"website,omitempty"`
	// About is long-form markdown, rendered by the web between the
	// header and the activity graph.
	About       string              `json:"about,omitempty"`
	AboutFormat string              `json:"about_format,omitempty"`
	Links       []store.ProfileLink `json:"links,omitempty"`
	// The rest is what a profile page shows: who they work with, what
	// they own that you can see, and how active they have been. The web
	// read these straight out of the store, which kept them off every
	// other surface.
	Orgs     []ProfileMember `json:"orgs,omitempty"`    // for a user
	Members  []ProfileMember `json:"members,omitempty"` // for an org
	Repos    []ProfileRepo   `json:"repos"`
	Activity []ActivityDay   `json:"activity,omitempty"`
	// ActivityTotal counts the same window the days cover.
	ActivityTotal int `json:"activity_total"`
}

type ProfileRepo added in v1.12.0

type ProfileRepo struct {
	Path          string   `json:"path"`
	Visibility    string   `json:"visibility"`
	Description   string   `json:"description,omitempty"`
	DefaultBranch string   `json:"default_branch"`
	Topics        []string `json:"topics,omitempty"`
	License       string   `json:"license,omitempty"`
	Updated       string   `json:"updated,omitempty"`
	Archived      bool     `json:"archived,omitempty"`
}

ProfileRepo is one repository as a profile lists it. The listing metadata — topics, license, last commit — is here because a profile is a listing: a client that renders repositories without it is showing less than the web does, which is why the web kept its own copy.

type ReviewOut added in v1.10.0

type ReviewOut struct {
	Reviewer string `json:"reviewer"`
	Verdict  string `json:"verdict"`
	Stale    bool   `json:"stale"`
	// Counts reports whether this verdict decides the merge gates. A
	// reader may review a public merge request; only someone who can
	// write to the repository decides whether it merges. Without this the
	// page would show an approval the gate ignores, and the difference
	// would be invisible until a merge was refused (#147).
	Counts    bool   `json:"counts"`
	CreatedAt string `json:"created_at"`
}

ReviewOut is one review on a merge request.

type RevisionOut added in v1.13.0

type RevisionOut struct {
	N         int    `json:"n"` // 1 is the first push
	SHA       string `json:"sha"`
	BaseSHA   string `json:"base_sha,omitempty"`
	CreatedAt string `json:"created_at"`
	Current   bool   `json:"current,omitempty"`
}

RevisionOut is one head a merge request has had.

type SearchResult added in v1.11.0

type SearchResult struct {
	Kind      string `json:"kind"` // repo, issue, or mr
	Repo      string `json:"repo"`
	Number    int64  `json:"number,omitempty"`
	Title     string `json:"title"`
	Author    string `json:"author,omitempty"`
	State     string `json:"state,omitempty"`
	UpdatedAt string `json:"updated_at,omitempty"`
}

SearchResult is one match, in the shape all three kinds share.

func Search(st *store.Store, root string, userID int64, q string, kinds []string) ([]SearchResult, error)

Search runs a query for a user, or for an anonymous visitor when userID is 0, in which case only public repositories are reached. kinds names which of repo, issue and mr to look at; empty means all three. It is exported because the web's /search page renders it for readers who have no session to dispatch a command as.

type ServerOut added in v1.12.0

type ServerOut struct {
	Commit string `json:"commit"`
}

ServerOut is admin-only. The exact build a host is running narrows down which known issues apply to it, so it is not everyone's to read; the person who needs it is the operator.

Source Files

  • admin.go
  • adminhost.go
  • audit.go
  • build.go
  • commitfile.go
  • commitrefs.go
  • control.go
  • cursor.go
  • dashboard.go
  • deploykey.go
  • deps.go
  • diffcomment.go
  • events.go
  • explore.go
  • flags.go
  • ghimport.go
  • identity.go
  • import.go
  • issue.go
  • label.go
  • license.go
  • migrate.go
  • milestone.go
  • mirrorcmd.go
  • mr.go
  • notifications.go
  • org.go
  • output.go
  • pagescmd.go
  • profile.go
  • quota.go
  • read.go
  • register.go
  • release.go
  • repo.go
  • search.go
  • sig.go
  • status.go
  • teams.go
  • thread.go
  • token.go
  • web.go
  • webhook.go
  • wiki.go

Jump to

Keyboard shortcuts

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