Skip to content

fix(server): detect GitHub Enterprise remotes that gh is signed in to - #7958

Closed
Ygilany wants to merge 3 commits into
pingdotgg:mainfrom
Ygilany:t3code/63a18e9a
Closed

Ygilany wants to merge 3 commits into
pingdotgg:mainfrom
Ygilany:t3code/63a18e9a

Conversation

@Ygilany

@Ygilany Ygilany commented Aug 23, 2026 •

Copy link
Copy Markdown

What Changed

GitHubSourceControlProvider's discovery spec now implements refineUnknownRemote, the hook GitLab already used to claim hosts that hostname matching cannot identify. When a remote is detected as kind: "unknown", gh auth status --json hosts is consulted, and any host gh is signed in to claims that remote as GitHub.

  • apps/server/src/sourceControl/GitHubSourceControlProvider.ts — the refiner, +27 lines
  • packages/shared/src/sourceControl.ts — export the existing parseHostName so both sides of the host comparison drop ports
  • Tests — detection precondition in packages/shared, five refiner cases in GitHubSourceControlProvider.test.ts, one end-to-end resolveHandle case in SourceControlProviderRegistry.test.ts
  • One paragraph in docs/user/source-control.md

Nothing changes for hosts that already resolve. refineUnknownRemoteProvider returns early unless the kind is unknown, so github.com and github.* remotes never reach the new code and spawn no extra process.

Why

A GitHub Enterprise Server hostname is chosen by whoever installed it. isGitHubHost matches only github.com or a host carrying github as a dot-separated DNS label, so an install at git.example.edu or code.acme.tld falls through every branch to kind: "unknown". No provider is registered under "unknown", so unsupportedProvider is returned and every operation fails:

Source control provider unknown failed in listChangeRequests:
No unknown source control provider is registered.

The PR panel stays empty and that message repeats on every status refresh, through VcsStatusBroadcaster.refreshStatus → remoteStatus → readRemoteStatus → lookupStatusPr → findLatestPrForHeadContext → listChangeRequests. gh resolves the PR correctly from the same cwd the whole time.

The recovery path for exactly this case already exists: refineUnknownRemoteProvider runs each CLI's auth command and lets a provider claim the host by name. GitLab implements refineUnknownRemote; GitHub did not, so isCliRemoteRefinementSpec filtered the GitHub spec out and gh was never asked. Net effect was that GitLab self-hosted on an arbitrary domain worked while GitHub Enterprise on an arbitrary domain did not — which reads as unintended, since the contracts already model github.com and a GHES install as separate identities under one provider kind.

Everything needed was already in place: authArgs is already ["auth", "status", "--json", "hosts"], and parseGitHubAuthStatus already decodes that JSON per host. No new parsing, no new process invocation, no config surface.

Two details worth a reviewer's attention:

  • Matching accepts any authenticated account on the host rather than the active one. gh keeps one active account per host, so gating on active would fail a user with two logins on the same GHES host who has switched to the other.
  • The unknown context carries the raw remote host in provider.name, which retains :port, while gh keys hosts by bare hostname — so both sides go through parseHostName. GitLab's refiner deliberately still compares the raw name: glab reports hosts with the port, and there are existing tests for localhost:8080 and self-hosted.example.test:8443.

Verification

vp test run across the four affected source-control test files: 46 tests pass. Targeted lint and typecheck are clean for apps/server and packages/shared.

Also exercised against a real machine with gh signed in to both github.com and a GHES install at once:

remote result
https://github.com/pingdotgg/t3code.git detected github by hostname; refiner never consulted
https://<ghes-host>/org/repo.git detected unknown, refined to github / GitHub Self-Hosted
a third host with no gh account stays null; not claimed

One pre-existing limitation this PR does not address: with two hosts signed in, the Settings → Source Control row still reports a single identity, because parseGitHubAuth collapses the account list through findAuthenticatedGitHubAccount. That is display-only and does not affect which account serves PR lookup. Widening it would mean changing SourceControlProviderAuth in packages/contracts, which belongs in its own PR.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes — n/a, no UI changes
  • I included a video for animation/interaction changes — n/a, no motion or interaction changes

