Keep worktree PR badges stable during refresh (#6397)

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Brennan Benson 2026-06-25 19:23:40 -07:00 committed by GitHub
parent 5f995df942
commit ef477199af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 200 additions and 9 deletions

View File

@ -668,4 +668,173 @@ describe('WorktreeCard linked PR display', () => {
expect(markup).not.toContain('Branch')
expect(markup).not.toContain('lucide-git-branch')
})
it('keeps the detailed right-side PR badge during a transient hosted-review miss', async () => {
settings = { compactWorktreeCards: false, experimentalNewWorktreeCardStyle: false }
worktreeCardProperties = ['pr']
hostedReviewCache = {
'local::repo-1::feature/local-branch': {
data: null,
fetchedAt: 100
}
}
prCache = {
'repo-1::feature/local-branch': {
data: makePRInfo({
number: 6340,
title: 'Remove split terminal from onboarding checklist',
state: 'open',
checksStatus: 'success'
}),
fetchedAt: 200
}
}
const { default: WorktreeCard } = await import('./WorktreeCard')
const markup = renderWorktreeCardMarkup(
<WorktreeCard
worktree={makeWorktree({ linkedPR: null })}
repo={makeRepo()}
isActive={false}
/>
)
expect(markup).toContain('Linked PR #6340')
expect(markup).not.toContain('Linked PR #456')
})
it('keeps the detailed PR badge when a transient miss still has an older review hint', async () => {
settings = { compactWorktreeCards: false, experimentalNewWorktreeCardStyle: false }
worktreeCardProperties = ['pr']
hostedReviewCache = {
'local::repo-1::feature/local-branch': {
data: null,
fetchedAt: 100,
linkedReviewHintKey: 'github:999'
}
}
prCache = {
'repo-1::feature/local-branch': {
data: makePRInfo({
number: 6340,
title: 'Remove split terminal from onboarding checklist',
state: 'open',
checksStatus: 'success'
}),
fetchedAt: 200
}
}
const { default: WorktreeCard } = await import('./WorktreeCard')
const markup = renderWorktreeCardMarkup(
<WorktreeCard
worktree={makeWorktree({ linkedPR: null })}
repo={makeRepo()}
isActive={false}
/>
)
expect(markup).toContain('Linked PR #6340')
expect(markup).not.toContain('Linked PR #456')
})
it('keeps durable non-GitHub linked review metadata ahead of branch PR cache', async () => {
settings = { compactWorktreeCards: false, experimentalNewWorktreeCardStyle: false }
worktreeCardProperties = ['pr']
hostedReviewCache = {
'local::repo-1::feature/local-branch': {
data: null,
fetchedAt: 100
}
}
prCache = {
'repo-1::feature/local-branch': {
data: makePRInfo({
number: 6340,
title: 'Remove split terminal from onboarding checklist',
state: 'open',
checksStatus: 'success'
}),
fetchedAt: 200
}
}
const { default: WorktreeCard } = await import('./WorktreeCard')
const markup = renderWorktreeCardMarkup(
<WorktreeCard
worktree={makeWorktree({ linkedGitLabMR: 77 })}
repo={makeRepo()}
isActive={false}
/>
)
expect(markup).toContain('Linked MR #77')
expect(markup).not.toContain('Linked PR #6340')
})
it('does not resurrect an older PR cache entry after a newer hosted-review miss', async () => {
settings = { compactWorktreeCards: false, experimentalNewWorktreeCardStyle: false }
worktreeCardProperties = ['pr']
hostedReviewCache = {
'local::repo-1::feature/local-branch': {
data: null,
fetchedAt: 200
}
}
prCache = {
'repo-1::feature/local-branch': {
data: makePRInfo({
number: 6340,
title: 'Remove split terminal from onboarding checklist',
state: 'open',
checksStatus: 'success'
}),
fetchedAt: 100
}
}
const { default: WorktreeCard } = await import('./WorktreeCard')
const markup = renderWorktreeCardMarkup(
<WorktreeCard
worktree={makeWorktree({ linkedPR: null })}
repo={makeRepo()}
isActive={false}
/>
)
expect(markup).not.toContain('Linked PR #6340')
})
it('does not resurrect PR cache on the same millisecond as a hosted-review miss', async () => {
settings = { compactWorktreeCards: false, experimentalNewWorktreeCardStyle: false }
worktreeCardProperties = ['pr']
hostedReviewCache = {
'local::repo-1::feature/local-branch': {
data: null,
fetchedAt: 200
}
}
prCache = {
'repo-1::feature/local-branch': {
data: makePRInfo({
number: 6340,
title: 'Remove split terminal from onboarding checklist',
state: 'open',
checksStatus: 'success'
}),
fetchedAt: 200
}
}
const { default: WorktreeCard } = await import('./WorktreeCard')
const markup = renderWorktreeCardMarkup(
<WorktreeCard
worktree={makeWorktree({ linkedPR: null })}
repo={makeRepo()}
isActive={false}
/>
)
expect(markup).not.toContain('Linked PR #6340')
})
})

