forge

package
v0.26.1 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package forge applies what reaches a forge — comments, labels, issues, merge requests — on GitHub, GitLab, or a simulated forge for the tests. Every write is idempotent, so a run interrupted half-way can be resumed.

Index

Constants

View Source
const (
	VerdictStatus = "workline/verdict"
	Accepted      = "workline/accepted"
)

The statuses workline sets on a head on GitHub, by its App's token: the line's verdict, and the yes the merge policy holds (ADR-0042).

View Source
const (
	LinePosted  = "posted"  // posted now, in this review
	LineOpen    = "open"    // one holding its key is open on the merge request: not posted again
	LineOutside = "outside" // its line is not in the diff the forge shows, which takes no comment there
	LineRefused = "refused" // the forge refused it, Why says how
)

What became of a line comment (Placed.State).

View Source
const Eyes = "eyes"

Eyes is the reaction the role puts on a comment it read: 👀, as the forges name it.

View Source
const Missing = "" /* 128-byte string literal not displayed */

Missing says what to do when a write needs a forge and the project has none.

Variables

View Source
var (
	ReviewHere = Marker("review")
	ReviewEnd  = Marker("review-end")
)

ReviewHere and ReviewEnd hold the region where a sticky comment carrying a review says what became of its comments on lines: the engine writes it there once the review is posted (docs/spec/role-outcome.md, `comment`). What the role writes between them is for an engine that posts no comment on a line, which leaves it as it is: each comment in full.

View Source
var ErrUnreachable = errors.New("forge unreachable")

ErrUnreachable marks a forge that did not answer: the run is blocked by something outside the role.

Functions

func Bodies added in v0.11.0

func Bodies(notes []Note) []string

Bodies is the text of each note, in order.

func CommentLink(f any, issue int, id string) string

CommentLink is the address of a comment on an issue, by the forge's id of it (Note.ID): the product owner's comment on the issue links to the question it asked there; "" when the forge has no such address.

func FilePages added in v0.23.0

func FilePages(f any) string

FilePages is the address of f's files on the default branch, a file's path after it making its page: the product owner links the decisions and docs its drafts cite; "" when the forge has no such page.

func FillReview added in v0.25.0

func FillReview(body, section string) string

FillReview puts section in body's review region, the region's markers and what they held replaced; a body without the end marker has only ReviewHere replaced.

func InCI added in v0.2.2

func InCI() string

InCI names the variable that says the run is in CI, or "" outside it.

func IssuePages added in v0.23.0

func IssuePages(f any) string

IssuePages is the address of f's issues, an issue's number after it making its page: the job's summary links each issue it names (ADR-0038); "" when the forge has no such page.

func KeepsBranches added in v0.2.2

func KeepsBranches(f Forge) bool

KeepsBranches says whether f's merge requests come from local branches: nothing is pushed to a remote, nor fetched from one.

func LabelFilter added in v0.23.0

func LabelFilter(f any, label string) string

LabelFilter is the address of f's open issues bearing label, a person's saved filter; "" when the forge has no such page.

func Marker

func Marker(key string) string

Marker is the hidden text that makes a comment findable again.

func MergeRef added in v0.26.1

func MergeRef(f any, id int) string

MergeRef is how f names a merge request: !7 on GitLab, #7 elsewhere.

func MergeToken added in v0.26.1

func MergeToken(f any) string

MergeToken says why a merge f makes with its token would start no pipeline on the base — on GitHub Actions, the job's own token starts no workflow (ADR-0042) —, "" when it would.

func Refused added in v0.26.1

func Refused(err error) bool

Refused says whether err is the forge refusing a request — a token that may not, a request it does not take — rather than not answering.

func Said added in v0.26.1

func Said(err error) string

Said is what the forge said refusing, without the words that only mark the error's kind.

func ScopedLabels added in v0.23.0

func ScopedLabels(f any) bool

ScopedLabels says whether f's labels are scoped, `key::value`, as GitLab's: the product owner's own labels are named so there (ADR-0038).

Types

type Backlog added in v0.5.0