Model: Claude Opus 5. Harness: Claude Code, driven from T3 Code.


Note

Medium Risk
Changes provider detection for unknown remotes using CLI auth status. Mis-matching a host could route GitHub operations to the wrong provider, but the path only runs for unknown remotes and requires a signed-in gh account.

Overview
GitHub Enterprise remotes whose hostnames do not contain github (e.g. git.example.edu) are now claimed as GitHub when gh has a signed-in account for that host, instead of staying unknown and failing every PR operation.

GitHub discovery now implements refineUnknownRemote, matching GitLab’s existing hook. Any authenticated account on the host counts (not only the active one). Host comparison goes through exported parseHostName so remotes with ports still match gh’s bare hostnames. Hosts already classified by name are unchanged.

Reviewed by Cursor Bugbot for commit 2640c97. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Detect GitHub Enterprise remotes that gh is signed in to via refineUnknownRemote

  • Adds refineUnknownGitHubRemote to GitHubSourceControlProvider.ts, which parses gh auth status stdout and maps an 'unknown' remote to a GitHub provider when any authenticated account matches the remote's host.
  • Exports parseHostName from sourceControl.ts to normalize hosts (dropping ports) for matching against gh's bare hostname keys.
  • Wires refineUnknownRemote into the discovery object so unknown remotes are refined during discovery.
  • Updates docs/user/source-control.md to document GitHub Enterprise Server recognition via gh authentication.
  • Risk: non-standard-port remotes match gh's bare hostname but preserve the original port in baseUrl; verify refineUnknownGitHubRemote port handling in GitHubSourceControlProvider.ts.
📊 Macroscope summarized 2640c97. 3 files reviewed, 1 issue evaluated, 1 issue filtered, 0 comments posted

🗂️ Filtered Issues

apps/server/src/sourceControl/GitHubSourceControlProvider.ts — 0 comments posted, 1 evaluated, 1 filtered
  • line 107: refineUnknownGitHubRemote drops the remote's port before matching it to a gh host. If one hostname serves GitHub Enterprise and another provider on a different port (for example, example.com for GHES and example.com:8443 for GitLab), an authenticated gh entry for example.com makes the unknown remote on port 8443 get incorrectly claimed as GitHub. The returned provider then routes operations to the wrong CLI; preserve or otherwise validate the remote port before claiming it. [ Out of scope (post-validation triage) ]

Provider CLIs report hosts inconsistently, so callers outside this module
need the same port-stripping normalization that detection already uses.
A GitHub Enterprise host is named by whoever installed it, so matching on a
"github" DNS label misses installs like git.example.edu. Those remotes were
classified as unknown, which resolves to a stub that fails every operation,
so the PR panel stayed empty with "No unknown source control provider is
registered."

GitLab already claimed unknown hosts through refineUnknownRemote; GitHub
never implemented it, so the discovery spec was filtered out and gh was
never asked. Add the GitHub refiner so any authenticated gh host claims its
remote. Matching accepts any signed-in account on the host rather than only
the active one, since gh selects an active account per host and a remote
should resolve regardless of which login is currently selected. Both sides
of the host comparison are normalized so a remote carrying a port still
matches gh's bare hostnames.
Signing in with gh --hostname is now enough for T3 Code to recognize an
enterprise install, whatever the host is called.
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c6e4aa77-7b6c-477b-8211-a251fe504c1e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 23, 2026
@Ygilany Ygilany closed this Aug 23, 2026
@Ygilany
Ygilany deleted the t3code/63a18e9a branch August 23, 2026 03:31
@Ygilany

Ygilany commented Aug 23, 2026

Copy link
Copy Markdown
Author

Superseded by #7959 — same commits, renamed the head branch to something descriptive and GitHub closed this one when the old ref went away. Nothing to review here.

@macroscopeapp

macroscopeapp Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Skipped

Macroscope did not run approvability analysis for this PR. Macroscope could not determine whether this PR modifies its approvability configuration, so the PR was not approved automatically. A PR that may change the rules that govern approval is never approved automatically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant