Keep worktree PR badges stable during refresh (#6397)
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
parent
5f995df942
commit
ef477199af
|
|
@ -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')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue