Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Repo Assist] Fix gh stack add: use last active branch index for top-of-stack check - #21

Draft
github-actions[bot] wants to merge 1 commit into
mainfrom
repo-assist/fix-add-merged-top-check-2026-04-25-af04bc8cfd077670
Draft

github-actions[bot] wants to merge 1 commit into
mainfrom
repo-assist/fix-add-merged-top-check-2026-04-25-af04bc8cfd077670

Conversation

@github-actions

Copy link
Copy Markdown

πŸ€– This is an automated pull request from Repo Assist, an AI assistant.

Summary

Two related bugs in gh stack add's middle-of-stack guard:

Bug 1 β€” Blocked from adding at last active branch when merged branches sit above it

Before: With trunk β†’ a β†’ b(merged) and on branch a:

βœ— can only add branches on top of the stack; run `gh stack top` to switch to "b"

b is already merged β€” switching to it and adding makes no sense.

After: Allowed. a is the last active branch, so adding on top of it is correct.

Bug 2 β€” Not blocked when on a merged branch that is the last overall branch

Before: With trunk β†’ a β†’ b(merged) and on branch b:

  • No error shown; a new branch would be created from the merged branch's position.

After: Blocked with a message pointing to a (the last active branch).

Root Cause

The guard compared idx against len(s.Branches)-1 (absolute last branch index), which is wrong when the last branch is merged.

Fix

Compute lastActiveIdx β€” the index of the last non-merged branch β€” and use it for both the guard condition and the error message.

lastActiveIdx := len(s.Branches) - 1
for i := len(s.Branches) - 1; i >= 0; i-- {
    if !s.Branches[i].IsMerged() {
        lastActiveIdx = i
        break
    }
}

if idx >= 0 && (s.Branches[idx].IsMerged() || idx < lastActiveIdx) {
    cfg.Errorf("can only add branches on top of the stack; run `%s` to switch to %q",
        cfg.ColorCyan("gh stack top"), s.Branches[lastActiveIdx].Branch)
    return ErrInvalidArgs
}

Note on queued branches

IsQueued() is a transient field populated by syncStackPRs, which runAdd does not call. Queued branches are therefore treated the same as active branches in this check. This is documented in a code comment.

Tests Added

  • TestAdd_AllowedOnLastActiveBranchWithMergedAbove: verifies bug 1 is fixed
  • TestAdd_BlockedOnMergedBranch: verifies bug 2 is fixed; also asserts the error message names the correct last active branch

All existing TestAdd_* tests continue to pass with the new logic (verified by manual trace).

Test Status

Tests could not be executed locally due to Go toolchain version requirements (go.mod requires go 1.25.7) and network restrictions. CI (test.yml) will run the full test suite. The change is a targeted two-line condition replacement with a supporting loop; all edge cases are traced against the existing test scenarios above.

Generated by 🌈 Repo Assist, see workflow run. Learn more.

Warning

⚠️ Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • sum.golang.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "sum.golang.org"

See Network Configuration for more information.

Generated by 🌈 Repo Assist, see workflow run. Learn more.

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@11c9a2c442e519ff2b427bf58679f5a525353f76

Previously, the middle-of-stack guard compared idx against
len(s.Branches)-1 (the absolute last branch), which caused two bugs:

1. Blocked when on the last ACTIVE branch if merged branches sit above it.
   Example: trunk -> a -> b(merged), user on a β†’ wrongly blocked with
   "switch to b" (a merged branch).

2. Allowed adding from a MERGED branch that happened to be last.
   Example: trunk -> a -> b(merged), user on b β†’ not blocked, leading
   to a new branch created from a merged-branch position.

Fix: compute lastActiveIdx (the index of the last non-merged branch)
and use it for both the guard and the error message. The error message
now points to the correct active branch instead of potentially a merged
one.

Note: IsQueued() is transient (set only by syncStackPRs, which runAdd
does not call), so only IsMerged() (persisted) is checked here.

Two new tests cover both scenarios.

Co-authored-by: Copilot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automation bug Something isn't working repo-assist

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants