Fix PR review actions failing on GitHub Enterprise remotes

- Threads GitHub host identity (not just owner/repo) through the client,
  work-item-details, issues, and RPC layers so gh commands target the
  correct Enterprise server instead of silently falling back to github.com
- Adds a shared github-api-repository helper to resolve/host-qualify repo
  identity consistently across REST, GraphQL, and CLI shorthand calls
- Scopes the gh rate-limit breaker and singleton rate-limit snapshot by
  host/runtime so a github.com block or probe can't affect GHES or WSL
- Coalesces concurrent host-auth probes and paginates PR file fetching
  beyond 100 results
- Propagates `host` through renderer PR caches, checks-panel keys, and
  preload IPC types so Enterprise and github.com data never collide
This commit is contained in:
Jinjing
2026-07-20 12:35:24 -07:00
parent 9ac7fd483d
commit 7b49c5739d
31 changed files with 1544 additions and 300 deletions
+67
View File
@@ -0,0 +1,67 @@
import type { GitHubOwnerRepo } from '../../shared/types'
import { getOwnerRepo, type LocalGitExecOptions } from './gh-utils'
import { getEnterpriseGitHubRepoSlug } from './github-enterprise-repository'
export type GitHubApiRepository = GitHubOwnerRepo
export async function getOriginGitHubApiRepository(
repoPath: string,
connectionId?: string | null,
localGitOptions: LocalGitExecOptions = {}
): Promise<GitHubApiRepository | null> {
const ownerRepo = await getOwnerRepo(repoPath, connectionId, localGitOptions)
if (ownerRepo) {
return { ...ownerRepo, host: 'github.com' }
}
const enterpriseOptions =
Object.keys(localGitOptions).length > 0 ? { localGitExecOptions: localGitOptions } : {}
return getEnterpriseGitHubRepoSlug(repoPath, connectionId, enterpriseOptions)
}
export async function resolveGitHubApiRepository(
repoPath: string,
repository?: GitHubApiRepository | null,
connectionId?: string | null,
localGitOptions: LocalGitExecOptions = {}
): Promise<GitHubApiRepository | null> {
if (repository?.host) {
return repository
}
const originRepository = await getOriginGitHubApiRepository(
repoPath,
connectionId,
localGitOptions
)
if (!repository) {
return originRepository
}
// Why: older clients only send owner/repo. The origin still supplies the
// execution host for fork-base slugs on the same GitHub Enterprise server.
if (originRepository?.host) {
return { ...repository, host: originRepository.host }
}
// Why: connection-backed gh has no cwd to infer a host from. An unhosted
// legacy identity is unsafe there because gh would target its default account.
return connectionId ? null : repository
}
export function githubApiHostArgs(repository: GitHubApiRepository): string[] {
const host = repository.host
return host && host.toLowerCase() !== 'github.com' ? ['--hostname', host] : []
}
export function isGitHubDotComRepository(repository: GitHubApiRepository): boolean {
return !repository.host || repository.host.toLowerCase() === 'github.com'
}
// Why: owner/repo shorthand targets gh's default host, and SSH-backed repos
// have no local cwd from which gh can infer an Enterprise hostname.
export function githubCliRepositoryArgument(repository: GitHubApiRepository): string {
return !isGitHubDotComRepository(repository)
? `${repository.host}/${repository.owner}/${repository.repo}`
: `${repository.owner}/${repository.repo}`
}
export function githubRepositoryWebHost(repository: GitHubApiRepository): string {
return repository.host ?? 'github.com'
}