shippable

package
v0.17.14 Latest Latest
Warning

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

Go to latest
Published: May 11, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package shippable provides analysis and management of shippable work. It determines which stacks are ready to be merged to trunk based on PR approval status, CI checks, and combinability with other stacks.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetBlockingReasonDescription

func GetBlockingReasonDescription(reason BlockingReason) string

GetBlockingReasonDescription returns a human-readable description of a BlockingReason.

func GetStatusDescription

func GetStatusDescription(status Status) string

GetStatusDescription returns a human-readable description of a Status.

func UpdateCompatibility

func UpdateCompatibility(stacks []Stack, result *CombinationResult)

UpdateCompatibility updates the compatibility information for each stack based on a combination result.

Types

type AnalysisResult

type AnalysisResult struct {
	Stacks          []Stack // All analyzed stacks
	ShippableCount  int     // Number of shippable stacks
	PendingCount    int     // Number of pending stacks
	BlockedCount    int     // Number of blocked stacks
	IncompleteCount int     // Number of incomplete stacks
}

AnalysisResult contains the result of analyzing all stacks.

func (*AnalysisResult) FilterByAuthor

func (r *AnalysisResult) FilterByAuthor(author string) *AnalysisResult

FilterByAuthor returns a new AnalysisResult containing only stacks by the given author.

func (*AnalysisResult) GetBlocked

func (r *AnalysisResult) GetBlocked() []Stack

GetBlocked returns only the stacks that are blocked.

func (*AnalysisResult) GetIncomplete

func (r *AnalysisResult) GetIncomplete() []Stack

GetIncomplete returns only the stacks that are incomplete.

func (*AnalysisResult) GetPending

func (r *AnalysisResult) GetPending() []Stack

GetPending returns only the stacks that are pending.

func (*AnalysisResult) GetShippable

func (r *AnalysisResult) GetShippable() []Stack

GetShippable returns only the stacks that are ready to ship.

func (*AnalysisResult) HasShippable

func (r *AnalysisResult) HasShippable() bool

HasShippable returns true if there are any shippable stacks.

func (*AnalysisResult) TotalStacks

func (r *AnalysisResult) TotalStacks() int

TotalStacks returns the total number of stacks analyzed.

type Analyzer

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

Analyzer analyzes stacks for shippability.

func NewAnalyzer

func NewAnalyzer(eng engine.BranchReader, client github.Client) *Analyzer

NewAnalyzer creates a new shippability analyzer.

func (*Analyzer) AnalyzeAll

func (a *Analyzer) AnalyzeAll(ctx context.Context) (*AnalysisResult, error)

AnalyzeAll discovers and analyzes all stacks for shippability.

func (*Analyzer) AnalyzeStack

func (a *Analyzer) AnalyzeStack(ctx context.Context, stack merge.MultiStackInfo) (*Stack, error)

AnalyzeStack analyzes a single stack for shippability. This can be used when you already have a stack and status information.

type BlockingPR

type BlockingPR struct {
	Branch   string         // Branch name
	PRNumber int            // PR number (0 if no PR)
	Reason   BlockingReason // Why this PR is blocking
}

BlockingPR describes a PR that is blocking a stack from being shippable.

type BlockingReason

type BlockingReason string

BlockingReason describes why a PR is blocking shippability.

const (
	// ReasonChangesRequested indicates a reviewer has requested changes.
	ReasonChangesRequested BlockingReason = "changes_requested"
	// ReasonCIFailing indicates CI checks are failing.
	ReasonCIFailing BlockingReason = "ci_failing"
	// ReasonCIPending indicates CI checks are still running.
	ReasonCIPending BlockingReason = "ci_pending"
	// ReasonDraft indicates the PR is still a draft.
	ReasonDraft BlockingReason = "draft"
	// ReasonNoPR indicates no PR exists for this branch.
	ReasonNoPR BlockingReason = "no_pr"
	// ReasonReviewRequired indicates the PR needs review approval.
	ReasonReviewRequired BlockingReason = "review_required"
	// ReasonNotPushed indicates the local branch differs from remote.
	ReasonNotPushed BlockingReason = "not_pushed"
)

type CheckCombinationOptions

type CheckCombinationOptions struct {
	// RunLocalCI determines whether to run local CI validation after merge.
	RunLocalCI bool
}

CheckCombinationOptions configures how combination checking is performed.

type CombinationResult

type CombinationResult struct {
	// Combinable indicates whether the selected stacks can be merged without conflicts.
	Combinable bool

	// WorkingStacks are stacks that can be merged together.
	WorkingStacks []Stack

	// ConflictingStacks are stacks that conflict and cannot be included.
	ConflictingStacks []ExcludedStack

	// LocalCIPassed indicates whether local CI passed on the combined code.
	// nil means local CI was not run.
	LocalCIPassed *bool

	// LocalCIError contains the error if local CI failed.
	LocalCIError error
}

CombinationResult contains the result of checking if stacks can be merged together.

func (*CombinationResult) AllCombined

func (r *CombinationResult) AllCombined() bool

AllCombined returns true if all stacks could be combined.

func (*CombinationResult) ExcludedCount

func (r *CombinationResult) ExcludedCount() int

ExcludedCount returns the number of stacks that were excluded.

func (*CombinationResult) GetConflictingRoots

func (r *CombinationResult) GetConflictingRoots() []string

GetConflictingRoots returns the root branch names of conflicting stacks.

func (*CombinationResult) GetWorkingRoots

func (r *CombinationResult) GetWorkingRoots() []string

GetWorkingRoots returns the root branch names of working stacks.

func (*CombinationResult) IncludedCount

func (r *CombinationResult) IncludedCount() int

IncludedCount returns the number of stacks that can be combined.

type Combiner

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

Combiner analyzes whether multiple stacks can be merged together.

func NewCombiner

func NewCombiner(eng engine.Engine, cfg config.Configurer, out output.Output) *Combiner

NewCombiner creates a new stack combiner.

func (*Combiner) CheckCombination

func (c *Combiner) CheckCombination(ctx context.Context, stacks []Stack, opts CheckCombinationOptions) (*CombinationResult, error)

CheckCombination checks if the given stacks can be merged together. It creates a temporary worktree, attempts to merge all stacks, and optionally runs local CI to verify the combined code compiles/passes tests.

func (*Combiner) FindLargestCompatible

func (c *Combiner) FindLargestCompatible(ctx context.Context, stacks []Stack, opts FindLargestCompatibleOptions) (*CombinationResult, error)

FindLargestCompatible finds the largest subset of stacks that can be merged together. It uses a greedy approach: try adding stacks one by one, keeping those that merge cleanly. If RunLocalCI is true, it also validates that the combined code passes local CI.

type ExcludedStack

type ExcludedStack struct {
	Stack  Stack           // The excluded stack
	Reason ExclusionReason // Why it was excluded
}

ExcludedStack represents a stack that was excluded from a combination.

type ExclusionReason

type ExclusionReason string

ExclusionReason describes why a stack was excluded from a combination.

const (
	// ReasonMergeConflict indicates the stack has merge conflicts with others.
	ReasonMergeConflict ExclusionReason = "merge_conflict"
	// ReasonLocalCIFailed indicates local CI failed when this stack was included.
	ReasonLocalCIFailed ExclusionReason = "local_ci_failed"
)

type FindLargestCompatibleOptions

type FindLargestCompatibleOptions struct {
	// RunLocalCI determines whether to run local CI for each candidate set.
	RunLocalCI bool
}

FindLargestCompatibleOptions configures how the search is performed.

type ShipOptions

type ShipOptions struct {
	// SkipLocalCI skips local CI validation.
	SkipLocalCI bool
	// Wait waits for CI and auto-merges the PR.
	Wait bool
}

ShipOptions configures the ship operation.

type ShipResult

type ShipResult struct {
	// IncludedStacks are stacks that were successfully shipped.
	IncludedStacks []Stack
	// ExcludedStacks are stacks that were excluded due to conflicts.
	ExcludedStacks []ExcludedStack
	// PRNumber is the created PR number.
	PRNumber int
	// PRURL is the created PR URL.
	PRURL string
	// BranchName is the consolidation branch name.
	BranchName string
}

ShipResult contains the result of a ship operation.

type Shipper

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

Shipper handles shipping selected stacks to trunk.

func NewShipper

func NewShipper(ctx *app.Context) *Shipper

NewShipper creates a new shipper.

func (*Shipper) Ship

func (s *Shipper) Ship(stacks []Stack, opts ShipOptions) (*ShipResult, error)

Ship ships the selected stacks to trunk by creating a consolidated PR. It uses the existing multi-stack merge functionality.

type Stack

type Stack struct {
	Stack   merge.MultiStackInfo // The underlying stack
	Status  Status               // Overall shippability status
	Author  string               // GitHub username of stack author (from first PR)
	PRTitle string               // PR title of the root branch (for display)

	// Breakdown of shippability components
	ApprovalOK bool  // All PRs have been approved
	GitHubCIOK bool  // All GitHub CI checks are passing
	LocalCIOK  *bool // Local CI result (nil = not checked)

	// Blocking details
	BlockingPRs []BlockingPR // PRs blocking shippability

	// Compatibility (populated during combination analysis)
	CompatibleWith []string // Root branches this can ship with
	ConflictsWith  []string // Root branches this conflicts with
}

Stack represents a stack with its shippability analysis.

func (*Stack) BranchCount

func (s *Stack) BranchCount() int

BranchCount returns the total number of branches in this stack.

func (*Stack) DisplayTitle

func (s *Stack) DisplayTitle() string

DisplayTitle returns the best title for displaying this stack. The analyzer populates PRTitle with: PR title > commit subject > branch name. Falls back to branch name if PRTitle is empty (e.g., in tests).

func (*Stack) IsBlocked

func (s *Stack) IsBlocked() bool

IsBlocked returns true if the stack has failed CI or has changes requested.

func (*Stack) IsIncomplete

func (s *Stack) IsIncomplete() bool

IsIncomplete returns true if the stack is missing PRs or has drafts.

func (*Stack) IsPending

func (s *Stack) IsPending() bool

IsPending returns true if the stack is waiting on CI or review.

func (*Stack) IsShippable

func (s *Stack) IsShippable() bool

IsShippable returns true if the stack is ready to ship.

func (*Stack) RootBranch

func (s *Stack) RootBranch() string

RootBranch returns the root branch name of this stack.

type Status

type Status string

Status represents the overall shippability state of a stack.

const (
	// StatusShippable indicates the stack is ready to ship (all checks pass, approved).
	StatusShippable Status = "shippable"
	// StatusPending indicates the stack is waiting on CI or review.
	StatusPending Status = "pending"
	// StatusBlocked indicates the stack cannot ship (CI failed or changes requested).
	StatusBlocked Status = "blocked"
	// StatusIncomplete indicates the stack is missing PRs or has drafts.
	StatusIncomplete Status = "incomplete"
)

Jump to

Keyboard shortcuts

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