type Backlog interface {
	// Issues lists the open issues, merge requests left out, by number,
	// each with the issues it waits on in the forge's own relation.
	Issues() ([]Issue, error)
	// AllIssues lists the issues open and closed, merge requests left out,
	// by number: a subject a role found is looked for in both (OpenOnce).
	AllIssues() ([]Issue, error)
	// Comments lists the comments on t, oldest first.
	Comments(t Target) ([]string, error)
	// Notes lists the comments on t with their authors, oldest first, as
	// Comments does.
	Notes(t Target) ([]Note, error)
	// Close closes an issue: as a duplicate of dup when dup > 0, else as
	// completed. Closing one already closed changes nothing.
	Close(id, dup int) error
	// Milestones lists the open milestones, with their due dates.
	Milestones() ([]Milestone, error)
	// SetMilestone puts an issue in the open milestone with this title,
	// creating it when there is none.
	SetMilestone(id int, title string) error
	// SetBody rewrites an issue's body.
	SetBody(id int, body string) error
	// SetTitle renames an issue.
	SetTitle(id int, title string) error
	// AddSubIssue makes child a sub-issue of parent where the forge has
	// sub-issues, and says so; false on a forge that has none, the child
	// then listed in the parent's body by the caller. Adding one already
	// there changes nothing.
	AddSubIssue(parent, child int) (bool, error)
	// AddBlocker records that id waits on blocker in the forge's own
	// relation, and says so; false on a forge that has none — the caller
	// then writes a line in the body (ADR-0028). Adding one already there
	// changes nothing.
	AddBlocker(id, blocker int) (bool, error)
	// RemoveBlocker takes blocker off what id waits on in the forge's own
	// relation; one not there, or a forge without the relation, changes
	// nothing. Only the role's own links are taken off (ADR-0028).
	RemoveBlocker(id, blocker int) error
	// Closers lists what closed an issue, as the forge links it: the pull
	// or merge request, or the commit; nil when the forge does not say.
	Closers(id int) ([]Closer, error)
	// Trail says when an open issue last got a label, and what pull or
	// merge requests and commits name it; an empty Labeled when the
	// forge does not say (ADR-0031).
	Trail(id int, label string) (Trail, error)
	// EnsureLabel creates a label when the project has none of that name,
	// so a person finds it in the forge's list to set.
	EnsureLabel(name, color, description string) error
	// LabelEvents lists the labels set on an issue and taken off, oldest
	// first, with who did each and when; nil when the forge does not say
	// (ADR-0038).
	LabelEvents(id int) ([]LabelEvent, error)
	// React puts a reaction (Eyes) on a comment of an issue, by the note's
	// ID; one there already changes nothing, nor does a forge without
	// reactions (ADR-0038).
	React(id int, note, emoji string) error
}

Backlog is what a role acting on a project's issues needs from its forge (docs/spec/backlog-acts.md). Every forge workline speaks has it.

type Closer added in v0.14.0

type Closer struct {
	Kind string `json:"kind"`           // pull-request (a GitHub pull request, a GitLab merge request) or commit
	Ref  string `json:"ref"`            // how the forge names it: "#20", "!7", a short commit
	Text string `json:"text,omitempty"` // its title and description, or the commit's message
}

Closer is what closed an issue, as the forge links it: a pull or merge request merged, or a commit, with its text — the evidence a parent's report quotes (ADR-0029).

type Fake

type Fake struct{ Path, Repo string }

Fake is a forge kept in a JSON file, shared between processes, for the conformance tests. It can be told to fail its N-th write, once. Repo is the repository it serves: a merge request's diff is computed there.

func (*Fake) Accept added in v0.26.1

func (f *Fake) Accept(head string, ok bool, why string) error

Accept sets workline/accepted on head, as GitHub does.

func (*Fake) AddBlocker added in v0.14.0

func (f *Fake) AddBlocker(id, blocker int) (bool, error)

func (*Fake) AddSubIssue added in v0.11.0

func (f *Fake) AddSubIssue(parent, child int) (bool, error)

func (*Fake) AllIssues added in v0.10.0

func (f *Fake) AllIssues() ([]Issue, error)

func (*Fake) AutoMerge added in v0.26.1

func (f *Fake) AutoMerge(mr MergeRequest, head string, on bool) (bool, error)

AutoMerge turns auto-merge on, now, as workline's token's user, or off; one Clean is merged at once instead. A draft is refused, as GitHub refuses it.

func (*Fake) Close added in v0.5.0

func (f *Fake) Close(id, dup int) error

func (*Fake) CloseMergeRequest added in v0.25.0

func (f *Fake) CloseMergeRequest(branch, body, marker string) error

func (*Fake) Closers added in v0.14.0

func (f *Fake) Closers(id int) ([]Closer, error)

func (*Fake) Comment

func (f *Fake) Comment(t Target, body, marker string) error

func (*Fake) Comments added in v0.5.0

func (f *Fake) Comments(t Target) ([]string, error)

func (*Fake) EnsureLabel added in v0.7.0

func (f *Fake) EnsureLabel(name, color, description string) error

