forge

package
v0.0.0-...-c98162d Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package forge defines a forge-agnostic interface for repo, PR, status, branch, comment and setup operations. Concrete implementations live in sibling packages (internal/gitea, internal/github).

Index

Constants

View Source
const (
	MQContext           = "gitea-mq"
	MirrorContextPrefix = MQContext + "/"
)

Variables

View Source
var ErrNotFastForward = errors.New("forge: not a fast-forward")

ErrNotFastForward is returned by FastForward when sha is not a descendant of the branch's current tip. Callers treat it as "target moved, rebuild".

Functions

func CancelMergeIntent

func CancelMergeIntent(ctx context.Context, f Forge, owner, name string, number int64, mergeLabel string) error

CancelMergeIntent withdraws whatever signal put the PR into the queue: forge-native automerge and, when configured, the merge label.

func DashboardPRURL

func DashboardPRURL(base string, kind Kind, owner, repo string, n int64) string

DashboardPRURL builds the gitea-mq dashboard link for a PR. It is the target_url of every MQStatus so users land on the queue page from the forge's check UI.

func IsOwnContext

func IsOwnContext(ctx string) bool

IsOwnContext recognises statuses gitea-mq itself produced so callers can drop them before they feed back into the monitor.

Types

type Capabilities

type Capabilities struct {
	// StatusWebhook: forge delivers commit-status/check-run results via
	// webhooks. Without it CI results must be polled, so idle gating is
	// unsafe.
	StatusWebhook bool
}

Capabilities lets callers branch on forge features instead of on Kind.

type Check

type Check struct {
	State       CheckState
	Description string
	TargetURL   string
}

Check is a single context's status as reported by GetCheckStates. Description and TargetURL are passed through so callers can implement status mirroring and stale-mirror cleanup without forge-specific code.

type CheckState

type CheckState = pg.CheckState

CheckState aliases pg.CheckState so callers do not import the store package.

func ParseCheckState

func ParseCheckState(s string) CheckState

ParseCheckState folds a forge status string to a CheckState. Gitea's "warning"/"skipped" are treated as success; GitHub's vocabulary is a subset.

type Forge

type Forge interface {
	Kind() Kind
	Capabilities() Capabilities
	RepoHTMLURL(owner, name string) string
	BranchHTMLURL(owner, name, branch string) string

	ListOpenPRs(ctx context.Context, owner, name string) ([]PR, error)
	GetPR(ctx context.Context, owner, name string, number int64) (*PR, error)

	SetMQStatus(ctx context.Context, owner, name, sha string, st MQStatus) error
	// MirrorCheck posts a status/check with an arbitrary context name on sha,
	// used to surface merge-branch CI results on the PR head.
	MirrorCheck(ctx context.Context, owner, name, sha, checkContext string, c Check) error
	GetRequiredChecks(ctx context.Context, owner, name, branch string) ([]string, error)
	GetCheckStates(ctx context.Context, owner, name, sha string) (map[string]Check, error)

	// CreateMergeBranch creates branch at base's tip and merges headSHA into it.
	// conflict=true (err=nil) indicates the merge could not complete.
	CreateMergeBranch(ctx context.Context, owner, name, base, headSHA, branch string) (sha string, conflict bool, err error)
	DeleteBranch(ctx context.Context, owner, name, branch string) error
	ListBranches(ctx context.Context, owner, name string) ([]string, error)
	// IsUpToDate reports whether headSHA already contains the tip of base
	// (i.e. merging base into head would be a no-op).
	IsUpToDate(ctx context.Context, owner, name, base, headSHA string) (bool, error)

	CancelAutoMerge(ctx context.Context, owner, name string, number int64) error
	// RemoveLabel removes a label from a PR; a missing label is not an error.
	RemoveLabel(ctx context.Context, owner, name string, number int64, label string) error
	// MergePR merges the PR (on GitHub: the whole stack up to and including
	// it, atomically). May complete asynchronously; callers observe the
	// PR's merged state.
	MergePR(ctx context.Context, owner, name string, number int64) error
	Comment(ctx context.Context, owner, name string, number int64, body string) error

	EnsureRepoSetup(ctx context.Context, owner, name string, cfg SetupConfig) error

	// MergeInto merges headSHA into an existing branch and returns the new
	// tip. conflict=true (err=nil) on merge conflict. Used to stack batch
	// members onto the batch branch after CreateMergeBranch seeded it.
	MergeInto(ctx context.Context, owner, name, branch, headSHA string) (sha string, conflict bool, err error)

	// FastForward updates branch to sha without force. Returns
	// ErrNotFastForward when sha is not a descendant of the current tip,
	// *PushDeniedError when branch protection rejects the push.
	FastForward(ctx context.Context, owner, name, branch, sha string) error

	// ClosePR closes an open PR without merging. Idempotent on
	// already-closed/merged.
	ClosePR(ctx context.Context, owner, name string, number int64) error
}

