github / github/gh-stack

Stale or missing `refs/pull/N/merge` on stacked PRs silently prevents all `pull_request` workflows from running

Open
#319 3 comments 1 reaction 0 assignees View on GitHub
bug topic: stale refs
Dominant language
Go
Stars
1.5k
Forks
70
Avg merge
1d 8h
Merged PRs (30d)
7

Description

### What happened

Three PRs in a 10-PR stack stopped running CI entirely. Not failing, not skipped: the check runs simply never get created, so the PRs look like CI has not started yet and stay that way indefinitely. `pull_request_target` workflows keep running on every push, which makes the PRs look half-alive and hides the problem.

The common factor is `refs/pull/N/merge`. `pull_request` workflows run against that ref, and on the affected PRs it is either missing or pinned to superseded commits:

| PR | position in stack | `refs/pull/N/merge` | mergeable | `pull_request` CI |
|----|-------------------|---------------------|-----------|-------------------|
| A | below the wedge | present, current | MERGEABLE | runs, green |
| B | wedge | missing | CONFLICTING | none for ~2 days |
| C | above B | stale, superseded parents | CONFLICTING | none |
| D | above C | stale, superseded parents | CONFLICTING | none |

```
PR C merge ref parents: 46c51a0a7 e1ca4188f <- both superseded
actual base/head: eb03b5605 6bc00ac9c

PR D merge ref parents: e1ca4188f d90f608e5 <- both superseded
actual base/head: 6bc00ac9c f8dbef22c
```

B, C and D each have a head that is a strict descendant of its base, so merging is a fast-forward and `git merge-tree` reports zero conflicts. The CONFLICTING state is phantom, and appears to be the same stale merge computation (see discussion #229).

The code and the runners are both fine: a `pull_request_target` labeler ran on every SHA, and `workflow_dispatch` runs of the same three workflows against the same branches all pass. It is specifically the merge-ref-backed `pull_request` path that is dead.

The failure is silent. A red X is actionable, but an empty check list is indistinguishable from "queued", so a PR can sit for days appearing to wait on CI when nothing will ever run. We only found it by comparing check-run names across sibling PRs in the same stack. Any repo with required status checks would block forever with no indication why.

### Expected

Either the merge ref is recomputed on push so `pull_request` workflows run, or the PR surfaces that its merge state is stale instead of rendering an empty check list.

### Recovery attempts, all blocked

- Pushing new commits, five times, no recompute
- Close and reopen, which deleted the merge ref instead of rebuilding it
- Retarget the base away and back: `422 Cannot change the base branch because the pull request is part of a stack`
- `gh stack unstack`: `Unstacking not allowed: Pull requests ... cannot be removed from this stack`, naming the 13 merged members

Stack membership blocks the base fix, and merged members block removing membership, so there is no way out from the client side.

### Environment

`gh` 2.68.1, `gh stack` v0.0.8. A stack of 10 open PRs on top of 13 merged ones, trunk `dev`.

Contributor guide

Open the contributing guide

Research direction

Start with the gh stack behavior for a stacked PR whose refs/pull/N/merge ref is missing or stale, and compare it with the actual base and head commits using git merge-tree. Check the pull_request and pull_request_target workflow paths and the discussion in #229. Done means the merge ref is recomputed on push or the PR clearly exposes its stale merge state instead of showing an empty check list.

Written by the indexing model from the issue text.

Assessment

Tech stack
git, github, go
Domain
ci-cd, cli, devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.