Documentation
¶
Overview ¶
Package merge provides functionality for merging stacked pull requests.
Index ¶
- Constants
- func Action(ctx *app.Context, opts Options) error
- func AllBranchesAreLeaves(graph *engine.StackGraph, branches []BranchMergeInfo) bool
- func AnalyzeMidStackScope(eng engine.Engine, plan *Plan, currentScope string) []string
- func AnyPRHasChecks(branches []BranchMergeInfo) bool
- func CreateMergePlan(ctx context.Context, eng mergePlanEngine, splog output.Output, ...) (*Plan, *PlanValidation, error)
- func Execute(ctx *app.Context, eng mergeExecuteEngine, opts ExecuteOptions) error
- func ExecuteInWorktree(ctx *app.Context, eng mergeExecuteEngine, opts ExecuteOptions, scope string, ...) (err error)
- func FormatMergePlan(plan *Plan, validation *PlanValidation) string
- func FormatStackLabel(stack MultiStackInfo) string
- func FormatValidationError(errors, warnings []string) error
- func FormatValidationSection(result *strings.Builder, validation *PlanValidation)
- func GenerateMultiStackBranchName() string
- func GetAvailableScopes(eng engine.Engine) []string
- func GetMergeMethod(ctx *app.Context, githubClient github.Client) (github.MergeMethod, error)
- func HandlePostMerge(ctx *app.Context, handler InteractiveHandler) error
- func IsSingleBranchLeafMerge(plan *Plan, graph *engine.StackGraph) bool
- func RunWizard(ctx *app.Context, handler InteractiveHandler, opts WizardOptions) error
- type BranchMergeInfo
- type CIWaiter
- func (w *CIWaiter) SetProgressHandler(handler EventHandler, stepIndex int)
- func (w *CIWaiter) WaitAndMerge(ctx context.Context, branchName string, pr *github.PullRequestInfo, ...) error
- func (w *CIWaiter) WaitForChecks(ctx context.Context, branchName string, prNumber int, expectChecks bool) (*WaitResult, error)
- type CIWaiterOptions
- type ChecksStatus
- type CollectedBranches
- type ConsolidateMergeExecutor
- type ConsolidationResult
- type CreatePlanOptions
- type Event
- type EventHandler
- type EventType
- type ExecuteOptions
- type IndividualMergeStatus
- type InteractiveHandler
- type LocalCISearchResult
- type LocalCIValidator
- type MergeType
- type MultiStackExcluded
- type MultiStackInfo
- type MultiStackOptions
- type MultiStackPRCreator
- func (p *MultiStackPRCreator) BuildStackMetadata(included []MultiStackInfo) pr.StackMetadata
- func (p *MultiStackPRCreator) CreateAndPushBranch(ctx context.Context, branchName string) error
- func (p *MultiStackPRCreator) CreatePR(ctx context.Context, branchName string, included []MultiStackInfo, ...) (*github.PullRequestInfo, error)
- func (p *MultiStackPRCreator) EnableAutoMerge(ctx context.Context, pr *github.PullRequestInfo, commitBody string) error
- func (p *MultiStackPRCreator) WaitAndMerge(ctx context.Context, branchName string, pr *github.PullRequestInfo, ...) error
- type MultiStackResult
- type MultiStackWorktreeExecutor
- type MultiStackWorktreeResult
- type NullEventHandler
- type Options
- type PRCleaner
- type PRCleanupConfig
- type PRCleanupResult
- type PRCleanupSource
- type PRContentGenerator
- type Phase
- type Plan
- type PlanStep
- type PlanValidation
- type PostMergeAction
- type PostMergeActionRequired
- type Result
- type StepType
- type Strategy
- type StrategyChoice
- type WaitResult
- type WizardOptions
Constants ¶
const ( // DefaultCITimeout is the default timeout for waiting on CI checks DefaultCITimeout = 10 * time.Minute // DefaultCIPollInterval is the default interval between CI status checks DefaultCIPollInterval = 15 * time.Second // CIRegistrationDelay is the delay to allow CI checks to register after push CIRegistrationDelay = 5 * time.Second )
Timing constants for CI waiting
Variables ¶
This section is empty.
Functions ¶
func AllBranchesAreLeaves ¶
func AllBranchesAreLeaves(graph *engine.StackGraph, branches []BranchMergeInfo) bool
AllBranchesAreLeaves checks if all branches in the plan have no children in the stack graph.
Why this matters: Only leaf branches (those with no children) can be merged individually without affecting other branches. Merging a non-leaf would orphan its children or require restacking them, making individual merge inappropriate. This check enables offering the "merge individually" option when all selected branches are independent leaves.
Note: Branches not found in the graph (nil node) are treated as non-leaves and cause the function to return false. This is a fail-safe behavior - if we can't verify a branch's structure, we don't allow individual merging.
func AnalyzeMidStackScope ¶
AnalyzeMidStackScope checks if user is mid-stack in a scope and returns any upstack branches that are in the same scope (won't be merged).
func AnyPRHasChecks ¶
func AnyPRHasChecks(branches []BranchMergeInfo) bool
AnyPRHasChecks returns true if any of the given branches have CI checks configured
func CreateMergePlan ¶
func CreateMergePlan(ctx context.Context, eng mergePlanEngine, splog output.Output, githubClient github.Client, opts CreatePlanOptions) (*Plan, *PlanValidation, error)
CreateMergePlan analyzes the current state and builds a merge plan. This is a convenience wrapper that calls CollectMergeBranches + BuildMergePlan.
func Execute ¶
func Execute(ctx *app.Context, eng mergeExecuteEngine, opts ExecuteOptions) error
Execute executes a validated merge plan step by step
func ExecuteInWorktree ¶
func ExecuteInWorktree(ctx *app.Context, eng mergeExecuteEngine, opts ExecuteOptions, scope string, targetBranch string) (err error)
ExecuteInWorktree executes the merge plan in a temporary worktree
func FormatMergePlan ¶
func FormatMergePlan(plan *Plan, validation *PlanValidation) string
FormatMergePlan returns a human-readable representation of a merge plan
func FormatStackLabel ¶
func FormatStackLabel(stack MultiStackInfo) string
FormatStackLabel creates a display label for a stack
func FormatValidationError ¶
FormatValidationError creates a detailed error message including validation errors and warnings.
func FormatValidationSection ¶
func FormatValidationSection(result *strings.Builder, validation *PlanValidation)
FormatValidationSection writes validation errors, warnings, and info to the builder. Used by all plan format functions to avoid duplication.
func GenerateMultiStackBranchName ¶
func GenerateMultiStackBranchName() string
GenerateMultiStackBranchName creates a unique branch name for the multi-stack PR
func GetAvailableScopes ¶
GetAvailableScopes returns all unique non-empty scopes in the repository
func GetMergeMethod ¶
GetMergeMethod returns the merge method to use for PR merges. If not configured, it prompts the user to select one and saves it to config.
func HandlePostMerge ¶
func HandlePostMerge(ctx *app.Context, handler InteractiveHandler) error
HandlePostMerge handles the post-merge follow-up workflow.
func IsSingleBranchLeafMerge ¶
func IsSingleBranchLeafMerge(plan *Plan, graph *engine.StackGraph) bool
IsSingleBranchLeafMerge returns true if this is a simple merge of a single leaf branch (no children, no upstack work needed).
Why this matters: Single leaf branches with no upstack work represent the simplest merge case. We can offer a streamlined confirmation UX (just "Proceed?") instead of showing the full plan, since there are no complex steps or dependencies to review.
func RunWizard ¶
func RunWizard(ctx *app.Context, handler InteractiveHandler, opts WizardOptions) error
RunWizard executes the interactive merge wizard. It guides the user through selecting what to merge, the strategy, and then executes the merge.
Types ¶
type BranchMergeInfo ¶
type BranchMergeInfo struct {
BranchName string
PRNumber int
PRURL string
IsDraft bool
ChecksStatus ChecksStatus
MatchesRemote bool
}
BranchMergeInfo contains info about a branch to be merged
func (BranchMergeInfo) HasChecks ¶
func (b BranchMergeInfo) HasChecks() bool
HasChecks returns true if the branch has CI checks configured
type CIWaiter ¶
type CIWaiter struct {
// contains filtered or unexported fields
}
CIWaiter handles waiting for CI checks to pass on GitHub PRs. It extracts the common CI polling logic used by both consolidation and step execution.
func NewCIWaiter ¶
func NewCIWaiter(opts CIWaiterOptions) *CIWaiter
NewCIWaiter creates a new CIWaiter with the given options
func (*CIWaiter) SetProgressHandler ¶
func (w *CIWaiter) SetProgressHandler(handler EventHandler, stepIndex int)
SetProgressHandler sets the handler and step index for progress reporting
func (*CIWaiter) WaitAndMerge ¶
func (w *CIWaiter) WaitAndMerge(ctx context.Context, branchName string, pr *github.PullRequestInfo, expectChecks bool, mergeOpts github.MergePROptions) error
WaitAndMerge waits for CI checks to pass and then merges the PR. This is used for consolidation PRs that should be auto-merged.
func (*CIWaiter) WaitForChecks ¶
func (w *CIWaiter) WaitForChecks(ctx context.Context, branchName string, prNumber int, expectChecks bool) (*WaitResult, error)
WaitForChecks waits for CI checks to pass on a branch. Returns an error if checks fail, timeout, or context is canceled.
type CIWaiterOptions ¶
type CIWaiterOptions struct {
Client github.Client
Output output.Output
Timeout time.Duration // Default: 10 minutes
PollInterval time.Duration // Default: 15 seconds
}
CIWaiterOptions configures a CIWaiter
type ChecksStatus ¶
type ChecksStatus string
ChecksStatus represents the CI check status for a PR
const ( // ChecksPassing indicates all checks passed ChecksPassing ChecksStatus = "PASSING" // ChecksFailing indicates at least one check failed ChecksFailing ChecksStatus = "FAILING" // ChecksPending indicates checks are still running ChecksPending ChecksStatus = "PENDING" // ChecksNone indicates no checks are configured ChecksNone ChecksStatus = "NONE" )
type CollectedBranches ¶
type CollectedBranches struct {
BranchesToMerge []BranchMergeInfo
UpstackBranches []string
CurrentBranch string
Validation *PlanValidation
}
CollectedBranches holds the intermediate result of branch collection. This allows the wizard to collect branches once, then build plans with different strategies.
func CollectMergeBranches ¶
func CollectMergeBranches(ctx context.Context, eng mergePlanEngine, splog output.Output, githubClient github.Client, opts CreatePlanOptions) (*CollectedBranches, error)
CollectMergeBranches gathers branches, metadata, CI status, and validation without building strategy-specific steps. This is the expensive part that calls GitHub APIs and should only run once per wizard session.
type ConsolidateMergeExecutor ¶
type ConsolidateMergeExecutor struct {
// contains filtered or unexported fields
}
ConsolidateMergeExecutor handles stack consolidation merging
func NewConsolidateMergeExecutor ¶
func NewConsolidateMergeExecutor(plan *Plan, engine mergeExecuteEngine, ctx *app.Context) *ConsolidateMergeExecutor
NewConsolidateMergeExecutor creates a new consolidation executor
func (*ConsolidateMergeExecutor) Execute ¶
func (c *ConsolidateMergeExecutor) Execute(ctx context.Context, opts ExecuteOptions) (*ConsolidationResult, error)
Execute performs stack consolidation merging
func (*ConsolidateMergeExecutor) SetProgressHandler ¶
func (c *ConsolidateMergeExecutor) SetProgressHandler(handler EventHandler, stepIndex int)
SetProgressHandler sets the progress handler and step index for reporting
type ConsolidationResult ¶
ConsolidationResult contains information about a completed consolidation
type CreatePlanOptions ¶
type CreatePlanOptions struct {
Strategy Strategy
Force bool
Scope string
TargetBranch string // Optional branch to merge from (instead of current)
Wait bool // Whether to wait for CI/merge (applies to consolidate strategy)
}
CreatePlanOptions contains options for creating a merge plan
type Event ¶
type Event struct {
Phase Phase
Type EventType
StepIndex int
Step *PlanStep
Message string
Error error
// Waiting-specific fields
Elapsed time.Duration
Timeout time.Duration
Checks []github.CheckDetail
// Estimate fields
EstimatedDuration time.Duration
}
Event represents a merge progress event
type EventHandler ¶
type EventHandler interface {
// Start is called when the merge plan is ready to execute.
// The plan contains all steps that will be executed.
Start(plan *Plan)
// EmitEvent sends a progress event to the handler.
// Called for each step transition (started, completed, failed, waiting).
// May be called concurrently from multiple goroutines.
EmitEvent(event Event)
// Complete is called when the merge operation is finished.
// Result contains success status and any consolidation result.
Complete(result *Result)
// Cleanup ensures terminal state is restored.
// Should be called via defer after creating the handler.
// No-op for non-TTY handlers.
Cleanup()
}
EventHandler is the interface for reporting merge progress using events. This is the recommended interface for new handler implementations.
Lifecycle:
- Start() is called once when the merge plan is ready
- EmitEvent() is called for each step (started, completed, failed, waiting)
- Complete() is called once when the operation finishes
- Cleanup() should be called via defer to restore terminal state
Thread safety: All methods may be called from different goroutines. Implementations should handle synchronization internally.
type ExecuteOptions ¶
type ExecuteOptions struct {
Plan *Plan
Strategy Strategy
Force bool
Wait bool // Whether to wait for CI/merge (applies to consolidate)
Handler EventHandler // Optional progress handler
UndoStackDepth int // Maximum undo stack depth (from config)
ConsolidationResultFunc func(*ConsolidationResult) // Callback for consolidation results
MergeMethod github.MergeMethod // Optional: override merge method (empty = auto-detect/prompt)
}
ExecuteOptions contains options for executing a merge plan
type IndividualMergeStatus ¶
type IndividualMergeStatus struct {
CanMerge bool // True if all PRs can be merged individually
MergeableState map[string]bool // Per-branch mergeable state (true = mergeable)
BlockingReason string // Reason why individual merge is blocked (if any)
}
IndividualMergeStatus contains the result of checking if individual merge is possible
func CanMergeIndividually ¶
func CanMergeIndividually(ctx context.Context, gitRunner git.Runner, githubClient github.Client, graph *engine.StackGraph, branches []BranchMergeInfo) (*IndividualMergeStatus, error)
CanMergeIndividually checks if all PRs can be merged individually by verifying: 1. All branches are leaf branches (no children) 2. All PRs have GitHub mergeable state = MERGEABLE (no conflicts with trunk)
Returns the status including per-branch mergeable states for display purposes. Returns error if GitHub API call fails; check CanMerge field and BlockingReason for results.
type InteractiveHandler ¶
type InteractiveHandler interface {
EventHandler
// IsInteractive returns true if this handler supports interactive prompts.
// Non-interactive handlers (e.g., SimpleMergeEventHandler) return false,
// and their prompt methods will return errors.
// Check this before calling prompt methods to provide better error messages.
IsInteractive() bool
// PromptMergeType asks user what to merge (this/scope/stacks).
// Called at the start of the wizard when no merge target is pre-selected.
// canMergeThisBranch indicates if "This branch" is a valid option (false on trunk or empty worktree).
// Returns ErrCanceled if user cancels.
PromptMergeType(canMergeThisBranch bool, availableScopes []string, availableStacks []MultiStackInfo) (MergeType, error)
// PromptScope asks user to select a scope from available options.
// Called when user selects MergeTypeScope.
// Returns ErrCanceled if user cancels.
PromptScope(availableScopes []string) (string, error)
// PromptStacks asks user to select stacks (multi-select with ordering).
// Returns selected stack root names in priority order.
// Called when user selects MergeTypeStacks.
// Returns ErrCanceled if user cancels.
PromptStacks(availableStacks []MultiStackInfo) ([]string, error)
// PromptStrategy asks user to select merge strategy.
// plan provides context (branch count, etc.) for display.
// recommended is the suggested default based on stack size.
// Returns ErrCanceled if user cancels.
PromptStrategy(plan *Plan, recommended Strategy) (StrategyChoice, error)
// PromptConfirm asks user to confirm an action.
// Returns ErrCanceled if user cancels.
PromptConfirm(message string, defaultYes bool) (bool, error)
// ShowPlan displays the merge plan for review.
// This is informational - no return value needed.
// Called before prompting for strategy selection.
ShowPlan(plan *Plan, validation *PlanValidation)
// ShowMidStackWarning displays a warning when user is mid-stack in a scope.
// Called when branches above the current branch share the same scope.
ShowMidStackWarning(scope string, upstackBranchesInScope []string)
// PromptPostMerge asks user what to do after merge completes.
// Called after successful merge execution.
// Returns ErrCanceled if user cancels (treated as "done").
PromptPostMerge(hasUncommittedChanges bool, trunkName string) (PostMergeAction, error)
// PromptSimpleMergeConfirm shows a simplified confirmation for single-branch merges.
// This provides a cleaner UX than ShowPlan + PromptConfirm for simple cases.
// Returns true to proceed, false to cancel.
PromptSimpleMergeConfirm(branch BranchMergeInfo, baseBranch string) (bool, error)
}
InteractiveHandler extends EventHandler with interactive prompt capabilities. This allows the action layer to request user input without depending on specific UI implementations (TUI, CLI, etc.).
Implementations should handle TUI lifecycle (pause/resume) internally when showing prompts to avoid conflicts with progress display.
Error handling: Prompt methods should return sterrors.ErrCanceled when the user cancels (e.g., Ctrl+C, Escape). Other errors indicate actual failures.
type LocalCISearchResult ¶
type LocalCISearchResult struct {
WorkingStacks []MultiStackInfo // Stacks that pass CI together
FailedStacks []MultiStackExcluded // Stacks that failed CI
}
LocalCISearchResult contains the result of binary search for working stacks
func FindLargestWorkingSet ¶
func FindLargestWorkingSet( ctx context.Context, validator *LocalCIValidator, executor *MultiStackWorktreeExecutor, worktreeEng engine.Engine, worktreePath string, stacks []MultiStackInfo, ) (*LocalCISearchResult, error)
FindLargestWorkingSet finds the maximum subset of stacks that pass CI. It uses a greedy approach: try adding stacks one by one, keeping those that pass.
type LocalCIValidator ¶
type LocalCIValidator struct {
Command string
Timeout time.Duration
// contains filtered or unexported fields
}
LocalCIValidator runs local CI validation on merged code
func NewLocalCIValidator ¶
func NewLocalCIValidator(cfg config.Configurer, out output.Output) *LocalCIValidator
NewLocalCIValidator creates a new local CI validator from config. Uses the unified ci.command config, with fallback to combine.ciCommand for backwards compatibility.
func (*LocalCIValidator) IsConfigured ¶
func (v *LocalCIValidator) IsConfigured() bool
IsConfigured returns true if a CI command is configured
type MultiStackExcluded ¶
type MultiStackExcluded struct {
Stack MultiStackInfo
Reason string // "conflict" | "ci_failure"
}
MultiStackExcluded represents a stack that was not included in the merge
type MultiStackInfo ¶
type MultiStackInfo struct {
RootBranch string // Stack root branch name (direct child of trunk)
AllBranches []string // All branches in the stack (root to tip, in order)
PRCount int // Number of PRs in this stack
Scope string // Stack scope if any
}
MultiStackInfo represents a stack that can be merged in multi-stack mode
func DiscoverStacks ¶
func DiscoverStacks(eng engine.BranchReader) ([]MultiStackInfo, error)
DiscoverStacks returns all independent stacks rooted at trunk. Each stack is represented by its root branch (direct child of trunk) and includes all branches in the stack in topological order.
func DiscoverStacksWithSort ¶
func DiscoverStacksWithSort(eng engine.BranchReader, strategy engine.SortStrategy) ([]MultiStackInfo, error)
DiscoverStacksWithSort is like DiscoverStacks but allows specifying the sort strategy. Use SortStrategySmart to match the ordering of `stackit log`.
func FilterStacks ¶
func FilterStacks(stacks []MultiStackInfo, selectedRoots []string) []MultiStackInfo
FilterStacks filters stacks based on selected root branch names. If selectedRoots is empty, returns all stacks. The returned stacks maintain the order of selectedRoots (priority order).
type MultiStackOptions ¶
type MultiStackOptions struct {
SelectedStacks []string // Stack roots selected by user (skips picker if provided)
SkipLocalCI bool // Skip local CI validation
Wait bool // Wait for CI and auto-merge
}
MultiStackOptions contains options specific to multi-stack merge
type MultiStackPRCreator ¶
type MultiStackPRCreator struct {
// contains filtered or unexported fields
}
MultiStackPRCreator handles creating the multi-stack PR
func NewMultiStackPRCreator ¶
func NewMultiStackPRCreator(ctx *app.Context, worktreeEng engine.Engine, worktreePath string) *MultiStackPRCreator
NewMultiStackPRCreator creates a new PR creator for multi-stack merge
func (*MultiStackPRCreator) BuildStackMetadata ¶
func (p *MultiStackPRCreator) BuildStackMetadata(included []MultiStackInfo) pr.StackMetadata
BuildStackMetadata builds stack trailer metadata for the included multi-stack branches.
func (*MultiStackPRCreator) CreateAndPushBranch ¶
func (p *MultiStackPRCreator) CreateAndPushBranch(ctx context.Context, branchName string) error
CreateAndPushBranch creates a named branch at the current HEAD and pushes it
func (*MultiStackPRCreator) CreatePR ¶
func (p *MultiStackPRCreator) CreatePR(ctx context.Context, branchName string, included []MultiStackInfo, excluded []MultiStackExcluded) (*github.PullRequestInfo, error)
CreatePR creates the multi-stack pull request
func (*MultiStackPRCreator) EnableAutoMerge ¶
func (p *MultiStackPRCreator) EnableAutoMerge(ctx context.Context, pr *github.PullRequestInfo, commitBody string) error
EnableAutoMerge enables GitHub auto-merge for a multi-stack PR.
func (*MultiStackPRCreator) WaitAndMerge ¶
func (p *MultiStackPRCreator) WaitAndMerge(ctx context.Context, branchName string, pr *github.PullRequestInfo, commitBody string) error
WaitAndMerge waits for CI to pass and auto-merges the PR
type MultiStackResult ¶
type MultiStackResult struct {
IncludedStacks []MultiStackInfo // Stacks that were successfully included
ExcludedStacks []MultiStackExcluded // Stacks that were excluded with reasons
PRNumber int // Created PR number
PRURL string // Created PR URL
BranchName string // Consolidation branch name
}
MultiStackResult contains the result of a multi-stack merge operation
func ExecuteMultiStack ¶
func ExecuteMultiStack(ctx *app.Context, opts MultiStackOptions) (*MultiStackResult, error)
ExecuteMultiStack performs the multi-stack merge operation. It merges multiple independent stacks into a single consolidated branch, handling conflicts by skipping entire stacks that conflict.
type MultiStackWorktreeExecutor ¶
type MultiStackWorktreeExecutor struct {
// contains filtered or unexported fields
}
MultiStackWorktreeExecutor handles merging stacks in a worktree
func NewMultiStackWorktreeExecutor ¶
func NewMultiStackWorktreeExecutor(eng engine.Engine, out output.Output) *MultiStackWorktreeExecutor
NewMultiStackWorktreeExecutor creates a new worktree executor for multi-stack merge
func (*MultiStackWorktreeExecutor) ExecuteInWorktree ¶
func (w *MultiStackWorktreeExecutor) ExecuteInWorktree(ctx context.Context, stacks []MultiStackInfo) (*MultiStackWorktreeResult, error)
ExecuteInWorktree creates a worktree at trunk and attempts to merge all stacks. It first tries a global octopus merge (all branches from all stacks in one commit). If that fails due to conflicts, it falls back to per-stack merging to identify which stacks conflict.
func (*MultiStackWorktreeExecutor) ResetToTrunk ¶
ResetToTrunk resets the worktree to trunk, discarding all merges. This is used by binary search to try different combinations.
type MultiStackWorktreeResult ¶
type MultiStackWorktreeResult struct {
MergedStacks []MultiStackInfo // Stacks that were successfully merged
ConflictStacks []MultiStackExcluded // Stacks that conflicted
WorktreePath string // Path to the worktree
WorktreeEngine engine.Engine // Engine for the worktree
Cleanup func() // Function to clean up the worktree
}
MultiStackWorktreeResult contains the result of merging stacks in a worktree
type NullEventHandler ¶
type NullEventHandler struct{}
NullEventHandler is a no-op EventHandler for testing or when output is not needed
func (*NullEventHandler) Cleanup ¶
func (h *NullEventHandler) Cleanup()
Cleanup implements EventHandler.
func (*NullEventHandler) Complete ¶
func (h *NullEventHandler) Complete(_ *Result)
Complete implements EventHandler.
func (*NullEventHandler) EmitEvent ¶
func (h *NullEventHandler) EmitEvent(_ Event)
EmitEvent implements EventHandler.
func (*NullEventHandler) Start ¶
func (h *NullEventHandler) Start(_ *Plan)
Start implements EventHandler.
type Options ¶
type Options struct {
DryRun bool
Confirm bool
Strategy Strategy
Force bool
Wait bool // Whether to wait for CI/merge (applies to consolidate)
Scope string
TargetBranch string
Plan *Plan // Optional pre-calculated plan
UndoStackDepth int // Maximum undo stack depth (from config)
Handler EventHandler
MergeMethod github.MergeMethod // Optional: override merge method (empty = auto-detect/prompt)
}
Options contains options for the merge command
type PRCleaner ¶
type PRCleaner struct {
// contains filtered or unexported fields
}
PRCleaner handles post-merge cleanup of individual PRs
func NewPRCleaner ¶
func NewPRCleaner(ctx *app.Context, eng prCleanupEngine, config PRCleanupConfig) *PRCleaner
NewPRCleaner creates a new PR cleaner
func (*PRCleaner) CleanupBranches ¶
func (c *PRCleaner) CleanupBranches(ctx context.Context, branchNames []string) PRCleanupResult
CleanupBranches closes PRs for the given branch names and updates their bodies with a footer
func (*PRCleaner) LogResult ¶
func (c *PRCleaner) LogResult(result PRCleanupResult)
LogResult logs the cleanup result to output
type PRCleanupConfig ¶
type PRCleanupConfig struct {
// Source identifies the cleanup source for footer text
Source PRCleanupSource
// ConsolidationPRNumber is the PR number of the consolidation PR
ConsolidationPRNumber int
// UserName is the username to include in the footer (optional)
UserName string
}
PRCleanupConfig configures the post-merge PR cleanup behavior
type PRCleanupResult ¶
type PRCleanupResult struct {
ClosedPRs []int // PR numbers that were closed
FailedPRs []int // PR numbers that failed to close
SkippedPRs []int // PR numbers that were already closed
}
PRCleanupResult contains the results of PR cleanup
func (PRCleanupResult) ClosedCount ¶
func (r PRCleanupResult) ClosedCount() int
ClosedCount returns the number of PRs that were closed
func (PRCleanupResult) FailedCount ¶
func (r PRCleanupResult) FailedCount() int
FailedCount returns the number of PRs that failed to close
func (PRCleanupResult) SkippedCount ¶
func (r PRCleanupResult) SkippedCount() int
SkippedCount returns the number of PRs that were skipped (already closed)
type PRCleanupSource ¶
type PRCleanupSource string
PRCleanupSource identifies how a consolidation happened (for footer text)
const ( // CleanupSourceConsolidate is used when consolidating a single stack CleanupSourceConsolidate PRCleanupSource = "consolidation" // CleanupSourceMultiStack is used when consolidating multiple stacks CleanupSourceMultiStack PRCleanupSource = "multi-stack consolidation" )
type PRContentGenerator ¶
type PRContentGenerator struct {
// contains filtered or unexported fields
}
PRContentGenerator handles PR title and body generation for merge PRs.
func NewPRContentGenerator ¶
func NewPRContentGenerator(engine interface {
GetBranch(name string) engine.Branch
GetScope(branch engine.Branch) engine.Scope
GetStackDescription(branch engine.Branch) *git.StackDescription
Trunk() engine.Branch
}) *PRContentGenerator
NewPRContentGenerator creates a new PR content generator.
func (*PRContentGenerator) GenerateConsolidationPR ¶
func (g *PRContentGenerator) GenerateConsolidationPR(branches []BranchMergeInfo) pr.Content
GenerateConsolidationPR generates PR content for stack consolidation.
func (*PRContentGenerator) GenerateMultiStackPR ¶
func (g *PRContentGenerator) GenerateMultiStackPR(included []MultiStackInfo, excluded []MultiStackExcluded) pr.Content
GenerateMultiStackPR generates PR content for multi-stack merges.
type Plan ¶
type Plan struct {
Strategy Strategy
CurrentBranch string
BranchesToMerge []BranchMergeInfo // Branches that will be merged (bottom to top)
UpstackBranches []string // Branches above current that will be restacked
Steps []PlanStep // Ordered steps to execute
Warnings []string // Non-blocking warnings
Infos []string // Informational messages
CreatedAt time.Time
}
Plan is the complete plan for a merge operation
func BuildMergePlan ¶
func BuildMergePlan(collected *CollectedBranches, strategy Strategy, wait bool) *Plan
BuildMergePlan builds a Plan with strategy-specific steps from collected branch data. This is the cheap part that only does in-memory computation.
type PlanStep ¶
type PlanStep struct {
StepType StepType
BranchName string
PRNumber int
Description string // Human-readable description for display
WaitTimeout time.Duration // Timeout for waiting steps (e.g., CI checks)
ExpectChecks bool // Whether we expect CI checks to be present
}
PlanStep represents a single step in the merge plan
type PlanValidation ¶
type PlanValidation struct {
Valid bool
Errors []string // Blocking errors
Warnings []string // Non-blocking warnings
Infos []string // Informational messages
}
PlanValidation contains validation results
type PostMergeAction ¶
type PostMergeAction string
PostMergeAction represents a follow-up action after merge
const ( PostMergeSyncTrunk PostMergeAction = "sync-trunk" // Switch to trunk and sync PostMergeDone PostMergeAction = "done" // No follow-up action )
PostMergeAction constants
type PostMergeActionRequired ¶
type PostMergeActionRequired struct {
Action PostMergeAction
}
PostMergeActionRequired is returned when post-merge action is needed
func (*PostMergeActionRequired) Error ¶
func (e *PostMergeActionRequired) Error() string
type Result ¶
type Result struct {
Success bool
ConsolidationResult *ConsolidationResult
Error error
}
Result contains the final result of a merge operation
type StepType ¶
type StepType string
StepType represents the type of step in a merge plan
const ( // StepMergePR represents merging a PR StepMergePR StepType = "MERGE_PR" // StepRestack represents restacking a branch onto its parent StepRestack StepType = "RESTACK" // StepDeleteBranch represents deleting a local branch StepDeleteBranch StepType = "DELETE_BRANCH" // StepUpdatePRBase represents updating a PR's base branch StepUpdatePRBase StepType = "UPDATE_PR_BASE" // StepPullTrunk represents pulling the trunk branch StepPullTrunk StepType = "PULL_TRUNK" // StepWaitCI represents waiting for CI checks to complete StepWaitCI StepType = "WAIT_CI" // StepConsolidate represents consolidating the entire stack into a single PR StepConsolidate StepType = "CONSOLIDATE" )
type Strategy ¶
type Strategy string
Strategy defines how PRs in the stack should be merged
func DetermineRecommendedStrategy ¶
DetermineRecommendedStrategy returns the recommended strategy based on stack size. - 1-2 branches: bottom-up (merge one at a time) - 3+ branches: ship (atomic merge)
type StrategyChoice ¶
type StrategyChoice struct {
Strategy Strategy
Wait bool // Whether to wait for CI (consolidate strategy only)
}
StrategyChoice contains the user's strategy selection and related options
type WaitResult ¶
type WaitResult struct {
Passed bool
MaxDuration time.Duration // Maximum duration of any check (for estimating future runs)
}
WaitResult contains the result of waiting for CI
type WizardOptions ¶
type WizardOptions struct {
DryRun bool // If true, show plan but don't execute
Force bool // Skip validation checks
Scope string // Pre-selected scope (empty = prompt or use current branch)
TargetBranch string // Pre-selected target branch (empty = current branch)
Strategy Strategy // Pre-selected strategy (empty = prompt)
Wait bool // Pre-selected wait option (for consolidate)
}
WizardOptions configures the interactive merge wizard