Forge abstracts all operations gitea-mq performs against a hosting forge.

type Kind

type Kind string

Kind identifies the hosting forge of a repository.

const (
	KindGitea  Kind = "gitea"
	KindGithub Kind = "github"
)

func (Kind) Valid

func (k Kind) Valid() bool

Valid reports whether k is a known forge kind.

type MQStatus

type MQStatus struct {
	State       CheckState
	Description string
	TargetURL   string
}

MQStatus is the lifecycle state reported by gitea-mq for a head SHA.

type MergeStacker

type MergeStacker interface {
	StackMerges(ctx context.Context, owner, repo, base string, heads []string, branch string) (tip string, steps []MergeStep, err error)
}

MergeStacker is optionally implemented by a Forge that can build a stack of merge commits in one repository checkout. The batch engine type-asserts for it and falls back to CreateMergeBranch + MergeInto otherwise. A returned error is a whole-operation failure (clone/push); per-head outcomes are in steps. tip is the branch SHA after the last successful merge, or "" when every head conflicted/failed.

type MergeStep

type MergeStep struct {
	Conflict bool
	Err      error // non-conflict failure for this head; the stacker continues
}

MergeStep is the per-head outcome of a StackMerges call.

type MockCall

type MockCall struct {
	Method string
	Args   []any
}

MockCall records one invocation on a MockForge.

type MockForge

type MockForge struct {
	Calls []MockCall

	KindVal         Kind
	CapabilitiesVal Capabilities

	RepoHTMLURLFn       func(owner, name string) string
	BranchHTMLURLFn     func(owner, name, branch string) string
	ListOpenPRsFn       func(ctx context.Context, owner, name string) ([]PR, error)
	GetPRFn             func(ctx context.Context, owner, name string, number int64) (*PR, error)
	SetMQStatusFn       func(ctx context.Context, owner, name, sha string, st MQStatus) error
	MirrorCheckFn       func(ctx context.Context, owner, name, sha, checkContext string, c Check) error
	GetRequiredChecksFn func(ctx context.Context, owner, name, branch string) ([]string, error)
	GetCheckStatesFn    func(ctx context.Context, owner, name, sha string) (map[string]Check, error)
	CreateMergeBranchFn func(ctx context.Context, owner, name, base, headSHA, branch string) (string, bool, error)
	DeleteBranchFn      func(ctx context.Context, owner, name, branch string) error
	ListBranchesFn      func(ctx context.Context, owner, name string) ([]string, error)
	IsUpToDateFn        func(ctx context.Context, owner, name, base, headSHA string) (bool, error)
	CancelAutoMergeFn   func(ctx context.Context, owner, name string, number int64) error
	RemoveLabelFn       func(ctx context.Context, owner, name string, number int64, label string) error
	MergePRFn           func(ctx context.Context, owner, name string, number int64) error
	ResolveStackFn      func(ctx context.Context, owner, name string, number int64) (*Stack, error)
	CommentFn           func(ctx context.Context, owner, name string, number int64, body string) error
	EnsureRepoSetupFn   func(ctx context.Context, owner, name string, cfg SetupConfig) error
	MergeIntoFn         func(ctx context.Context, owner, name, branch, headSHA string) (string, bool, error)
	FastForwardFn       func(ctx context.Context, owner, name, branch, sha string) error
	ClosePRFn           func(ctx context.Context, owner, name string, number int64) error
	// contains filtered or unexported fields
}

