Stale or missing `refs/pull/N/merge` on stacked PRs silently prevents all `pull_request` workflows from running
- 主要語言
- Go
- 星號
- 1.5k
- 分支
- 70
- 平均合併
- 1 天 8 小時
- 30 天內合併 PR
- 7
描述
### 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`.
貢獻指南
研究方向
先從 gh stack 對堆疊 PR 的行為著手:其 refs/pull/N/merge ref 缺失或已過期,然後使用 git merge-tree 將其與實際的 base 和 head commit 進行比較。檢查 pull_request 和 pull_request_target workflow 路徑,以及 #229 中的討論。完成標準是:merge ref 在 push 時重新計算,或 PR 明確顯示其已過期的 merge 狀態,而不是顯示空的檢查清單。
由索引模型根據 Issue 內容生成。
評估
- 技術堆疊
- git, github, go
- 領域
- ci-cd, cli, devtools
- Issue 類型
- 缺陷
- 難度
- 4/5
- 預估耗時
- 3-5 天
- 活躍度
- 活躍
- 描述清晰度
- 基本清楚
- 新手友好度
- 35/100