func (*Fake) Guarded added in v0.26.1

func (f *Fake) Guarded(base string) (string, error)

Guarded: as the file says (`unguarded`).

func (*Fake) Issue

func (f *Fake) Issue(id int) (*Issue, error)

func (*Fake) Issues added in v0.5.0

func (f *Fake) Issues() ([]Issue, error)

func (*Fake) KeepIssue

func (f *Fake) KeepIssue(title, body string, create bool) (int, error)

func (*Fake) KeepVerdict added in v0.26.1

func (f *Fake) KeepVerdict(head, class, why string) error

KeepVerdict keeps the verdict as GitHub does, a status by the token.

func (*Fake) Label

func (f *Fake) Label(t Target, add, remove []string) error

func (*Fake) LabelEvents added in v0.23.0

func (f *Fake) LabelEvents(id int) ([]LabelEvent, error)

func (*Fake) ListMergeRequests added in v0.25.0

func (f *Fake) ListMergeRequests() ([]MergeRequest, error)

ListMergeRequests lists the open merge requests, each head kept under refs/pull/<id>/head, as GitHub keeps them.

func (*Fake) MergeRequest added in v0.4.0

func (f *Fake) MergeRequest(id int) (MergeRequest, error)

func (*Fake) MergeState added in v0.26.1

func (f *Fake) MergeState(mr MergeRequest) (MergeState, error)

MergeState reads a merge request's state as the file holds it, its head and its pushes' heads resolved in the repository: the branch's tip on origin, a fork's under refs/pull/<id>/head.

func (*Fake) Milestones added in v0.5.0

func (f *Fake) Milestones() ([]Milestone, error)

func (*Fake) Notes added in v0.11.0

func (f *Fake) Notes(t Target) ([]Note, error)

func (*Fake) OpenIssue

func (f *Fake) OpenIssue(title, body, marker string) (int, error)

func (*Fake) OpenMergeRequest

func (f *Fake) OpenMergeRequest(branch, base, title, body string) (int, error)

func (*Fake) OpenMergeRequests

func (f *Fake) OpenMergeRequests(prefix string) ([]string, error)

func (*Fake) React added in v0.23.0

func (f *Fake) React(id int, note, emoji string) error

func (*Fake) RemoveBlocker added in v0.21.0

func (f *Fake) RemoveBlocker(id, blocker int) error

func (*Fake) Review added in v0.25.0

func (f *Fake) Review(id int, head, body string, comments []LineComment) (Reviewed, error)

Review keeps the comments as the merge request's threads, in one write, whole or not at all as GitHub's review; a line the merge request's diff does not show is left out. The diff is the repository's, from the merge request's base (main unless it names one) to head, as a forge computes it: renames found, three lines of context.

func (*Fake) SetBody added in v0.6.0

func (f *Fake) SetBody(id int, body string) error

func (*Fake) SetMilestone added in v0.5.0

func (f *Fake) SetMilestone(id int, title string) error

func (*Fake) SetTitle added in v0.11.0

func (f *Fake) SetTitle(id int, title string) error

func (*Fake) Sticky

func (f *Fake) Sticky(t Target, body, marker string, create bool) error

func (*Fake) Trail added in v0.15.0

func (f *Fake) Trail(id int, label string) (Trail, error)

func (*Fake) Verdict added in v0.26.1

func (f *Fake) Verdict(head string) (string, string, error)

Verdict reads back the verdict the token kept on head.

type FakeComment added in v0.11.0

type FakeComment Note

FakeComment is a comment: in the file, its body alone, or with its author as {body, author, insider, bot, created}.

func (FakeComment) MarshalJSON added in v0.11.0

func (c FakeComment) MarshalJSON() ([]byte, error)

func (*FakeComment) UnmarshalJSON added in v0.11.0

func (c *FakeComment) UnmarshalJSON(data []byte) error

type FakeItem

