Stack view shows "not ready" / "unable to merge as a stack" on approved mergeable PRs (stale stack UI cache)
- 主要言語
- Go
- スター
- 1.5k
- フォーク
- 70
- 平均マージ
- 1日 8時間
- マージ済み PR(30日)
- 7
説明
## Summary
The GitHub stack view (native stack feature, not CLI) shows "not ready" on some PRs in a 13-level stack, and displays "unable to merge as a stack" globally, even though every PR in the stack reports `mergeable=MERGEABLE`, `mergeStateStatus=CLEAN` (or `UNSTABLE`), `reviewDecision=APPROVED`, and all status checks passing via both REST and GraphQL APIs.
## Stack structure (anonymized)
```
base-branch
└── feat/base → PR #1 (base: base-branch) ← trunk base
└── feat/layer-2 → PR #2 (base: feat/base)
└── feat/layer-3 → PR #3 (base: feat/layer-2)
└── feat/layer-4 → PR #4 (base: feat/layer-3)
└── feat/layer-5 → PR #5 (base: feat/layer-4)
└── feat/layer-6 → PR #6 (base: feat/layer-5)
└── feat/layer-7 → PR #7 (base: feat/layer-6)
└── feat/layer-8 → PR #8 (base: feat/layer-7)
└── feat/layer-9 → PR #9 (base: feat/layer-8)
└── feat/layer-A → PR #10 (base: feat/layer-9)
└── feat/layer-B → PR #11 (base: feat/layer-A)
└── feat/layer-C → PR #12 (base: feat/layer-B)
└── feat/layer-D → PR #13 (base: feat/layer-C)
```
13 PRs in total. The bottom PR targets `base-branch`; each subsequent PR targets its predecessor's branch. All PRs are open, non-draft, created via `gh stack submit`.
## Environment
- `gh` 2.97.0
- `gh-stack` v0.1.0
- Repository: private, no branch protection, no repository rulesets, no merge queue, no CODEOWNERS.
- "Dismiss stale pull request approvals when new commits are pushed": disabled.
## Observed behavior
### In the GitHub stack UI (native stack view)
- Bottom 7 PRs (#1–#7): show **"Ready"**
- PR #8: shows **"Not ready"** (no tooltip / reason shown)
- PR #9: shows **"Blocked downstack"**
- PR #10: shows **"Not ready"** (no tooltip / reason shown)
- PRs #11–#13: show **"Blocked downstack"**
- At the top: global message **"Unable to merge as a stack"**
### Via the API (both REST and GraphQL, confirmed multiple times over several minutes)
Every PR in the stack (including #8 and #10) consistently reports:
| Field | Value |
|---|---|
| `mergeable` | `MERGEABLE` |
| `mergeStateStatus` | `CLEAN` (or `UNSTABLE` — only non-required checks pending like CodeRabbit) |
| `reviewDecision` | `APPROVED` (multiple approvals from different reviewers) |
| `statusCheckRollup.state` | `SUCCESS` |
| `isDraft` | `false` |
| `requested_reviewers` | `[]` (no pending reviewer requests) |
| No branch protection | (none exists on any branch in the stack) |
| No repository rulesets | (none exist) |
GraphQL query used:
```graphql
{
repository(owner: "O", name: "R") {
pullRequest(number: N) {
mergeable
mergeStateStatus
reviewDecision
isDraft
statusCheckRollup { state }
}
}
}
```
### Context about the "not ready" PRs (#8 and #10)
- Both are **history-import PRs** — they contain 500+ commits each (preserved full history of the imported repositories), adding ~48k lines across 180+ files.
- The remaining PRs are smaller (single-digit to low-double-digit commits).
- All PRs (including #8 and #10) were created via the same `gh stack submit` flow, all with the same review/check configuration.
- The status checks on #8 and #10 all show **green/success**. Only CodeRabbit (not required) shows as not completed.
## Attempted workaround: close + reopen the "not ready" PRs
We closed and reopened PR #8 (the first "not ready" PR in the stack) to force a full server-side recompute:
```
gh pr close 8 && gh pr reopen 8
```
**Result:**
- The individual PR returned to `mergeable=MERGEABLE, reviewDecision=APPROVED` correctly.
- The stack view took ~30 seconds to reload, but **the state did not change**: PR #8 remained "not ready", PR #9 remained "blocked downstack", and the global message stayed "unable to merge as a stack".
Close+reopen did **not** invalidate the stack view's cached state. The stack view appears to maintain its own independent cache that is not invalidated by PR state changes.
## Expected behavior
Given that:
1. All PRs are mergeable (no conflicts, `MERGEABLE`).
2. All PRs are approved (`APPROVED`).
3. All required status checks pass (`SUCCESS`).
4. No branch protection, rulesets, CODEOWNERS, or merge queue block merging.
5. Close+reopen did not help.
GitHub's native stack view should reflect the actual PR state and show all 13 PRs as **"Ready"**, with the **"Merge stack (13)"** option enabled and functional. A stale cached state rendering the stack unmergeable is a blocking UX bug.
## Related
- **#323** — "Can't merge a stacked PR with no clear reason (all PRs show mergeable)". Same class of bug: stack UI state differs from API state. In our case the stack never shows as mergeable at all (no attempt to merge fails — the UI never allows the attempt). We confirm the `MERGEABLE`/`CLEAN`/`APPROVED` symptom. Our close+reopen attempt did not resolve it, suggesting a different cache invalidation path.
コントリビューションガイド
調査の方向性
リポジトリのファイルやテストは指定されていません。まず GitHub のネイティブな stack ビューで 13 レベルの stack を再現し、表示される準備状態をレポートに記載された REST および GraphQL フィールドと比較してください。完了条件は、UI が承認済みでマージ可能な PRs を反映し、"Merge stack (13)" を有効にすることです。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- github
- 領域
- frontend
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 活発
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 45/100