mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 08:03:39 +00:00
* 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>
53 lines
1.8 KiB
TypeScript
53 lines
1.8 KiB
TypeScript
import type { IssueSourcePreference } from '../../shared/types'
|
|
import { pickPreferredGitRemote } from '../../shared/preferred-git-remote'
|
|
import { getDefaultRemote } from '../git/repo'
|
|
import { getGitHubApiRepositoryForRemote } from './github-api-repository'
|
|
|
|
type GitExec = (args: string[]) => Promise<{ stdout: string; stderr: string }>
|
|
|
|
// Why: explicit origin must match issue listing; otherwise hosting identity
|
|
// keeps contributor clones on the upstream project's PR namespace.
|
|
export async function resolveGitHubReviewHeadRemote(args: {
|
|
repoPath: string
|
|
issueSourcePreference?: IssueSourcePreference
|
|
connectionId?: string | null
|
|
localGitOptions?: { wslDistro?: string }
|
|
gitExec: GitExec
|
|
}): Promise<string> {
|
|
const { stdout } = await args.gitExec(['remote'])
|
|
const remotes = stdout
|
|
.split(/\r?\n/)
|
|
.map((line) => line.trim())
|
|
.filter(Boolean)
|
|
if (args.issueSourcePreference === 'origin') {
|
|
if (remotes.includes('origin')) {
|
|
return 'origin'
|
|
}
|
|
throw new Error('Repo has no configured origin remote.')
|
|
}
|
|
// Why: identity probes cost a `remote get-url` (plus a possible gh auth
|
|
// lookup) each; only multi-remote clones are ambiguous enough to need them.
|
|
if (remotes.length > 1) {
|
|
for (const remote of ['upstream', 'origin']) {
|
|
if (!remotes.includes(remote)) {
|
|
continue
|
|
}
|
|
const repository = await getGitHubApiRepositoryForRemote(
|
|
args.repoPath,
|
|
remote,
|
|
args.connectionId ?? null,
|
|
args.localGitOptions ?? {}
|
|
)
|
|
if (repository) {
|
|
return remote
|
|
}
|
|
}
|
|
}
|
|
// Why: when no remote maps to a GitHub project the hosting identity cannot
|
|
// guide the choice; keep the legacy per-transport fallback.
|
|
if (args.connectionId) {
|
|
return pickPreferredGitRemote(remotes)
|
|
}
|
|
return getDefaultRemote(args.repoPath, args.localGitOptions ?? {})
|
|
}
|