View File

@ -441,26 +441,48 @@ const WorktreeCard = React.memo(function WorktreeCard({
const hostedReview: HostedReviewInfo | null | undefined =
hostedReviewEntry !== undefined ? hostedReviewEntry.data : undefined
// Why: ChecksPanel can discover a branch PR before hosted-review metadata
// warms. The sidebar status slot should not fall back to "branch" while
// the branch PR cache already knows the review state.
const cachedBranchReview =
hostedReview === undefined && prCacheEntry?.data
? hostedReviewInfoFromGitHubPRInfo(prCacheEntry.data)
: hostedReview
const linkedGitHubPR = worktree.linkedPR ?? null
const linkedGitLabMR = worktree.linkedGitLabMR ?? null
const linkedBitbucketPR = worktree.linkedBitbucketPR ?? null
const linkedAzureDevOpsPR = worktree.linkedAzureDevOpsPR ?? null
const linkedGiteaPR = worktree.linkedGiteaPR ?? null
const hasNonGitHubLinkedReview =
linkedGitLabMR !== null ||
linkedBitbucketPR !== null ||
linkedAzureDevOpsPR !== null ||
linkedGiteaPR !== null
const hasLinkedReview =
linkedGitHubPR !== null ||
linkedGitLabMR !== null ||
linkedBitbucketPR !== null ||
linkedAzureDevOpsPR !== null ||
linkedGiteaPR !== null
// Why: ChecksPanel can discover a branch PR before hosted-review metadata
// warms, and transient older hosted-review misses can race with that cache.
// Newer hosted-review misses still win so stale PR cache cannot resurrect.
const cachedBranchPR = prCacheEntry?.data
const cachedBranchPRFetchedAt = prCacheEntry?.fetchedAt
const useCachedBranchReview =
cachedBranchPR !== undefined &&
cachedBranchPR !== null &&
!hasNonGitHubLinkedReview &&
(hostedReview === undefined ||
(hostedReview === null &&
cachedBranchPRFetchedAt !== undefined &&
cachedBranchPRFetchedAt > (hostedReviewEntry?.fetchedAt ?? 0)))
const cachedBranchReview = useCachedBranchReview
? hostedReviewInfoFromGitHubPRInfo(cachedBranchPR)
: hostedReview
const prDisplay = getWorktreeCardPrDisplay(
cachedBranchReview,
worktree.linkedPR,
linkedGitHubPR,
linkedGitLabMR,
linkedBitbucketPR,
linkedAzureDevOpsPR,
linkedGiteaPR,
{
reviewHintKey: hostedReviewEntry?.linkedReviewHintKey ?? (prCacheEntry?.data ? '' : undefined)
reviewHintKey:
useCachedBranchReview && !hasLinkedReview ? '' : hostedReviewEntry?.linkedReviewHintKey
}
)
const issue: IssueInfo | null | undefined = worktree.linkedIssue