Documentation
¶
Overview ¶
Package merge provides functionality for merging stacked pull requests.
Index ¶
- Constants
- func Action(ctx context.Context, deps Deps, opts Options) error
- func AnalyzeMidStackScope(eng engine.Engine, plan *Plan, currentScope string) []string
- func CreateMergePlan(ctx context.Context, eng mergePlanEngine, splog output.Output, ...) (*Plan, *PlanValidation, error)
- func EnableAutoMergeForPR(ctx context.Context, deps Deps, prNumber git.PRNumber) error
- func Execute(ctx context.Context, deps Deps, opts ExecuteOptions) error
- func ExecuteInWorktree(ctx context.Context, deps Deps, opts ExecuteOptions, scope string, ...) (err error)
- func FormatMergePlan(plan *Plan, validation *PlanValidation) 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 context.Context, out output.Output, prompts handler.Prompter, ...) (github.MergeMethod, error)
- func GetPRNodeID(ctx context.Context, githubClient github.Client, prNumber git.PRNumber) (string, error)
- func HandlePostMerge(ctx context.Context, eng postMergeEngine, handler InteractiveHandler) error
- func IsSingleBranchLeafMerge(plan *Plan, graph *engine.StackGraph) bool
- func RunWizard(ctx context.Context, deps Deps, handler InteractiveHandler, opts WizardOptions) error
- type BranchMergeInfo
- type CIConfig
- 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 git.PRNumber, ...) (*WaitResult, error)
- type CIWaiterClient
- type CIWaiterOptions
- type ChecksStatus
- type CollectedBranches
- type Config
- type ConsolidateMergeExecutor
- type ConsolidationResult
- type CreatePlanOptions
- type Deps
- type DrainBranchPushedEvent
- type DrainOptions
- type DrainPRStartedEvent
- type DrainResult
- type DrainStoppedEvent
- type DrainSyncingEvent
- type Event
- type EventHandler
- type EventType
- type ExcludeReason
- type ExecuteOptions
- type InteractiveHandler
- type LocalCISearchResult
- type LocalCIValidator
- type MergeBranches
- type MergeMethodConfig
- type MergePROptions
- type MergePROutcome
- 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 MultiStacks
- type NullEventHandler
- type NullProgressHandler
- type Options
- type PRAlreadyMergedEvent
- type PRAutomergeEnabledEvent
- type PRCleanStatusRaceEvent
- type PRCleaner
- type PRCleanupConfig
- type PRCleanupResult
- type PRCleanupSource
- type PRContentGenerator
- type PREnablingAutomergeEvent
- type PRMergedEvent
- type PRMergingDirectlyEvent
- type PRWaitingForMergeEvent
- type PRWaitingForMergeableEvent
- type Phase
- type Plan
- type PlanStep
- type PlanValidation
- type PostMergeAction
- type PostMergeActionRequiredError
- type PostMergeCheckoutError
- type PostMergeSyncOptions
- type PostMergeSyncResult
- type ProgressEvent
- type ProgressHandler
- type Result
- type StepType
- type Strategy
- type StrategyChoice
- type WaitResult
- type WizardOptions
Constants ¶
const ( // DefaultMergeTimeout is the default timeout for waiting on a merge to complete DefaultMergeTimeout = 30 * time.Minute // DefaultMergePollInterval is the default interval between merge status checks DefaultMergePollInterval = 10 * time.Second )
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 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 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 EnableAutoMergeForPR ¶ added in v0.29.0
EnableAutoMergeForPR enables GitHub auto-merge on a PR using the configured merge method (prompting for one if none is configured).
func Execute ¶
func Execute(ctx context.Context, deps Deps, opts ExecuteOptions) error
Execute executes a validated merge plan step by step
func ExecuteInWorktree ¶
func ExecuteInWorktree(ctx context.Context, deps Deps, 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 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 ¶
func GetMergeMethod(ctx context.Context, out output.Output, prompts handler.Prompter, cfg MergeMethodConfig, githubClient github.Client) (github.MergeMethod, error)
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.
out reports the chosen method and prompts asks for one when several are allowed and the session is interactive.
func GetPRNodeID ¶ added in v0.29.0
func GetPRNodeID(ctx context.Context, githubClient github.Client, prNumber git.PRNumber) (string, error)
GetPRNodeID fetches the GraphQL node ID for a PR by number. The node ID is what the GraphQL merge and automerge operations address a PR by.
func HandlePostMerge ¶
func HandlePostMerge(ctx context.Context, eng postMergeEngine, 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 context.Context, deps Deps, 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 git.PRNumber
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 CIConfig ¶ added in v0.29.0
CIConfig is the resolved ci.* configuration the validator needs. The loaded repository config satisfies it; callers pass it in rather than the action loading config from disk.
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.
type CIWaiterClient ¶ added in v0.29.0
type CIWaiterClient interface {
github.ChecksReader
github.PRMerger
}
CIWaiterClient is the GitHub surface CIWaiter needs: polling checks and merging once they pass.
type CIWaiterOptions ¶
type CIWaiterOptions struct {
Client CIWaiterClient
Output output.Output
Timeout time.Duration // Default: 10 minutes
PollInterval time.Duration // Default: 15 seconds
RegistrationDelay time.Duration // Default: CIRegistrationDelay
}
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 MergeBranches
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 Config ¶ added in v0.30.1
type Config interface {
MergeMethodConfig
CIConfig
}
Config lists the configuration getters (and the one setter) merge uses: the repository merge method, read and persisted on first use, and the local CI command multi-stack shipping validates with. A nil Config behaves as if no configuration was loaded.
type ConsolidateMergeExecutor ¶
type ConsolidateMergeExecutor struct {
// contains filtered or unexported fields
}
ConsolidateMergeExecutor handles stack consolidation merging
func NewConsolidateMergeExecutor ¶
func NewConsolidateMergeExecutor(plan *Plan, engine mergeExecuteEngine, deps Deps) *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 Deps ¶ added in v0.30.1
type Deps struct {
// Engine is the full engine: merge plans, executes and cleans up across
// the whole stack graph — locking, PR info, restacks, worktrees, pushes —
// and hands the engine to the multi-stack worktree executor and stack
// discovery, which take engine.Engine too. A merge in a temporary
// worktree swaps in an engine rooted there.
Engine engine.Engine
Out output.Output
// GitHub returns the client, or nil when GitHub is unavailable. It is a
// function so the client is only built when merge actually needs it.
GitHub func() github.Client
// GitHubError explains why GitHub returned nil, when known. May be nil.
GitHubError func() error
// GHRunner runs the GraphQL queries merge and automerge go through.
GHRunner github.GitCommandRunner
// PRSync pushes metadata and refreshes the PRs of locked or closed
// branches.
PRSync actions.PRSync
Prompts handler.Prompter
// RepoRoot is where restack continuation state is persisted.
RepoRoot string
Config Config
// Sync is what the post-merge sync runs with.
Sync sync.Deps
// Submit is what drain publishes restacked branches with.
Submit submit.Deps
// Checkout is what the post-merge trunk checkout runs with.
Checkout checkout.Deps
}
Deps are the collaborators merge needs. Adapters build them from their own runtime state; the action never sees bootstrap types.
type DrainBranchPushedEvent ¶ added in v0.29.0
DrainBranchPushedEvent reports the result of publishing one restacked branch after a merge. Failed is set (with Err) when the update failed.
type DrainOptions ¶ added in v0.29.0
type DrainOptions struct {
// Plan is the bottom-up plan the caller showed and confirmed. Its
// BranchesToMerge are locked for the duration of the drain.
Plan *Plan
// TargetBranch and Scope select the stack to re-plan on each iteration.
TargetBranch string
Scope string
Force bool
// Limit caps the number of PRs to merge (0 = all).
Limit int
// MergeMethod is the resolved merge method used for every PR.
MergeMethod github.MergeMethod
}
DrainOptions configures Drain.
type DrainPRStartedEvent ¶ added in v0.29.0
DrainPRStartedEvent reports that drain is about to merge the next PR. Position is 1-based; Total is the number of PRs this drain targets.
type DrainResult ¶ added in v0.29.0
type DrainResult struct {
Merged int
}
DrainResult reports what Drain did.
func Drain ¶ added in v0.29.0
func Drain(ctx context.Context, deps Deps, opts DrainOptions, handler ProgressHandler) (DrainResult, error)
Drain merges the stack's PRs bottom-up, one at a time, waiting for each to land before moving on. After every merge it checks out trunk, syncs with a restack scoped to the remaining branches, and publishes those branches so the next PR sees its new base.
A restack conflict in a drain branch is a hard error; drain never enters the conflict workflow (see PostMergeSync). Branches are locked with LockReasonDraining for the duration and unlocked on return.
type DrainStoppedEvent ¶ added in v0.29.0
DrainStoppedEvent reports that drain stopped early because re-planning failed after at least one PR had merged (typically the stack is drained).
type DrainSyncingEvent ¶ added in v0.29.0
DrainSyncingEvent reports that drain is syncing trunk and restacking the remaining branches after a merge.
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 ExcludeReason ¶ added in v0.22.0
type ExcludeReason string
ExcludeReason says why a stack was left out of a multi-stack merge.
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)
LinearStacks bool // stack.shape == linear (from config)
ConsolidationResultFunc func(*ConsolidationResult) // Callback for consolidation results
MergeMethod github.MergeMethod // Optional: override merge method (empty = auto-detect/prompt)
CIRegistrationDelay time.Duration // Optional: override CIRegistrationDelay (0 = default)
}
ExecuteOptions contains options for executing a merge plan
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 MultiStacks // 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 engine.WorktreePath, 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 CIConfig, 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. A nil config yields an unconfigured validator.
func (*LocalCIValidator) IsConfigured ¶
func (v *LocalCIValidator) IsConfigured() bool
IsConfigured returns true if a CI command is configured
func (*LocalCIValidator) Validate ¶
func (v *LocalCIValidator) Validate(ctx context.Context, workdir engine.WorktreePath) error
Validate runs the CI command in the specified directory
type MergeBranches ¶ added in v0.22.0
type MergeBranches []BranchMergeInfo
MergeBranches is an ordered collection of branches to merge.
func (MergeBranches) AllAreLeaves ¶ added in v0.22.0
func (branches MergeBranches) AllAreLeaves(graph *engine.StackGraph) bool
AllAreLeaves reports whether every branch is a leaf in graph. Only leaves can be merged individually without orphaning or restacking children.
Branches missing from the graph count as non-leaves: if we can't verify a branch's structure, we don't allow individual merging.
func (MergeBranches) AnyHasChecks ¶ added in v0.22.0
func (branches MergeBranches) AnyHasChecks() bool
AnyHasChecks returns true if any branch has CI checks configured.
func (MergeBranches) Names ¶ added in v0.22.0
func (branches MergeBranches) Names() []string
Names returns the branch names in merge order.
type MergeMethodConfig ¶ added in v0.29.0
type MergeMethodConfig interface {
MergeMethod() github.MergeMethod
SetMergeMethod(method github.MergeMethod) error
}
MergeMethodConfig reads and persists the repository's merge.method setting. Callers pass the already-loaded repository config (Deps.Config); the action never loads config from disk itself.
type MergePROptions ¶ added in v0.29.0
type MergePROptions struct {
BranchName string
PRNumber git.PRNumber
MergeMethod github.MergeMethod
Wait bool // Block until the PR merges instead of returning after enabling automerge
}
MergePROptions describes a single PR merge.
type MergePROutcome ¶ added in v0.29.0
type MergePROutcome int
MergePROutcome represents the result of a MergePR attempt.
const ( // MergePRMerged means the PR was merged (directly or via wait). MergePRMerged MergePROutcome = iota // MergePRAutomergeEnabled means automerge was enabled (fire-and-forget). MergePRAutomergeEnabled )
func MergePR ¶ added in v0.29.0
func MergePR(ctx context.Context, deps Deps, opts MergePROptions, handler ProgressHandler) (MergePROutcome, error)
MergePR merges one PR: it resolves the PR's GraphQL node ID, then runs the 3-tier merge (direct merge → automerge → poll fallback) described on orchestrateMerge. Progress is reported through handler.
type MultiStackExcluded ¶
type MultiStackExcluded struct {
Stack MultiStackInfo
Reason ExcludeReason
}
MultiStackExcluded represents a stack that was not included in the merge
type MultiStackInfo ¶
MultiStackInfo represents a stack that can be merged in multi-stack mode. Stack discovery and its types live in stackview; these aliases keep the merge package's names.
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(deps Deps, worktreeEng engine.Engine, worktreePath engine.WorktreePath) *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 MultiStacks // Stacks that were successfully included
ExcludedStacks []MultiStackExcluded // Stacks that were excluded with reasons
PRNumber git.PRNumber // 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 context.Context, deps Deps, 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.
type MultiStackWorktreeResult ¶
type MultiStackWorktreeResult struct {
MergedStacks MultiStacks // Stacks that were successfully merged
ConflictStacks []MultiStackExcluded // Stacks that conflicted
WorktreePath engine.WorktreePath // 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 MultiStacks ¶ added in v0.22.0
MultiStacks is an ordered collection of independent stacks.
func DiscoverStacks ¶
func DiscoverStacks(ctx context.Context, eng engine.BranchReader) (MultiStacks, error)
DiscoverStacks returns all independent stacks rooted at trunk. Discovery lives in stackview so read-only consumers (API, shippable) need not depend on the merge package; this wrapper keeps merge's call sites unchanged.
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 NullProgressHandler ¶ added in v0.29.0
type NullProgressHandler struct{}
NullProgressHandler discards all progress events.
func (NullProgressHandler) OnProgress ¶ added in v0.29.0
func (NullProgressHandler) OnProgress(ProgressEvent)
OnProgress implements ProgressHandler.
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)
LinearStacks bool // stack.shape == linear (from config)
Handler EventHandler
MergeMethod github.MergeMethod // Optional: override merge method (empty = auto-detect/prompt)
}
Options contains options for the merge command
type PRAlreadyMergedEvent ¶ added in v0.29.0
PRAlreadyMergedEvent reports that the PR was already merged before any merge attempt was made.
type PRAutomergeEnabledEvent ¶ added in v0.29.0
PRAutomergeEnabledEvent reports that auto-merge was enabled.
type PRCleanStatusRaceEvent ¶ added in v0.29.0
PRCleanStatusRaceEvent reports that enabling auto-merge failed because the PR became ready in the meantime, so it will be merged directly.
type PRCleaner ¶
type PRCleaner struct {
// contains filtered or unexported fields
}
PRCleaner handles post-merge cleanup of individual PRs
func NewPRCleaner ¶
func NewPRCleaner(deps Deps, 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 git.PRNumber
// 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 []git.PRNumber // PR numbers that were closed
FailedPRs []git.PRNumber // PR numbers that failed to close
SkippedPRs []git.PRNumber // 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
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(ctx context.Context, branch engine.Branch) *git.StackDescription
Trunk() engine.Branch
}) *PRContentGenerator
NewPRContentGenerator creates a new PR content generator.
func (*PRContentGenerator) GenerateConsolidationPR ¶
func (g *PRContentGenerator) GenerateConsolidationPR(ctx context.Context, 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 PREnablingAutomergeEvent ¶ added in v0.29.0
type PREnablingAutomergeEvent struct {
PRNumber git.PRNumber
Method github.MergeMethod
}
PREnablingAutomergeEvent reports that auto-merge is being enabled.
type PRMergedEvent ¶ added in v0.29.0
PRMergedEvent reports that the PR merged. External is set when it was merged by someone else while stackit was waiting.
type PRMergingDirectlyEvent ¶ added in v0.29.0
type PRMergingDirectlyEvent struct {
PRNumber git.PRNumber
Method github.MergeMethod
MergeState string
AfterWaiting bool
}
PRMergingDirectlyEvent reports that the PR is being merged directly through the REST API. AfterWaiting is set when the PR only became mergeable after polling (auto-merge unavailable); MergeState is the state it reached.
type PRWaitingForMergeEvent ¶ added in v0.29.0
PRWaitingForMergeEvent reports that stackit is waiting for GitHub to merge the PR after enabling auto-merge.
type PRWaitingForMergeableEvent ¶ added in v0.29.0
PRWaitingForMergeableEvent reports that auto-merge is not enabled on the repository, so stackit is polling until the PR becomes mergeable.
type Plan ¶
type Plan struct {
Strategy Strategy
CurrentBranch string
BranchesToMerge MergeBranches // 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.
func (*Plan) BranchNames ¶ added in v0.19.2
BranchNames returns the names of all branches to be merged, in order.
type PlanStep ¶
type PlanStep struct {
StepType StepType
BranchName string
PRNumber git.PRNumber
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 PostMergeActionRequiredError ¶ added in v0.30.1
type PostMergeActionRequiredError struct {
Action PostMergeAction
}
PostMergeActionRequiredError is returned when post-merge action is needed
func (*PostMergeActionRequiredError) Error ¶ added in v0.30.1
func (e *PostMergeActionRequiredError) Error() string
type PostMergeCheckoutError ¶ added in v0.29.0
type PostMergeCheckoutError struct {
Err error
}
PostMergeCheckoutError is returned by PostMergeSync when trunk could not be checked out, so no sync was attempted. Callers typically render recovery instructions (stash or commit local changes) for this case.
func (*PostMergeCheckoutError) Error ¶ added in v0.29.0
func (e *PostMergeCheckoutError) Error() string
func (*PostMergeCheckoutError) Unwrap ¶ added in v0.29.0
func (e *PostMergeCheckoutError) Unwrap() error
type PostMergeSyncOptions ¶ added in v0.29.0
type PostMergeSyncOptions struct {
// RestackScope limits the restack to these branches (empty = sync default).
RestackScope []string
// OnTrunkCheckedOut, when set, is called after trunk is checked out and
// before sync runs, so adapters can surface worktree-switch directives in
// order.
OnTrunkCheckedOut func(result checkout.Result)
}
PostMergeSyncOptions configures PostMergeSync.
type PostMergeSyncResult ¶ added in v0.29.0
type PostMergeSyncResult struct {
// Summary is the sync summary; ConflictBranches lists restacks that were
// left unresolved.
Summary sync.Summary
}
PostMergeSyncResult reports what the post-merge sync did.
func PostMergeSync ¶ added in v0.29.0
func PostMergeSync(ctx context.Context, deps Deps, opts PostMergeSyncOptions, newSyncHandler func() sync.Handler) (PostMergeSyncResult, error)
PostMergeSync runs the follow-up after a PR lands: check out trunk, then sync with restack.
newSyncHandler is called only once trunk is checked out, so an adapter can defer starting a sync UI until there is a sync to show.
It never enters the conflict-resolution workflow, whatever the handler answers: that workflow detaches HEAD, and a merge command must never leave the user in detached HEAD. Restack conflicts are left in the returned summary for the caller to report or fail on.
type ProgressEvent ¶ added in v0.29.0
type ProgressEvent interface {
// contains filtered or unexported methods
}
ProgressEvent is a progress notification emitted while merging individual PRs (MergePR) or draining a stack (Drain). Adapters render these; the action never writes merge progress to the terminal itself.
type ProgressHandler ¶ added in v0.29.0
type ProgressHandler interface {
OnProgress(event ProgressEvent)
}
ProgressHandler receives progress events from MergePR and Drain.
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)
// Resolved configuration, supplied by the caller.
UndoStackDepth int // Maximum undo stack depth (undo.depth)
LinearStacks bool // stack.shape == linear
}
WizardOptions configures the interactive merge wizard
Source Files
¶
- ci_waiter.go
- cleanup.go
- consolidate.go
- deps.go
- drain.go
- execute.go
- execute_steps.go
- handler.go
- helpers.go
- interactive.go
- merge.go
- merge_pr.go
- multistack.go
- multistack_ci.go
- multistack_discover.go
- multistack_pr.go
- multistack_types.go
- multistack_worktree.go
- plan.go
- post_merge_sync.go
- pr_generator.go
- progress.go
- wizard.go
- worktree.go