mirror of
https://github.com/stablyai/orca.git
synced 2026-10-14 00:02:42 +00:00
Preserve checks cache on refresh failures
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -103,4 +103,13 @@ describe('getPRChecks', () => {
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it('throws when both check-runs and gh pr checks fail', async () => {
|
||||
getOwnerRepoMock.mockResolvedValueOnce({ owner: 'acme', repo: 'widgets' })
|
||||
ghExecFileAsyncMock
|
||||
.mockRejectedValueOnce(new Error('gh: No commit found for SHA: stale-head (HTTP 422)'))
|
||||
.mockRejectedValueOnce(new Error('rate limited'))
|
||||
|
||||
await expect(getPRChecks('/repo-root', 42, 'stale-head')).rejects.toThrow('rate limited')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1232,7 +1232,7 @@ export async function getPRChecks(
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('getPRChecks failed:', err)
|
||||
return []
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -579,9 +579,15 @@ export async function getWorkItemDetails(
|
||||
// Promise.all above, so there's no ordering requirement between them.
|
||||
const [mentionParticipants, checks] = await Promise.all([
|
||||
getMentionParticipants(repoPath, item, comments, participants),
|
||||
shas?.headSha
|
||||
(shas?.headSha
|
||||
? getPRChecks(repoPath, item.number, shas.headSha)
|
||||
: getPRChecks(repoPath, item.number)
|
||||
).catch((err) => {
|
||||
// Why: details can still render body/comments/files when check fetching
|
||||
// is rate-limited or temporarily unavailable.
|
||||
console.warn('Failed to fetch PR checks for work item details:', err)
|
||||
return []
|
||||
})
|
||||
])
|
||||
|
||||
return {
|
||||
|
||||
@@ -227,6 +227,62 @@ describe('createGitHubSlice.fetchPRChecks', () => {
|
||||
noCache: true
|
||||
})
|
||||
})
|
||||
|
||||
it('preserves cached checks when the checks IPC fails', async () => {
|
||||
const store = createTestStore()
|
||||
const repoPath = '/repo'
|
||||
const branch = 'feature/test'
|
||||
const checksCacheKey = `${repoPath}::pr-checks::12`
|
||||
const cachedChecks = [
|
||||
{ name: 'build', status: 'completed', conclusion: 'failure', url: null } as const
|
||||
]
|
||||
|
||||
store.setState({
|
||||
checksCache: {
|
||||
[checksCacheKey]: {
|
||||
data: cachedChecks,
|
||||
fetchedAt: 1,
|
||||
headSha: 'abc123head'
|
||||
}
|
||||
}
|
||||
} as unknown as Partial<AppState>)
|
||||
mockApi.gh.prChecks.mockRejectedValueOnce(new Error('rate limited'))
|
||||
|
||||
await expect(
|
||||
store.getState().fetchPRChecks(repoPath, 12, branch, 'abc123head', { force: true })
|
||||
).resolves.toEqual(cachedChecks)
|
||||
|
||||
expect(store.getState().checksCache[checksCacheKey]?.data).toEqual(cachedChecks)
|
||||
expect(store.getState().checksCache[checksCacheKey]?.fetchedAt).toBe(1)
|
||||
})
|
||||
|
||||
it('does not return cached checks for a different requested head SHA after IPC failure', async () => {
|
||||
const store = createTestStore()
|
||||
const repoPath = '/repo'
|
||||
const branch = 'feature/test'
|
||||
const checksCacheKey = `${repoPath}::pr-checks::12`
|
||||
const oldHeadChecks = [
|
||||
{ name: 'build', status: 'completed', conclusion: 'success', url: null } as const
|
||||
]
|
||||
|
||||
store.setState({
|
||||
checksCache: {
|
||||
[checksCacheKey]: {
|
||||
data: oldHeadChecks,
|
||||
fetchedAt: 1,
|
||||
headSha: 'old-head'
|
||||
}
|
||||
}
|
||||
} as unknown as Partial<AppState>)
|
||||
mockApi.gh.prChecks.mockRejectedValueOnce(new Error('rate limited'))
|
||||
|
||||
await expect(
|
||||
store.getState().fetchPRChecks(repoPath, 12, branch, 'new-head', { force: true })
|
||||
).resolves.toEqual([])
|
||||
|
||||
expect(store.getState().checksCache[checksCacheKey]?.data).toEqual(oldHeadChecks)
|
||||
expect(store.getState().checksCache[checksCacheKey]?.headSha).toBe('old-head')
|
||||
})
|
||||
})
|
||||
|
||||
describe('createGitHubSlice.fetchPRForBranch', () => {
|
||||
|
||||
@@ -1430,7 +1430,11 @@ export const createGitHubSlice: StateCreator<AppState, [], [], GitHubSlice> = (s
|
||||
return checks
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch PR checks:', err)
|
||||
return get().checksCache[cacheKey]?.data ?? []
|
||||
const latestCached = get().checksCache[cacheKey]
|
||||
if (latestCached?.data && (!headSha || latestCached.headSha === headSha)) {
|
||||
return latestCached.data
|
||||
}
|
||||
return []
|
||||
} finally {
|
||||
inflightChecksRequests.delete(inflightKey)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user