fix(github): stop stale merged PRs from sticking in branch status
Branch PR status now resolves open PRs only, revalidates closed/merged associations on a discovery cadence, and clears authoritative empty results so the panel can self-heal without a manual refresh. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
This commit is contained in:
committed by
Cursor Agent
co-authored by
Serhii Dziupin
parent
6b1e677aaf
commit
962b016cbd
@@ -212,6 +212,11 @@ const findResolvedSiblingEntry = (
|
||||
if (entryKey === key || !entry.isInitialStatusResolved || !entry.status) {
|
||||
continue;
|
||||
}
|
||||
// Never seed a fresh key from a closed/merged association — that is what
|
||||
// made stale terminal PRs reappear after remote-key switches.
|
||||
if (isTerminalPrState(entry.status.pr?.state)) {
|
||||
continue;
|
||||
}
|
||||
const parsed = parseStatusKey(entryKey);
|
||||
if (!parsed
|
||||
|| parsed.runtimeKey !== target.runtimeKey
|
||||
@@ -359,15 +364,39 @@ const toPersistedEntry = (entry: PrStatusEntry): PersistedPrStatusEntry => ({
|
||||
resolvedRemoteName: entry.resolvedRemoteName ?? entry.status?.resolvedRemoteName ?? null,
|
||||
});
|
||||
|
||||
const hydrateEntry = (entry: PersistedPrStatusEntry | undefined): PrStatusEntry => ({
|
||||
...createEntry(),
|
||||
status: entry?.status ?? null,
|
||||
isInitialStatusResolved: entry?.isInitialStatusResolved ?? false,
|
||||
lastRefreshAt: entry?.lastRefreshAt ?? 0,
|
||||
lastDiscoveryPollAt: entry?.lastDiscoveryPollAt ?? 0,
|
||||
identity: entry?.identity ?? null,
|
||||
resolvedRemoteName: entry?.resolvedRemoteName ?? entry?.status?.resolvedRemoteName ?? null,
|
||||
});
|
||||
const stripTerminalPersistedStatus = (
|
||||
status: GitHubPullRequestStatus | null | undefined,
|
||||
): GitHubPullRequestStatus | null => {
|
||||
if (!status) {
|
||||
return null;
|
||||
}
|
||||
if (!isTerminalPrState(status.pr?.state)) {
|
||||
return status;
|
||||
}
|
||||
// Persisted closed/merged branch associations are not live authority. Keep
|
||||
// repo/remote continuity so refresh can resume without briefly showing the
|
||||
// stale terminal PR.
|
||||
return {
|
||||
...status,
|
||||
pr: null,
|
||||
checks: undefined,
|
||||
canMerge: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const hydrateEntry = (entry: PersistedPrStatusEntry | undefined): PrStatusEntry => {
|
||||
const status = stripTerminalPersistedStatus(entry?.status);
|
||||
const hadTerminalPr = Boolean(entry?.status?.pr) && !status?.pr;
|
||||
return {
|
||||
...createEntry(),
|
||||
status,
|
||||
isInitialStatusResolved: hadTerminalPr ? false : (entry?.isInitialStatusResolved ?? false),
|
||||
lastRefreshAt: entry?.lastRefreshAt ?? 0,
|
||||
lastDiscoveryPollAt: entry?.lastDiscoveryPollAt ?? 0,
|
||||
identity: entry?.identity ?? null,
|
||||
resolvedRemoteName: entry?.resolvedRemoteName ?? entry?.status?.resolvedRemoteName ?? null,
|
||||
};
|
||||
};
|
||||
|
||||
const boundEntries = (entries: Record<string, PrStatusEntry>): Record<string, PrStatusEntry> => {
|
||||
const all = Object.entries(entries);
|
||||
@@ -496,7 +525,11 @@ export const useGitHubPrStatusStore = create<GitHubPrStatusStore>()(
|
||||
}
|
||||
|
||||
const hasPr = Boolean(entry.status?.pr);
|
||||
if (!hasPr) {
|
||||
const isTerminal = isTerminalPrState(entry.status?.pr?.state);
|
||||
// Missing PR and terminal (closed/merged) PRs both need discovery:
|
||||
// a new open PR may exist for the same head, or the association may
|
||||
// need to clear to an authoritative empty result.
|
||||
if (!hasPr || isTerminal) {
|
||||
const now = Date.now();
|
||||
if (now - entry.lastDiscoveryPollAt < PR_DISCOVERY_INTERVAL_MS) {
|
||||
return;
|
||||
@@ -520,10 +553,6 @@ export const useGitHubPrStatusStore = create<GitHubPrStatusStore>()(
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTerminalPrState(entry.status?.pr?.state)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elapsed = Date.now() - entry.lastRefreshAt;
|
||||
const nextInterval = getOpenPrRefreshInterval(entry.status);
|
||||
if (elapsed < nextInterval) {
|
||||
@@ -850,6 +879,11 @@ export const useGitHubPrStatusStore = create<GitHubPrStatusStore>()(
|
||||
if (!identity?.directory || !identity.branch) {
|
||||
return false;
|
||||
}
|
||||
// Do not persist closed/merged branch associations — they become
|
||||
// permanently sticky without a discovery refresh after reload.
|
||||
if (isTerminalPrState(entry.status?.pr?.state)) {
|
||||
return false;
|
||||
}
|
||||
const freshness = Math.max(entry.lastRefreshAt, entry.lastDiscoveryPollAt);
|
||||
return freshness > 0 && Date.now() - freshness < PR_PERSIST_TTL_MS;
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user