MockForge is a test double for Forge. Each method delegates to the matching *Fn field if set, else returns zero value and nil. Safe for concurrent use.

func (*MockForge) BranchHTMLURL

func (m *MockForge) BranchHTMLURL(owner, name, branch string) string

func (*MockForge) CallsTo

func (m *MockForge) CallsTo(method string) []MockCall

CallsTo returns all recorded calls to method, in order.

func (*MockForge) CancelAutoMerge

func (m *MockForge) CancelAutoMerge(ctx context.Context, owner, name string, number int64) error

func (*MockForge) Capabilities

func (m *MockForge) Capabilities() Capabilities

func (*MockForge) ClosePR

func (m *MockForge) ClosePR(ctx context.Context, owner, name string, number int64) error

func (*MockForge) Comment

func (m *MockForge) Comment(ctx context.Context, owner, name string, number int64, body string) error

func (*MockForge) CreateMergeBranch

func (m *MockForge) CreateMergeBranch(ctx context.Context, owner, name, base, headSHA, branch string) (string, bool, error)

func (*MockForge) DeleteBranch

func (m *MockForge) DeleteBranch(ctx context.Context, owner, name, branch string) error

func (*MockForge) EnsureRepoSetup

func (m *MockForge) EnsureRepoSetup(ctx context.Context, owner, name string, cfg SetupConfig) error

func (*MockForge) FastForward

func (m *MockForge) FastForward(ctx context.Context, owner, name, branch, sha string) error

func (*MockForge) GetCheckStates

func (m *MockForge) GetCheckStates(ctx context.Context, owner, name, sha string) (map[string]Check, error)

func (*MockForge) GetPR

func (m *MockForge) GetPR(ctx context.Context, owner, name string, number int64) (*PR, error)

func (*MockForge) GetRequiredChecks

func (m *MockForge) GetRequiredChecks(ctx context.Context, owner, name, branch string) ([]string, error)

func (*MockForge) IsUpToDate

func (m *MockForge) IsUpToDate(ctx context.Context, owner, name, base, headSHA string) (bool, error)

func (*MockForge) Kind

func (m *MockForge) Kind() Kind

func (*MockForge) ListBranches

func (m *MockForge) ListBranches(ctx context.Context, owner, name string) ([]string, error)

func (*MockForge) ListOpenPRs

func (m *MockForge) ListOpenPRs(ctx context.Context, owner, name string) ([]PR, error)

func (*MockForge) MergeInto

func (m *MockForge) MergeInto(ctx context.Context, owner, name, branch, headSHA string) (string, bool, error)

func (*MockForge) MergePR

func (m *MockForge) MergePR(ctx context.Context, owner, name string, number int64) error

func (*MockForge) MirrorCheck

func (m *MockForge) MirrorCheck(ctx context.Context, owner, name, sha, checkContext string, c Check) error

func (*MockForge) RemoveLabel

func (m *MockForge) RemoveLabel(ctx context.Context, owner, name string, number int64, label string) error

func (*MockForge) RepoHTMLURL

func (m *MockForge) RepoHTMLURL(owner, name string) string

func (*MockForge) ResolveStack

func (m *MockForge) ResolveStack(ctx context.Context, owner, name string, number int64) (*Stack, error)

func (*MockForge) SetMQStatus