type FakeItem struct {
	ID        int           `json:"id"`
	Branch    string        `json:"branch,omitempty"` // a merge request's source branch
	Base      string        `json:"base,omitempty"`
	Closed    bool          `json:"closed,omitempty"`
	Reason    string        `json:"reason,omitempty"` // why it was closed: completed, not_planned or duplicate
	Milestone string        `json:"milestone,omitempty"`
	Fork      bool          `json:"fork,omitempty"` // a merge request from a fork
	Bot       bool          `json:"bot,omitempty"`  // a merge request a bot opened: an app, a token's user
	Title     string        `json:"title,omitempty"`
	Body      string        `json:"body,omitempty"`
	Labels    []string      `json:"labels"`
	Comments  []FakeComment `json:"comments"`
	Author    string        `json:"author,omitempty"`
	Insider   bool          `json:"insider,omitempty"`
	Parent    int           `json:"parent,omitempty"`     // the issue it is a sub-issue of
	BlockedBy []int         `json:"blocked-by,omitempty"` // the issues it waits on, in the forge's own relation
	ClosedBy  []Closer      `json:"closed-by,omitempty"`  // what closed it: a pull request, a commit
	// Labeled says when it last got each label; Links, what names it
	// (Trail, ADR-0031).
	Labeled map[string]string `json:"labeled,omitempty"`
	Links   []Link            `json:"links,omitempty"`
	// LabelEvents are its labels set and taken off, with who; Reactions,
	// the reactions on its comments, by the comment's id (ADR-0038).
	LabelEvents []LabelEvent        `json:"label-events,omitempty"`
	Reactions   map[string][]string `json:"reactions,omitempty"`
	// Threads are a merge request's comments on lines, as a review leaves
	// them (LineReviewer).
	Threads []FakeThread `json:"threads,omitempty"`
	// A merge request's state for the merge policy (MergeState, ADR-0042):
	// a draft; its auto-merge on, when it was last turned on and by whom;
	// its head's checks; its branch's pushes, each head a revision of the
	// repository. Clean: the forge would merge it at once, its rules met,
	// so turning auto-merge on merges it (Merged).
	Draft       bool       `json:"draft,omitempty"`
	AutoMerge   bool       `json:"auto-merge,omitempty"`
	AutoMergeAt string     `json:"auto-merge-at,omitempty"`
	AutoMergeBy string     `json:"auto-merge-by,omitempty"`
	Checks      string     `json:"checks,omitempty"`
	Pushes      []FakePush `json:"pushes,omitempty"`
	Clean       bool       `json:"clean,omitempty"`
	Merged      bool       `json:"merged,omitempty"`
}

FakeItem is an issue or a merge request.

type FakePush added in v0.26.1

type FakePush struct {
	Head string `json:"head"`
	At   string `json:"at"`
}

FakePush is a push to a merge request's branch: the head, a revision of the repository (a branch, branch~1), and when.

type FakeState

type FakeState struct {
	Issues        []FakeItem `json:"issues"`
	MergeRequests []FakeItem `json:"merge-requests"`
	Milestones    []string   `json:"milestones,omitempty"` // open milestones, by title
	// MilestoneDue gives a milestone its due date, YYYY-MM-DD, by title.
	MilestoneDue map[string]string `json:"milestone-due,omitempty"`
	Labels       []FakeItem        `json:"labels,omitempty"`       // labels defined, their name as id
	SubIssues    bool              `json:"sub-issues,omitempty"`   // the forge has sub-issues, as GitHub
	Dependencies bool              `json:"dependencies,omitempty"` // the forge has a blocked-by relation, as GitHub
	// Scoped: its labels are scoped, `key::value`, as GitLab's (ADR-0038).
	Scoped      bool `json:"scoped-labels,omitempty"`
	FailOnWrite int  `json:"fail-on-write,omitempty"` // the write that fails, counting from 1
	Writes      int  `json:"writes"`
	// ReviewRefused: the forge refuses every comment on a line, as a
	// token that may not review does, with this reason (HTTP 403).
	ReviewRefused string `json:"review-refused,omitempty"`
	Reviews       int    `json:"reviews,omitempty"` // the reviews posted, each holding comments on lines
	// JobToken: the token is a CI job's own, whose merges start no
	// pipeline, as GitHub's GITHUB_TOKEN (MergeToken, ADR-0042).
	JobToken bool `json:"job-token,omitempty"`
	// Unguarded: why a push after a yes could merge before follow takes
	// it back — a base not requiring workline/accepted (Guarded).
	Unguarded string `json:"unguarded,omitempty"`
	// Statuses are the statuses set on commits, as GitHub keeps them: the
	// commit a revision of the repository, who set it (`workline-bot`, the
	// token's user, or another).
	Statuses []FakeStatus `json:"statuses,omitempty"`
}

FakeState is the file's content.

type FakeStatus added in v0.26.1

type FakeStatus struct {
	Commit      string `json:"commit"`
	Name        string `json:"name"`
	State       string `json:"state,omitempty"`
	Description string `json:"description,omitempty"`
	By          string `json:"by"`
}

FakeStatus is a status set on a commit.

type FakeThread added in v0.25.0

type FakeThread struct {
	Path     string `json:"path"`
	Line     int    `json:"line"`
	Body     string `json:"body"`
	Resolved bool   `json:"resolved,omitempty"`
}

