mirror of
https://github.com/stablyai/orca.git
synced 2026-09-29 16:02:50 +00:00
fix(github): align PR source and review head origin (#10677)
* fix(github): align PR source and review head origin * fix(github): pin number-based work item open to the repo source preference Open-by-number and details still ran the upstream-first multi-candidate PR probe, so a fork and its upstream sharing a PR number opened different PRs than the list and start-point paths did once #10677 pinned those to origin. Thread repo.issueSourcePreference through dispatchWorkItem, getWorkItemDetails, getRepoWorkItem, and getRepoWorkItemDetails. getWorkItemByOwnerRepo is left alone: explicit owner/repo already pins identity. auto/upstream/undefined keep the multi-candidate probe. Co-authored-by: Orca <help@stably.ai> * test(github): enforce origin preference in review head origin resolution The explicit origin preference must short-circuit before any identity probe, so no remote queries should occur. Add validation to reject unexpected remotes and tighten the test assertion to verify no remote get-url calls happen at all. * fix(github): enforce origin preference in issue open-by-number lookup listWorkItems and getWorkItem must share preference so origin/upstream toggles cannot disagree. Explicit origin preference now fail-closes when origin identity is unresolved (no bare-lookup fallback), matching the PR candidate resolution rule. --------- Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -513,6 +513,54 @@ describe('GitHub issue source split', () => {
|
||||
expect(item?.prRepo).toEqual(upstream)
|
||||
})
|
||||
|
||||
it('pins typed PR metadata to explicit origin when upstream has the same number', async () => {
|
||||
const upstream = { owner: 'stablyai', repo: 'orca', host: 'github.com' }
|
||||
const origin = { owner: 'fork', repo: 'orca', host: 'github.com' }
|
||||
getOwnerRepoMock.mockResolvedValue(origin)
|
||||
mockUpstreamCandidate(upstream)
|
||||
resolvePRRepositoryCandidatesMock.mockResolvedValue({
|
||||
candidates: [upstream, origin],
|
||||
headRepo: origin
|
||||
})
|
||||
ghExecFileAsyncMock.mockResolvedValueOnce({
|
||||
stdout: JSON.stringify({
|
||||
number: 42,
|
||||
title: 'Origin PR',
|
||||
state: 'open',
|
||||
url: 'https://github.com/fork/orca/pull/42',
|
||||
labels: [],
|
||||
updatedAt: '2026-04-02T00:00:00Z',
|
||||
author: { login: 'octocat' },
|
||||
isDraft: false,
|
||||
headRefName: 'origin/fix',
|
||||
baseRefName: 'main'
|
||||
})
|
||||
})
|
||||
|
||||
const item = await getWorkItem('/repo-root', 42, 'pr', null, {}, 'origin')
|
||||
|
||||
expect(resolvePRRepositoryCandidatesMock).not.toHaveBeenCalled()
|
||||
expect(ghExecFileAsyncMock.mock.calls[0]?.[0]).toEqual(
|
||||
expect.arrayContaining(['pr', 'view', '--repo', 'fork/orca'])
|
||||
)
|
||||
expect(
|
||||
ghExecFileAsyncMock.mock.calls.some((call) =>
|
||||
(call[0] as string[]).some((arg) => arg.includes('upstream/orca'))
|
||||
)
|
||||
).toBe(false)
|
||||
expect(item?.prRepo).toEqual(origin)
|
||||
})
|
||||
|
||||
it('does not run a bare PR lookup when explicit origin identity is unresolved', async () => {
|
||||
getOwnerRepoMock.mockResolvedValue(null)
|
||||
mockUpstreamCandidate({ owner: 'stablyai', repo: 'orca' })
|
||||
|
||||
await expect(getWorkItem('/repo-root', 42, 'pr', null, {}, 'origin')).resolves.toBeNull()
|
||||
|
||||
expect(resolvePRRepositoryCandidatesMock).not.toHaveBeenCalled()
|
||||
expect(ghExecFileAsyncMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not run a bare gh lookup for an SSH repo without candidates', async () => {
|
||||
resolvePRRepositoryCandidatesMock.mockResolvedValueOnce({ candidates: [], headRepo: null })
|
||||
|
||||
|
||||
Reference in New Issue
Block a user