stack

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: Aug 11, 2026 License: AGPL-3.0 Imports: 8 Imported by: 0

Documentation

Overview

Package stack models a feature that spans several repositories: a set of merge requests with a dependency order between them.

A stack is not a chain of git branches. Each merge request is cut from its own repository's default branch; what the stack records is the order they must merge in, so an SDK change lands before the API change that needs it.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrCycle       = errors.New("the stack has a dependency cycle")
	ErrUnknownDep  = errors.New("the stack depends on an item that does not exist")
	ErrDuplicateID = errors.New("the stack has two items with the same id")
)

Errors returned when a stack does not describe a valid graph.

View Source
var ErrBadName = errors.New("a stack name cannot be empty or contain a path")

ErrBadName rejects a name that is not one: a stack's name comes from a hand-written YAML field and ends up as a path, so it may not point anywhere but straight at a file in the stacks directory.

View Source
var ErrNoStack = errors.New("no such stack")

ErrNoStack is reported when there is no stack by that name to act on.

StatusOrder is the order a summary reads in.

Functions

func CheckName added in v0.10.0

func CheckName(name string) error

CheckName reports why a name is not usable as a stack's, so a dialog can say so while the name is still being typed rather than at save time.

func Delete added in v0.8.0

func Delete(dir, name string) error

Delete removes a stack's file. It is not recoverable, which is why the name is checked before anything is joined onto a path.

func Dir

func Dir(configDir string) string

Dir returns the directory stacks are stored in, under gu's config dir.

Types

type Item

type Item struct {
	ID        string   `yaml:"id"`
	Profile   string   `yaml:"profile,omitempty"`
	Host      string   `yaml:"host"`
	Repo      string   `yaml:"repo"`
	MR        int      `yaml:"mr"`
	DependsOn []string `yaml:"depends_on,omitempty"`
}

Item is one merge request in a stack.

Profile is per item, not per stack: a feature can legitimately span two identities, or two providers, and the profile is what tells them apart when both live on the same host.

type Stack

type Stack struct {
	Name     string `yaml:"name"`
	Archived bool   `yaml:"archived,omitempty"`
	Items    []Item `yaml:"items"`
	// contains filtered or unexported fields
}

Stack is a named set of merge requests and the edges between them.

An archived stack is one that has been put away — its work is done — and is hidden from the list until asked for. Nothing else changes: it still loads, still resolves, and unarchiving is the same flag going back.

func Load

func Load(path string) (*Stack, error)

Load reads one stack file.

func LoadAll

func LoadAll(dir string) ([]*Stack, error)

LoadAll reads every stack in a directory, sorted by name. A missing directory yields no stacks and no error: not having any is normal.

func (*Stack) AllMerged added in v0.8.0

func (s *Stack) AllMerged(states map[string]State) bool

AllMerged reports a stack that has finished: every item merged, and at least one item to have merged. An empty stack has not finished anything.

func (*Stack) Blockers

func (s *Stack) Blockers(id string, states map[string]State) []string

Blockers lists the dependencies of id that have not merged yet.

func (*Stack) Delete added in v0.8.0

func (s *Stack) Delete(dir string) error

Delete removes the file this stack was read from.

func (*Stack) Dependents

func (s *Stack) Dependents(id string) []Item

Dependents lists the items that depend directly on id — the ones that may need rebasing once it merges.

func (*Stack) Find

func (s *Stack) Find(id string) (Item, bool)

Find returns the item with the given id.

func (*Stack) Layers

func (s *Stack) Layers() ([][]Item, error)

Layers groups the items by how deep they sit in the dependency graph: layer 0 depends on nothing, layer 1 on layer 0, and so on.

It is the shape the graph is drawn in — everything in a layer can merge in parallel once the layer before it has landed, which is the thing a reader wants to see. Items within a layer keep their declared order.

func (*Stack) Next

func (s *Stack) Next(states map[string]State, greenStatus string) (Item, bool)

Next is the item to merge now: the first in dependency order that is ready.

There is deliberately only ever one. Merging two at once means the second was resolved against a tree the first has since changed.

func (*Stack) Order

func (s *Stack) Order() ([]Item, error)

Order returns the items in an order that satisfies every dependency: nothing appears before something it depends on. Items that do not depend on each other keep their declared order, so the file stays readable.

It reports ErrCycle, ErrUnknownDep or ErrDuplicateID rather than guessing.

func (*Stack) Progress

func (s *Stack) Progress(states map[string]State) (merged, total int)

Progress counts how many items have merged.

func (*Stack) Ready

func (s *Stack) Ready(id string, states map[string]State, greenStatus string) bool

Ready reports whether an item can be merged right now: every dependency has merged, the provider considers it mergeable, and its own pipeline is green.

A missing pipeline does not block: plenty of repositories have no CI.

func (*Stack) Save

func (s *Stack) Save(dir string) error

Save writes the stack into dir, creating it if needed.

A stack that was read from a file in dir is written back to that same file, extension and all: a stack kept as `.yml` must not reappear as a second `.yaml` one the next time it is archived.

func (*Stack) StatusOf

func (s *Stack) StatusOf(id string, states map[string]State, greenStatus string) Status

StatusOf classifies one item.

Blocked outranks waiting: an item whose dependency has not merged is not waiting for its own CI in any useful sense, and saying "blocked on sdk" is more use than "waiting".

func (*Stack) Summary

func (s *Stack) Summary(states map[string]State, greenStatus string) map[Status]int

Summary counts the items by status, for a one-line "where is this stack".

func (*Stack) Validate

func (s *Stack) Validate() error

Validate checks the graph without ordering it.

type State

type State struct {
	Merged    bool
	Closed    bool
	Mergeable bool
	// Pipeline is the CI status of the item's own branch, using the
	// forge.Status* vocabulary. Empty means "no pipeline".
	Pipeline string
}

State is what the provider currently says about one item. The UI fills this in; the stack itself performs no I/O.

type Status

type Status string

Status is where one item stands, as a single word.

It exists so the list, the graph and the merge gate say the same thing about the same item: three places deciding separately what "ready" means is three chances to disagree.

const (
	Merged  Status = "merged"
	Ready   Status = "ready"
	Waiting Status = "waiting" // its own CI is not green yet
	Blocked Status = "blocked" // something it depends on has not merged
	Closed  Status = "closed"
	Stuck   Status = "stuck" // nothing blocking it, but the provider refuses
	Unknown Status = "unknown"
)

The states an item can be in, in the order a stack moves through them.

func SortedStatuses

func SortedStatuses(summary map[Status]int) []Status

SortedStatuses is the statuses present in a summary, in reading order.

func (Status) Done

func (s Status) Done() bool

Done reports whether the item needs nothing further.

Jump to

Keyboard shortcuts

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