FakeThread is a comment on a line of a merge request: its file and line in the file at the head of the change, its text, and whether a person resolved it.

type Forge

type Forge interface {
	Issue(id int) (*Issue, error)
	// Comment posts body on t unless a comment carrying marker is already there.
	Comment(t Target, body, marker string) error
	// Sticky keeps one comment carrying marker on t, edited to body on each
	// run instead of a new one each time; with create false, it only edits
	// one already there.
	Sticky(t Target, body, marker string, create bool) error
	// Label adds and removes labels; adding one already there changes nothing.
	Label(t Target, add, remove []string) error
	// OpenIssue creates an issue, or comments on an open one with the same title.
	OpenIssue(title, body, marker string) (int, error)
	// KeepIssue rewrites the body of the open issue with this title, or opens
	// it when there is none and create is true: one issue, kept in place.
	KeepIssue(title, body string, create bool) (int, error)
	// OpenMergeRequest opens a merge request from branch into base, or
	// updates the title and body of the one already open from branch.
	OpenMergeRequest(branch, base, title, body string) (int, error)
	// OpenMergeRequests lists the branches of the open merge requests whose
	// branch starts with prefix, sorted.
	OpenMergeRequests(prefix string) ([]string, error)
	// CloseMergeRequest closes the open merge request from branch, saying
	// why in a comment carrying marker, posted once; with none open from
	// branch, it changes nothing. The branch stays.
	CloseMergeRequest(branch, body, marker string) error
	// MergeRequest says where a merge request comes from and goes.
	MergeRequest(id int) (MergeRequest, error)
	// ListMergeRequests lists the open merge requests, by number, each with
	// where it comes from and goes, and who opened it: what `workline
	// follow` needs to merge a base into a person's (ADR-0041).
	ListMergeRequests() ([]MergeRequest, error)
}

Forge is what the engine needs from one.

func Open

func Open(spec, repo string) (Forge, error)

Open returns the forge named by spec: "github", "gitlab", "local" (kept in the clone), "cmd:<command>" (another forge, plugged by a command), "fake:<file>", or "" / "none" for no forge: what needs one is refused, and says so.

type Issue

type Issue struct {
	ID        int      `json:"id"`
	Title     string   `json:"title"`
	Body      string   `json:"body"`
	Labels    []string `json:"labels"`
	Closed    bool     `json:"closed,omitempty"`
	Reason    string   `json:"reason,omitempty"`    // why it was closed, when the forge says: completed, not_planned, duplicate
	Milestone string   `json:"milestone,omitempty"` // the title of the milestone it is in, if any
	// MilestoneDue is its milestone's due date, YYYY-MM-DD, when it has
	// one: the backlog's order ranks milestones by it (Milestone).
	MilestoneDue string `json:"milestone-due,omitempty"`
	Author       string `json:"author,omitempty"`  // who opened it
	Insider      bool   `json:"insider,omitempty"` // its author is a person of the project (GitHub: owner, member, collaborator; GitLab: Planner or above); false when the forge does not say
	// BlockedBy are the issues it waits on in the forge's own relation
	// (GitHub's dependencies, GitLab's is_blocked_by), open or closed, as
	// Issues gives them; a line in its body says the rest (ADR-0028).
	BlockedBy []int `json:"blocked-by,omitempty"`
	// Children are its sub-issues in the forge's own relation (GitHub's
	// sub-issues, GitLab's tasks), open or closed, as Issues gives them; a
	// task list under "## Sub-issues" in its body says the rest (ADR-0029).
	Children []int `json:"children,omitempty"`
}

Issue is what the line reads from a work item.

type LabelEvent added in v0.23.0

type LabelEvent struct {
	Label string `json:"label"`
	Added bool   `json:"added,omitempty"` // set; false: taken off
	// Writer: who did it may push and merge — GitHub's write, maintain or
	// admin; GitLab's Developer or above —, the merge policy's yes
	// (ADR-0042); Insider, a person of the project, is wider on GitLab.
	Writer bool `json:"writer,omitempty"`
	Note
}

LabelEvent is a label set on an issue, or taken off, with who did it and when (ADR-0038): Author, Insider and Bot as a Note's; Created, when.

type LineComment added in v0.25.0

type LineComment struct {
	Path string `json:"path" yaml:"path"`
	Line int    `json:"line" yaml:"line"` // in the file at the head of the change
	// Key is what it says, hidden in it (Marker("line="+Key)): while a
	// comment holding it is open on the merge request, it is not posted
	// again; resolved, it is.
	Key  string `json:"key,omitempty" yaml:"key,omitempty"`
	Body string `json:"body" yaml:"body"`
}

