mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 00:27:39 +00:00
fix(checks): scope foreground refreshes by provider
This commit is contained in:
@@ -134,7 +134,11 @@ import {
|
||||
shouldPollChecksPanelRuntimeSshStatus,
|
||||
type ChecksPanelGitStatusSnapshot
|
||||
} from './checks-panel-git-status-snapshot'
|
||||
import { resolveChecksPanelPRRefreshRequest } from './checks-panel-pr-refresh-request'
|
||||
import {
|
||||
getChecksPanelForegroundReviewEvidenceKey,
|
||||
resolveChecksPanelPRRefreshRequest,
|
||||
resolveChecksPanelReviewEvidenceProvider
|
||||
} from './checks-panel-pr-refresh-request'
|
||||
import { installWindowVisibilityInterval } from '@/lib/window-visibility-interval'
|
||||
import { useMountedRef } from '@/hooks/useMountedRef'
|
||||
import { callRuntimeRpc, getActiveRuntimeTarget } from '@/runtime/runtime-rpc-client'
|
||||
@@ -965,7 +969,22 @@ export default function ChecksPanel(): React.JSX.Element {
|
||||
hostedReviewCreation?.review?.number ??
|
||||
checksPanelReviewLookupResult.openReviewUrl ??
|
||||
'unknown'
|
||||
const unrenderedReviewEvidenceProvider = hostedReviewCreation?.provider ?? hostedReview?.provider
|
||||
const unrenderedReviewEvidenceProvider = resolveChecksPanelReviewEvidenceProvider({
|
||||
linkedGitHubPR: linkedPR,
|
||||
linkedGitLabMR,
|
||||
linkedBitbucketPR,
|
||||
linkedAzureDevOpsPR,
|
||||
linkedGiteaPR,
|
||||
eligibilityProvider: hostedReviewCreation?.provider,
|
||||
cachedProvider: hostedReview?.provider
|
||||
})
|
||||
const foregroundReviewEvidenceKey = getChecksPanelForegroundReviewEvidenceKey({
|
||||
refreshContextKey,
|
||||
reviewEvidenceIdentity: unrenderedReviewEvidenceIdentity,
|
||||
reviewEvidenceProvider: unrenderedReviewEvidenceProvider,
|
||||
hasUnrenderedReviewEvidence,
|
||||
isGitHubReviewContext
|
||||
})
|
||||
// Confirmed readiness from the last eligibility snapshot, not live canCreate (which would be circular and flap during transient failures).
|
||||
const hardErrorObservedAt =
|
||||
isGitHubReviewContext && hardRefreshError && hardRefreshError.contextKey === panelContextKey
|
||||
@@ -1359,7 +1378,7 @@ export default function ChecksPanel(): React.JSX.Element {
|
||||
}, [agentComposerState?.commentResolution, stateRequestKey])
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasUnrenderedReviewEvidence || !isPanelVisible) {
|
||||
if (foregroundReviewEvidenceKey === null || !isPanelVisible) {
|
||||
foregroundedUnrenderedReviewKeyRef.current = null
|
||||
}
|
||||
if (isPanelVisible && repo && !isFolder && branch) {
|
||||
@@ -1376,17 +1395,17 @@ export default function ChecksPanel(): React.JSX.Element {
|
||||
})
|
||||
// Why: the gh-based refresh coordinator is GitHub-only; running it elsewhere gave a spurious gh_unavailable error hiding a valid composer.
|
||||
if (activeWorktreeId && isGitHubReviewContext) {
|
||||
const evidenceKey = `${refreshContextKey}::${unrenderedReviewEvidenceIdentity}`
|
||||
const refreshRequest = resolveChecksPanelPRRefreshRequest({
|
||||
cachedHasPR: prCachedHasPR,
|
||||
cachedFetchedAt: prFetchedAt ?? null,
|
||||
panelVisibleSince: panelVisibleSinceRef.current,
|
||||
hasUnrenderedReviewEvidence,
|
||||
reviewEvidenceProvider: unrenderedReviewEvidenceProvider,
|
||||
hasRequestedForegroundRefresh: foregroundedUnrenderedReviewKeyRef.current === evidenceKey
|
||||
hasUnrenderedReviewEvidence: foregroundReviewEvidenceKey !== null,
|
||||
hasRequestedForegroundRefresh:
|
||||
foregroundReviewEvidenceKey !== null &&
|
||||
foregroundedUnrenderedReviewKeyRef.current === foregroundReviewEvidenceKey
|
||||
})
|
||||
if (refreshRequest.reason === 'active' && hasUnrenderedReviewEvidence) {
|
||||
foregroundedUnrenderedReviewKeyRef.current = evidenceKey
|
||||
if (refreshRequest.reason === 'active' && foregroundReviewEvidenceKey !== null) {
|
||||
foregroundedUnrenderedReviewKeyRef.current = foregroundReviewEvidenceKey
|
||||
}
|
||||
enqueueGitHubPRRefresh(activeWorktreeId, refreshRequest.reason, refreshRequest.priority)
|
||||
}
|
||||
@@ -1397,7 +1416,7 @@ export default function ChecksPanel(): React.JSX.Element {
|
||||
enqueueGitHubPRRefresh,
|
||||
fallbackGitHubPRNumber,
|
||||
fetchHostedReviewForBranch,
|
||||
hasUnrenderedReviewEvidence,
|
||||
foregroundReviewEvidenceKey,
|
||||
isFolder,
|
||||
isGitHubReviewContext,
|
||||
isPanelVisible,
|
||||
@@ -1409,9 +1428,6 @@ export default function ChecksPanel(): React.JSX.Element {
|
||||
linkedPR,
|
||||
prCachedHasPR,
|
||||
prFetchedAt,
|
||||
refreshContextKey,
|
||||
unrenderedReviewEvidenceIdentity,
|
||||
unrenderedReviewEvidenceProvider,
|
||||
repo
|
||||
])
|
||||
|
||||
|
||||
@@ -1,5 +1,73 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { resolveChecksPanelPRRefreshRequest } from './checks-panel-pr-refresh-request'
|
||||
import {
|
||||
getChecksPanelForegroundReviewEvidenceKey,
|
||||
resolveChecksPanelPRRefreshRequest,
|
||||
resolveChecksPanelReviewEvidenceProvider
|
||||
} from './checks-panel-pr-refresh-request'
|
||||
|
||||
describe('resolveChecksPanelReviewEvidenceProvider', () => {
|
||||
const noLinkedReviews = {
|
||||
linkedGitHubPR: null,
|
||||
linkedGitLabMR: null,
|
||||
linkedBitbucketPR: null,
|
||||
linkedAzureDevOpsPR: null,
|
||||
linkedGiteaPR: null
|
||||
}
|
||||
|
||||
it.each([
|
||||
['linkedGitHubPR', 'github'],
|
||||
['linkedGitLabMR', 'gitlab'],
|
||||
['linkedBitbucketPR', 'bitbucket'],
|
||||
['linkedAzureDevOpsPR', 'azure-devops'],
|
||||
['linkedGiteaPR', 'gitea']
|
||||
] as const)('lets an explicit %s link outrank stale cached metadata', (linkedField, provider) => {
|
||||
expect(
|
||||
resolveChecksPanelReviewEvidenceProvider({
|
||||
...noLinkedReviews,
|
||||
[linkedField]: 42,
|
||||
cachedProvider: 'unsupported'
|
||||
})
|
||||
).toBe(provider)
|
||||
})
|
||||
|
||||
it('uses eligibility before cached provider metadata when no review is linked', () => {
|
||||
expect(
|
||||
resolveChecksPanelReviewEvidenceProvider({
|
||||
...noLinkedReviews,
|
||||
eligibilityProvider: 'bitbucket',
|
||||
cachedProvider: 'gitlab'
|
||||
})
|
||||
).toBe('bitbucket')
|
||||
})
|
||||
})
|
||||
|
||||
describe('getChecksPanelForegroundReviewEvidenceKey', () => {
|
||||
const input = {
|
||||
refreshContextKey: 'worktree::cache::branch',
|
||||
reviewEvidenceIdentity: 42,
|
||||
hasUnrenderedReviewEvidence: true,
|
||||
isGitHubReviewContext: true
|
||||
} as const
|
||||
|
||||
it('keeps optimistic and confirmed GitHub evidence on one request key', () => {
|
||||
const optimisticKey = getChecksPanelForegroundReviewEvidenceKey(input)
|
||||
const confirmedKey = getChecksPanelForegroundReviewEvidenceKey({
|
||||
...input,
|
||||
reviewEvidenceProvider: 'github'
|
||||
})
|
||||
expect(optimisticKey).toBe('worktree::cache::branch::github::42')
|
||||
expect(confirmedKey).toBe(optimisticKey)
|
||||
})
|
||||
|
||||
it('clears the request key when evidence switches to another provider', () => {
|
||||
expect(
|
||||
getChecksPanelForegroundReviewEvidenceKey({
|
||||
...input,
|
||||
reviewEvidenceProvider: 'gitlab'
|
||||
})
|
||||
).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('resolveChecksPanelPRRefreshRequest', () => {
|
||||
it('uses an active refresh for a cached miss from before the checks panel became visible', () => {
|
||||
@@ -56,18 +124,6 @@ describe('resolveChecksPanelPRRefreshRequest', () => {
|
||||
).toEqual({ reason: 'swr', priority: 30 })
|
||||
})
|
||||
|
||||
it('does not promote non-GitHub review evidence into an active GitHub lookup', () => {
|
||||
expect(
|
||||
resolveChecksPanelPRRefreshRequest({
|
||||
cachedHasPR: null,
|
||||
cachedFetchedAt: null,
|
||||
panelVisibleSince: 200,
|
||||
hasUnrenderedReviewEvidence: true,
|
||||
reviewEvidenceProvider: 'gitlab'
|
||||
})
|
||||
).toEqual({ reason: 'swr', priority: 30 })
|
||||
})
|
||||
|
||||
it('keeps populated or unknown cache entries on the background path', () => {
|
||||
expect(
|
||||
resolveChecksPanelPRRefreshRequest({
|
||||
|
||||
@@ -7,7 +7,6 @@ type ChecksPanelPRRefreshRequestInput = {
|
||||
panelVisibleSince: number | null
|
||||
// A known-but-unrendered review needs one foreground lookup to resolve its transient state.
|
||||
hasUnrenderedReviewEvidence?: boolean
|
||||
reviewEvidenceProvider?: HostedReviewProvider
|
||||
hasRequestedForegroundRefresh?: boolean
|
||||
}
|
||||
|
||||
@@ -16,6 +15,58 @@ type ChecksPanelPRRefreshRequest = {
|
||||
priority: number
|
||||
}
|
||||
|
||||
type ChecksPanelReviewEvidenceProviderInput = {
|
||||
linkedGitHubPR: number | null
|
||||
linkedGitLabMR: number | null
|
||||
linkedBitbucketPR: number | null
|
||||
linkedAzureDevOpsPR: number | null
|
||||
linkedGiteaPR: number | null
|
||||
eligibilityProvider?: HostedReviewProvider | undefined
|
||||
cachedProvider?: HostedReviewProvider | undefined
|
||||
}
|
||||
|
||||
type ChecksPanelForegroundReviewEvidenceKeyInput = {
|
||||
refreshContextKey: string
|
||||
reviewEvidenceIdentity: number | string
|
||||
reviewEvidenceProvider?: HostedReviewProvider | undefined
|
||||
hasUnrenderedReviewEvidence: boolean
|
||||
isGitHubReviewContext: boolean
|
||||
}
|
||||
|
||||
export function resolveChecksPanelReviewEvidenceProvider(
|
||||
input: ChecksPanelReviewEvidenceProviderInput
|
||||
): HostedReviewProvider | undefined {
|
||||
if (input.linkedGitHubPR !== null) {
|
||||
return 'github'
|
||||
}
|
||||
if (input.linkedGitLabMR !== null) {
|
||||
return 'gitlab'
|
||||
}
|
||||
if (input.linkedBitbucketPR !== null) {
|
||||
return 'bitbucket'
|
||||
}
|
||||
if (input.linkedAzureDevOpsPR !== null) {
|
||||
return 'azure-devops'
|
||||
}
|
||||
if (input.linkedGiteaPR !== null) {
|
||||
return 'gitea'
|
||||
}
|
||||
return input.eligibilityProvider ?? input.cachedProvider
|
||||
}
|
||||
|
||||
export function getChecksPanelForegroundReviewEvidenceKey(
|
||||
input: ChecksPanelForegroundReviewEvidenceKeyInput
|
||||
): string | null {
|
||||
if (
|
||||
!input.hasUnrenderedReviewEvidence ||
|
||||
!input.isGitHubReviewContext ||
|
||||
(input.reviewEvidenceProvider !== undefined && input.reviewEvidenceProvider !== 'github')
|
||||
) {
|
||||
return null
|
||||
}
|
||||
return `${input.refreshContextKey}::github::${input.reviewEvidenceIdentity}`
|
||||
}
|
||||
|
||||
export function resolveChecksPanelPRRefreshRequest(
|
||||
input: ChecksPanelPRRefreshRequestInput
|
||||
): ChecksPanelPRRefreshRequest {
|
||||
@@ -25,9 +76,7 @@ export function resolveChecksPanelPRRefreshRequest(
|
||||
input.panelVisibleSince !== null &&
|
||||
input.cachedFetchedAt < input.panelVisibleSince
|
||||
const unresolvedEvidenceNeedsForeground =
|
||||
input.hasUnrenderedReviewEvidence &&
|
||||
input.cachedHasPR !== true &&
|
||||
(input.reviewEvidenceProvider === undefined || input.reviewEvidenceProvider === 'github')
|
||||
input.hasUnrenderedReviewEvidence && input.cachedHasPR !== true
|
||||
|
||||
if (
|
||||
!input.hasRequestedForegroundRefresh &&
|
||||
|
||||
Reference in New Issue
Block a user