mirror of
https://github.com/stablyai/orca.git
synced 2026-10-13 08:02:52 +00:00
fix(git): skip upstream remote probes when the remote is absent (#18455)
* fix(git): skip upstream remote probes when the remote is absent Issue and PR resolvers listed remotes by probing `git remote get-url upstream` on every poll, including origin-only clones where that remote cannot exist. List remotes once, cache against git config, and skip the probe unless `upstream` is present. * fix(git): avoid stale remote probe cache entries * fix(github): observe origin repository probe failures * fix(github): observe verified origin probe failures * fix(github): skip missing upstream probe for PR lists * test(github): scope the #9171 lazy-resolution guard to default-branch commands The guard asserted that no git command runs for an open PR, using "no git at all" as a proxy for "no default-branch resolution". Remote-name listing is a separate concern, so allow it and keep every other command forbidden; the symbolic-ref/rev-parse resolution this issue is about stays unreachable. --------- Co-authored-by: Neil <neil@stably.ai>
This commit is contained in:
@@ -8,13 +8,15 @@ const {
|
||||
getOwnerRepoMock,
|
||||
getOwnerRepoForRemoteMock,
|
||||
getSshGitProviderGenerationMock,
|
||||
isGitHubHostAuthenticatedMock
|
||||
isGitHubHostAuthenticatedMock,
|
||||
shouldProbeGitRemoteMock
|
||||
} = vi.hoisted(() => ({
|
||||
getEnterpriseGitHubRepoSlugMock: vi.fn(),
|
||||
getOwnerRepoMock: vi.fn(),
|
||||
getOwnerRepoForRemoteMock: vi.fn(),
|
||||
getSshGitProviderGenerationMock: vi.fn(() => 0),
|
||||
isGitHubHostAuthenticatedMock: vi.fn()
|
||||
isGitHubHostAuthenticatedMock: vi.fn(),
|
||||
shouldProbeGitRemoteMock: vi.fn(async () => true)
|
||||
}))
|
||||
|
||||
vi.mock('../providers/ssh-git-dispatch', async (importOriginal) => ({
|
||||
@@ -35,12 +37,18 @@ vi.mock('./github-enterprise-repository', async (importOriginal) => ({
|
||||
isGitHubHostAuthenticated: isGitHubHostAuthenticatedMock
|
||||
}))
|
||||
|
||||
vi.mock('../git/remote-name-listing', () => ({
|
||||
shouldProbeGitRemote: shouldProbeGitRemoteMock
|
||||
}))
|
||||
|
||||
import {
|
||||
_resetOriginGitHubApiRepositoryCache,
|
||||
getGitHubApiRepositoryForRemote,
|
||||
getIssueGitHubApiRepository,
|
||||
getOriginGitHubApiRepository,
|
||||
githubHostExecOptions,
|
||||
resolveGitHubApiRepository,
|
||||
resolveGitHubApiRepositoryCandidates,
|
||||
resolveGitHubRepoExecution
|
||||
} from './github-api-repository'
|
||||
|
||||
@@ -51,6 +59,7 @@ beforeEach(() => {
|
||||
getOwnerRepoForRemoteMock.mockReset().mockResolvedValue(null)
|
||||
getSshGitProviderGenerationMock.mockReset().mockReturnValue(0)
|
||||
isGitHubHostAuthenticatedMock.mockReset().mockResolvedValue(false)
|
||||
shouldProbeGitRemoteMock.mockReset().mockResolvedValue(true)
|
||||
})
|
||||
|
||||
describe('githubHostExecOptions', () => {
|
||||
@@ -346,3 +355,146 @@ describe('origin repository cache', () => {
|
||||
expect(getEnterpriseGitHubRepoSlugMock).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
})
|
||||
|
||||
describe('skip missing upstream remote probes', () => {
|
||||
it('starts the issue origin probe before checking whether upstream exists', async () => {
|
||||
let releaseRemoteProbe: (value: boolean) => void = () => undefined
|
||||
shouldProbeGitRemoteMock.mockReturnValue(
|
||||
new Promise<boolean>((resolve) => {
|
||||
releaseRemoteProbe = resolve
|
||||
})
|
||||
)
|
||||
let originStarted = false
|
||||
getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) => {
|
||||
if (remote === 'origin') {
|
||||
originStarted = true
|
||||
return { owner: 'fork', repo: 'orca' }
|
||||
}
|
||||
return { owner: 'stablyai', repo: 'orca' }
|
||||
})
|
||||
|
||||
const resultPromise = getIssueGitHubApiRepository('/repo')
|
||||
expect(originStarted).toBe(true)
|
||||
|
||||
releaseRemoteProbe(true)
|
||||
await expect(resultPromise).resolves.toEqual({
|
||||
owner: 'stablyai',
|
||||
repo: 'orca',
|
||||
host: 'github.com'
|
||||
})
|
||||
})
|
||||
|
||||
it('does not probe upstream for issue identity when that remote is absent', async () => {
|
||||
shouldProbeGitRemoteMock.mockResolvedValue(false)
|
||||
getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) =>
|
||||
remote === 'origin' ? { owner: 'acme', repo: 'widgets' } : null
|
||||
)
|
||||
|
||||
await expect(getIssueGitHubApiRepository('/repo')).resolves.toEqual({
|
||||
owner: 'acme',
|
||||
repo: 'widgets',
|
||||
host: 'github.com'
|
||||
})
|
||||
expect(getOwnerRepoForRemoteMock.mock.calls.map(([, remote]) => remote)).toEqual(['origin'])
|
||||
})
|
||||
|
||||
it('still probes upstream for issue identity when that remote is present', async () => {
|
||||
getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) =>
|
||||
remote === 'upstream' ? { owner: 'stablyai', repo: 'orca' } : { owner: 'fork', repo: 'orca' }
|
||||
)
|
||||
|
||||
await expect(getIssueGitHubApiRepository('/repo')).resolves.toEqual({
|
||||
owner: 'stablyai',
|
||||
repo: 'orca',
|
||||
host: 'github.com'
|
||||
})
|
||||
expect(getOwnerRepoForRemoteMock).toHaveBeenCalledWith('/repo', 'upstream', undefined, {})
|
||||
})
|
||||
|
||||
it('observes a rejected origin probe when upstream resolves the issue repository', async () => {
|
||||
const originError = new Error('origin probe failed')
|
||||
getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) => {
|
||||
if (remote === 'origin') {
|
||||
throw originError
|
||||
}
|
||||
return { owner: 'stablyai', repo: 'orca' }
|
||||
})
|
||||
|
||||
await expect(getIssueGitHubApiRepository('/repo')).resolves.toEqual({
|
||||
owner: 'stablyai',
|
||||
repo: 'orca',
|
||||
host: 'github.com'
|
||||
})
|
||||
})
|
||||
|
||||
it('preserves a rejected origin probe when upstream cannot resolve the issue repository', async () => {
|
||||
const originError = new Error('origin probe failed')
|
||||
getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) => {
|
||||
if (remote === 'origin') {
|
||||
throw originError
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
await expect(getIssueGitHubApiRepository('/repo')).rejects.toBe(originError)
|
||||
})
|
||||
|
||||
it('does not probe upstream for PR candidates when that remote is absent', async () => {
|
||||
shouldProbeGitRemoteMock.mockResolvedValue(false)
|
||||
getOwnerRepoForRemoteMock.mockResolvedValue({ owner: 'fork', repo: 'orca' })
|
||||
|
||||
await expect(resolveGitHubApiRepositoryCandidates('/repo')).resolves.toEqual({
|
||||
candidates: [{ owner: 'fork', repo: 'orca', host: 'github.com' }],
|
||||
headRepo: { owner: 'fork', repo: 'orca', host: 'github.com' }
|
||||
})
|
||||
expect(getOwnerRepoForRemoteMock.mock.calls.map(([, remote]) => remote)).toEqual(['origin'])
|
||||
})
|
||||
|
||||
it('observes and propagates a verified origin probe failure while listing remotes', async () => {
|
||||
let releaseRemoteProbe: (value: boolean) => void = () => undefined
|
||||
shouldProbeGitRemoteMock.mockReturnValue(
|
||||
new Promise<boolean>((resolve) => {
|
||||
releaseRemoteProbe = resolve
|
||||
})
|
||||
)
|
||||
const originError = new Error('origin probe failed')
|
||||
getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) => {
|
||||
if (remote === 'origin') {
|
||||
throw originError
|
||||
}
|
||||
return { owner: 'stablyai', repo: 'orca' }
|
||||
})
|
||||
|
||||
const resultPromise = resolveGitHubApiRepositoryCandidates('/repo')
|
||||
await vi.waitFor(() =>
|
||||
expect(getOwnerRepoForRemoteMock).toHaveBeenCalledWith(
|
||||
'/repo',
|
||||
'origin',
|
||||
undefined,
|
||||
{},
|
||||
{ requireVerifiedSshProbe: true }
|
||||
)
|
||||
)
|
||||
releaseRemoteProbe(true)
|
||||
|
||||
await expect(resultPromise).rejects.toBe(originError)
|
||||
})
|
||||
|
||||
it('still probes upstream for PR candidates when that remote is present', async () => {
|
||||
getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) =>
|
||||
remote === 'upstream' ? { owner: 'Acme', repo: 'Orca' } : { owner: 'acme', repo: 'orca' }
|
||||
)
|
||||
|
||||
await expect(resolveGitHubApiRepositoryCandidates('/repo')).resolves.toEqual({
|
||||
candidates: [{ owner: 'Acme', repo: 'Orca', host: 'github.com' }],
|
||||
headRepo: { owner: 'acme', repo: 'orca', host: 'github.com' }
|
||||
})
|
||||
expect(getOwnerRepoForRemoteMock).toHaveBeenCalledWith(
|
||||
'/repo',
|
||||
'upstream',
|
||||
undefined,
|
||||
{},
|
||||
{ requireVerifiedSshProbe: true }
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user