LineComment is a comment on a line of a merge request's change: a reviewer's finding where it stands, for its author to answer or resolve there, as a person's review comment (#277).

type LineReviewer added in v0.25.0

type LineReviewer interface {
	Review(id int, head, body string, comments []LineComment) (Reviewed, error)
}

LineReviewer is a forge that takes comments on the lines of a merge request, in its own review: GitHub's pull request review, GitLab's discussions on the diff, the simulated forge's threads. A review never approves nor asks for changes (ADR-0020). A comment on a line its diff does not show is left out, never forced elsewhere; one the forge refuses — a token that may not review — is said, never an error: only a forge out of reach is.

type Link struct {
	Kind string `json:"kind"`         // pull-request (a GitHub pull request, a GitLab merge request) or commit
	Ref  string `json:"ref"`          // how the forge names it: "#20", "!7", a short commit
	At   string `json:"at,omitempty"` // when it named the issue, RFC 3339 or YYYY-MM-DD
}

Link is a pull or merge request, or a commit, naming an issue.

type Local added in v0.2.2

type Local struct{ Repo string }

Local is a forge kept in the clone, never committed: for a project with no forge, or one whose person works alone. Each issue is a Markdown file, .git/workline/issues/<n>.md; each merge request is a local branch, recorded the same way in .git/workline/merge-requests/<n>.md. Nothing is pushed: `workline issues` reads them. Writes are idempotent, as on any forge.

func (*Local) AddBlocker added in v0.14.0

func (l *Local) AddBlocker(id, blocker int) (bool, error)

AddBlocker: the local forge has no relation between issues; the body says what an issue waits on (ADR-0028).

func (*Local) AddSubIssue added in v0.11.0

func (l *Local) AddSubIssue(parent, child int) (bool, error)

AddSubIssue: the local forge has no sub-issues; the parent's body lists its children.

func (*Local) AllIssues added in v0.10.0

func (l *Local) AllIssues() ([]Issue, error)

AllIssues: the local forge keeps no close reason.

func (*Local) Close added in v0.5.0

func (l *Local) Close(id, dup int) error

Close closes an issue; the local forge keeps no reason, the engine's comment says it.

func (*Local) CloseMergeRequest added in v0.25.0

func (l *Local) CloseMergeRequest(branch, body, marker string) error

func (*Local) Closers added in v0.14.0

func (l *Local) Closers(id int) ([]Closer, error)

Closers: the local forge does not link what closed an issue.

func (*Local) Comment added in v0.2.2

func (l *Local) Comment(t Target, body, marker string) error

func (*Local) Comments added in v0.5.0

func (l *Local) Comments(t Target) ([]string, error)

func (*Local) EnsureLabel added in v0.7.0

func (l *Local) EnsureLabel(name, color, description string) error

EnsureLabel: the local forge keeps no list of labels apart from its items.

func (*Local) Issue added in v0.2.2

func (l *Local) Issue(id int) (*Issue, error)

func (*Local) Issues added in v0.5.0

func (l *Local) Issues() ([]Issue, error)

func (*Local) Item added in v0.2.2

func (l *Local) Item(kind string, id int) (*LocalItem, error)

Item reads one issue or merge request.

func (*Local) Items added in v0.2.2

func (l *Local) Items(kind string) ([]*LocalItem, error)

Items lists the issues, or the merge requests, by number.

func (*Local) KeepIssue added in v0.2.2

func (l *Local) KeepIssue(title, body string, create bool) (int, error)

func (*Local) Label added in v0.2.2

func (l *Local) Label(t Target, add, remove []string) error

func (*Local) LabelEvents added in v0.23.0

func (l *Local) LabelEvents(id int) ([]LabelEvent, error)

LabelEvents: the local forge keeps no history: it does not say who set a label.

func (*Local) ListMergeRequests added in v0.25.0

func (l *Local) ListMergeRequests() ([]MergeRequest, error)

ListMergeRequests lists the open merge requests: each from a branch of this clone, by whoever wrote it.

func (*Local) MergeRequest added in v0.4.0

func (l *Local) MergeRequest(id int) (MergeRequest, error)

func (*Local) Milestones added in v0.5.0

func (l *Local) Milestones() ([]Milestone, error)

Milestones are the ones its open issues are in: the local forge keeps no milestone apart from them.

func (*Local) Notes added in v0.11.0

func (l *Local) Notes(t Target) ([]Note, error)