func (m *MockForge) SetMQStatus(ctx context.Context, owner, name, sha string, st MQStatus) error

type PR

type PR struct {
	Number           int64
	Title            string
	State            string // "open", "closed"
	Merged           bool
	AuthorLogin      string
	HeadBranch       string
	HeadSHA          string
	BaseBranch       string
	HTMLURL          string
	AutoMergeEnabled bool
	Labels           []string
}

PR is a forge-agnostic pull request.

AutoMergeEnabled normalises forge-specific signals (Gitea timeline comments, GitHub auto_merge field) so callers do not handle forge internals.

func (*PR) HasLabel

func (p *PR) HasLabel(name string) bool

HasLabel reports whether the PR carries the given label (case-insensitive, matching forge semantics).

type PushDeniedError

type PushDeniedError struct {
	Branch  string
	Message string
}

PushDeniedError is returned by FastForward when the push is rejected by branch protection / ruleset. Carries the forge's message so the user gets an actionable hint (e.g. which whitelist to add the token user to).

func (*PushDeniedError) Error

func (e *PushDeniedError) Error() string

type RepoRef

type RepoRef struct {
	Forge Kind
	Owner string
	Name  string
}

RepoRef identifies a repository on a specific forge.

func ParseRepoRef

func ParseRepoRef(s string) (RepoRef, bool)

ParseRepoRef parses a "<forge>:<owner>/<name>" string. Returns false on invalid format or unknown forge kind.

func (RepoRef) String

func (r RepoRef) String() string

String returns the canonical "<forge>:<owner>/<name>" form.

type Set

type Set struct {
	// contains filtered or unexported fields
}

Set is a lookup of Forge implementations by Kind. Callers resolve the correct adapter for a RepoRef via For.

func NewSet

func NewSet() *Set

NewSet returns an empty Set.

func (*Set) For

func (s *Set) For(ref RepoRef) (Forge, error)

For returns the adapter for ref, or *UnknownForgeError if unregistered.

func (*Set) Kinds

func (s *Set) Kinds() []Kind

Kinds returns registered forge kinds in unspecified order.

func (*Set) Register

func (s *Set) Register(f Forge)

Register installs f under its Kind, replacing any previous entry.

type SetupConfig

type SetupConfig struct {
	// ExternalURL is the public base URL of the gitea-mq instance. Used by
	// Gitea for webhook URL construction and as the dashboard link target.
	ExternalURL string
	// WebhookSecret is the shared secret for Gitea webhook signatures.
	// Ignored by GitHub adapters (App webhook is configured out-of-band).
	WebhookSecret string
}

SetupConfig holds inputs to EnsureRepoSetup.

type Stack

type Stack struct {
	BaseBranch string
	PRs        []StackPR
}

Stack is an ordered (bottom→top) chain of stacked PRs targeting BaseBranch.

func ResolveStack

func ResolveStack(ctx context.Context, f Forge, owner, name string, number int64) (*Stack, error)

ResolveStack looks up the PR's stack when the forge supports stacks.

func (*Stack) MembersUpTo

func (s *Stack) MembersUpTo(number int64) ([]StackPR, bool)

MembersUpTo returns the members up to and including number, and whether number is part of the stack.

type StackPR

type StackPR struct {
	Number  int64
	HeadSHA string
	Merged  bool
}

type StackResolver

type StackResolver interface {
	ResolveStack(ctx context.Context, owner, name string, number int64) (*Stack, error)
}

StackResolver is optionally implemented by forges with native stacked-PR support (GitHub). ResolveStack returns nil (no error) when the PR is not part of a stack or the feature is unavailable.

type UnknownForgeError

type UnknownForgeError struct {
	Kind Kind
}

UnknownForgeError is returned by Set.For when no adapter is registered for a ref's forge kind.

func (*UnknownForgeError) Error

func (e *UnknownForgeError) Error() string

Jump to

Keyboard shortcuts

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