Notes: the local forge keeps no author; whoever writes in the clone is of the project, as its issues' authors are.

func (*Local) OpenIssue added in v0.2.2

func (l *Local) OpenIssue(title, body, marker string) (int, error)

func (*Local) OpenMergeRequest added in v0.2.2

func (l *Local) OpenMergeRequest(branch, base, title, body string) (int, error)

func (*Local) OpenMergeRequests added in v0.2.2

func (l *Local) OpenMergeRequests(prefix string) ([]string, error)

func (*Local) React added in v0.23.0

func (l *Local) React(id int, note, emoji string) error

React: the local forge has no reactions; nothing to do.

func (*Local) RemoveBlocker added in v0.21.0

func (l *Local) RemoveBlocker(id, blocker int) error

RemoveBlocker: no relation, nothing to take off; the body's line is the caller's.

func (*Local) SetBody added in v0.6.0

func (l *Local) SetBody(id int, body string) error

func (*Local) SetMilestone added in v0.5.0

func (l *Local) SetMilestone(id int, title string) error

func (*Local) SetTitle added in v0.11.0

func (l *Local) SetTitle(id int, title string) error

func (*Local) StateOf added in v0.2.2

func (l *Local) StateOf(it *LocalItem) string

StateOf is an item's state as it stands: a merge request whose branch is gone is closed, one whose branch its base holds is merged — the person merges it with git.

func (*Local) Sticky added in v0.2.2

func (l *Local) Sticky(t Target, body, marker string, create bool) error

func (*Local) Trail added in v0.15.0

func (l *Local) Trail(id int, label string) (Trail, error)

Trail: the local forge keeps no history, nor links: it does not say when an issue got a label (ADR-0031).

type LocalItem added in v0.2.2

type LocalItem struct {
	ID        int      `yaml:"-"`
	Title     string   `yaml:"title"`
	State     string   `yaml:"state"` // open or closed, as written; see Local.StateOf
	Labels    []string `yaml:"labels,flow"`
	Milestone string   `yaml:"milestone,omitempty"`
	Branch    string   `yaml:"branch,omitempty"` // a merge request's local branch
	Base      string   `yaml:"base,omitempty"`
	Body      string   `yaml:"-"`
	Comments  []string `yaml:"-"`
}

LocalItem is an issue or a merge request of the local forge.

type MergeRequest added in v0.4.0

type MergeRequest struct {
	ID     int    // its number; 0 when the forge does not say
	Branch string // the branch it comes from
	Base   string // the branch it goes into; "" when the forge does not say
	Here   bool   // the branch lives in this repository, not in a fork
	Title  string // what its author calls it
	Body   string // what its author says of it: testimony for a review (ADR-0020)
	Author string // who opened it; "" when the forge does not say
	Bot    bool   // opened by a bot: an app, a token's user
	// Head is the ref this repository keeps its head under, for one from a
	// fork (GitHub's refs/pull/<n>/head); "" when the forge keeps none.
	Head string
	// Labels, Draft and AutoMerge are what ListMergeRequests reads of it
	// for the merge policy (ADR-0042): its labels, whether it is a draft,
	// whether the forge's auto-merge is on.
	Labels    []string
	Draft     bool
	AutoMerge bool
}

MergeRequest is where a merge request comes from and where it goes.

func (MergeRequest) ByBot added in v0.25.0

func (m MergeRequest) ByBot() bool

ByBot says whether a merge request is a bot's: opened by one, or from a dependency bot's branch.

type MergeState added in v0.26.1

type MergeState struct {
	Head  string `json:"head"` // its head commit
	Draft bool   `json:"draft,omitempty"`
	// AutoMerge: the forge's auto-merge is on now. AutoMergeAt: when it
	// was last turned on, on now or not; "" never, or the forge does not
	// say. AutoMergeBy, AutoMergeBot: who turned it on now, and whether a
	// bot — workline's token, an app.
	AutoMerge    bool   `json:"auto-merge,omitempty"`
	AutoMergeAt  string `json:"auto-merge-at,omitempty"`
	AutoMergeBy  string `json:"auto-merge-by,omitempty"`
	AutoMergeBot bool   `json:"auto-merge-bot,omitempty"`
	// Checks: its head's checks as the forge sums them up — success,
	// pending, failure; "" none, or unread (ChecksUnread says why).
	Checks       string `json:"checks,omitempty"`
	ChecksUnread string `json:"checks-unread,omitempty"`
	// Labels are its labels set and taken off, oldest first, with who did
	// each, as Backlog's LabelEvents.
	Labels []LabelEvent `json:"label-events,omitempty"`
	// Pushes are the heads its branch was pushed to, oldest first; nil when
	// the forge does not say.
	Pushes []Push `json:"pushes,omitempty"`
}

MergeState is what the merge policy weighs of an open merge request (ADR-0042), as its forge says it.

type Merger added in v0.26.1

type Merger interface {
	// MergeState reads an open merge request's state.
	MergeState(mr MergeRequest) (MergeState, error)
	// AutoMerge turns the forge's auto-merge on for the merge request at
	// head, or off. merged: the forge took it at once, its rules met
	// already (GitHub turns no auto-merge on for a pull request it could
	// merge now). Turning off one already off changes nothing.
	AutoMerge(mr MergeRequest, head string, on bool) (merged bool, err error)
	// Guarded says why a push after a person's yes could merge before
	// `follow` takes the yes back; "" when the forge holds it: GitHub when
	// the base requires the status Accepted, which a new head lacks;
	// GitLab, whose merge waits for the head's pipeline, `follow` in it.
	Guarded(base string) (string, error)
	// Accept marks a head accepted, or not, where the forge needs it to
	// hold a yes to that head only (GitHub: the status Accepted, by this
	// token); nothing where it does not.
	Accept(head string, ok bool, why string) error
	// KeepVerdict keeps the line's verdict on a head — its class, pass,
	// held, short or red, and why — where only this token writes it
	// (GitHub: the status VerdictStatus); Verdict reads it back, "" when
	// none is kept, or the forge keeps none (GitLab: the verdict is in hand
	// in the pipeline that judged the head).
	KeepVerdict(head, class, why string) error
	Verdict(head string) (class, why string, err error)
}

Merger is a forge whose own auto-merge the merge policy turns on and off (ADR-0042): the forge merges, checking its own rules.

type Milestone added in v0.21.0

type Milestone struct {
	Title string `json:"title"`
	Due   string `json:"due,omitempty"`
}

Milestone is an open milestone: its title, and its due date when it has one, YYYY-MM-DD — what the backlog's order ranks milestones by first, the title after (docs/spec/backlog-acts.md, "Ordering").

type Note added in v0.11.0

type Note struct {
	Body    string `json:"body"`
	Author  string `json:"author,omitempty"`  // who wrote it; "" when the forge does not say
	Insider bool   `json:"insider,omitempty"` // its author is a person of the project, as Issue.Insider
	Bot     bool   `json:"bot,omitempty"`     // its author is a bot: a token's user, an app
	Created string `json:"created,omitempty"` // when it was written, RFC 3339 or YYYY-MM-DD; "" when the forge does not say
	// ID is the forge's own id of the comment, to put a reaction on it
	// (React); "" when the forge does not say.
	ID string `json:"id,omitempty"`
}

Note is a comment with who wrote it: what a reply decides counts only from the right people (ADR-0021).

type Placed added in v0.25.0

type Placed struct {
	LineComment
	State string `json:"state"`
	Why   string `json:"why,omitempty"`
}

Placed is what became of a line comment.

type Push added in v0.26.1

type Push struct {
	Head string `json:"head"`
	At   string `json:"at"` // RFC 3339
}

Push is a head a merge request's branch was pushed to, and when.

type Reviewed added in v0.25.0

type Reviewed struct {
	URL    string   `json:"url,omitempty"`
	Placed []Placed `json:"placed"`
}

Reviewed is a review's outcome: where a person reads it — the review posted, else the merge request's changes, where its comments show — and each comment's fate, in the order given.

func Unplaced added in v0.25.0

func Unplaced(comments []LineComment, why string) Reviewed

Unplaced is comments none of which is on its line, each for why.

func (Reviewed) Section added in v0.25.0

func (r Reviewed) Section() string

Section says where the comments on lines are, with a link to the review, and gives in full those not on their line, grouped by why: what a summary comment says of its review.

type Target

type Target struct {
	Kind string `json:"kind" yaml:"kind"` // "issue" or "merge-request"
	ID   int    `json:"id" yaml:"id"`
}

Target is what a comment or a label goes on.

func (Target) String

func (t Target) String() string

type Trail added in v0.15.0

type Trail struct {
	Labeled string `json:"labeled,omitempty"` // when it last got the label, RFC 3339 or YYYY-MM-DD; "" when the forge does not say
	Links   []Link `json:"links,omitempty"`
}

Trail is what a forge says of an open issue since it got a label: when it last got it, and the pull or merge requests and commits that name the issue, each with when — what started it, or nothing (ADR-0031).

Jump to

Keyboard shortcuts

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