Repository navigation
Fetch issues from gitlab.com as well as github.com - #25
Merged
Merged
Conversation
added 2 commits
August 26, 2026 14:06
Anything that talks to a code-hosting service on the user's behalf has to decide which service it is talking to, and the only evidence always present in a checkout is the URL of its `origin` remote. Reading that URL is a one-liner, but interpreting it is not: git uses two unrelated syntaxes for the same repository depending on how it was cloned — `https://host/owner/repo.git` from an HTTPS clone and the scp-like `git@host:owner/repo.git` from an SSH one. Comparing raw URLs, or handling only the HTTPS form, routes the same project two different ways depending on which one a given contributor happened to use. `parseGitRemoteHost` reduces both forms (plus `ssh://`, `git://`, embedded credentials, and a port) to a lowercased hostname. `issueHostFor` maps that hostname to a forge, matching the public hostnames exactly: a self-hosted instance is not inferred from a hostname that merely reads like one, because guessing wrong points the wrong client at the wrong API, and that is harder to act on than being told the host is unsupported. Note that `git remote get-url` reports the *effective* URL, so a user's own `url.<base>.insteadOf` rewrite rules change its answer. That is the desired behaviour — the rewritten URL is the host git actually contacts — but it does mean the tests empty out the git config they run against, or they would pass or fail depending on whose machine ran them.
"Fetch issues" ran `gh issue list` unconditionally. In a checkout hosted anywhere other than GitHub that is not a degraded result, it is a confusing one: `gh` reports that it cannot resolve the repository, so a GitLab user is told their project does not exist rather than that the wrong tool was asked. The forge is now chosen from the `origin` remote's host. github.com keeps the existing `gh` path unchanged; gitlab.com goes to `glab`, GitLab's own CLI, arranged exactly as the GitHub path is — ask the CLI for JSON, let it own authentication, store no token. `glab` must be installed and logged in for that path to work, the same assumption the `gh` path has always made. Any other host is refused by name instead of guessed at. Pointing `gh` at a self-hosted GitLab, or `glab` at GitHub Enterprise, fails in terms that describe neither the repository nor the real problem; "supports github.com and gitlab.com" is at least actionable. The message names the parsed host and never the remote URL, because a remote can carry a personal access token and this text is rendered in the app. The GitLab JSON is mapped from field names verified against `glab issue list --output json` rather than assumed from the GitHub shape, which differs in four places that would otherwise fail silently: `iid` is the per-project number users see (`id` is global), `description` holds the body and is null rather than empty when unset, assignees carry `username` not `login`, and `labels` is an array of plain strings where `gh` returns objects with a `name` — reading that one as objects yields empty labels and no error. The renderer and the IPC channel are untouched: the normalized issue shape is the same, and the button already said "Fetch issues" rather than naming a forge.
🚫 This PR is missing its before/after evidenceEvery pull request here has to show its work. Screenshots or a short screen recording, before the change and after it.
How to fix it: edit the description, keep the A bug fix with no visible surface still needs it: show the failing behaviour, then the same steps passing. A terminal recording is fine. Genuinely nothing to show — a CI tweak, a typo, a dependency bump? A maintainer can apply the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
"Fetch issues" in the Monitor panel ran
gh issue listunconditionally. On arepository hosted anywhere other than GitHub that is not a degraded result, it
is a misleading one:
ghreports that the repository points at no known GitHubhost, so a GitLab user is told their project does not exist rather than that the
wrong tool was asked.
The forge is now chosen from the
originremote's host. github.com keeps theexisting
ghpath unchanged; gitlab.com goes toglab, GitLab's own CLI,arranged exactly as the GitHub path already is — ask the CLI for JSON, let it
own authentication, store no token.
glabmust be installed and logged in forthe GitLab path to work, which is the same assumption the
ghpath has alwaysmade. No new credential storage or token plumbing is introduced.
Any other host — a self-hosted GitLab, GitHub Enterprise, Bitbucket, or a repo
with no
origin— is refused by name rather than guessed at. Pointingghat aself-hosted GitLab fails in terms that describe neither the repository nor the
real problem, so the message names the supported hosts instead. It reports the
parsed host and never the remote URL, because a remote can carry a personal
access token and this string is rendered in the app.
The renderer and the IPC channel are untouched: the normalized issue shape is
unchanged, and the button already read "Fetch issues" rather than naming a
forge. Scope is issues only — the separate CI-runs path is GitHub Actions
specific and is deliberately left alone.
Type of change
Evidence
A terminal capture, since the change is in the main process behind an existing
button whose label and markup do not change.
Before
mainrunsghregardless of host. In a checkout whoseoriginis agitlab.com project (
https://gitlab.com/gitlab-org/cli.git), that is the exactcommand the old
listIssuesissued:The panel surfaces that string. Nothing in it suggests the project is fine and
the client was wrong.
After
The same checkout, same command path, with this change applied —
listIssues()called against that gitlab.com repo, printing what the renderer receives:
The GitHub path is unchanged — this repository's own
origin, same call:An unsupported host is named rather than guessed at, and a token embedded in the
remote is not echoed back:
Test suite, before and after:
How I tested it
npm run typecheck— 0 errors (node + web).npm run test:focused— 563 of 563 pass. The baseline on the committhis branches from is 552 of 552, so the 11 added tests are the whole
difference and there are no pre-existing failures.
npm run build— succeeds;out/main/index.jscontains the new routing.listIssues()end to end against live gitlab.com(
gitlab-org/cli, viaglab1.114.0) and against live github.com(this repository, via
gh), plus a self-hosted-looking host and atoken-bearing remote. All four outputs are quoted above.
glab issue list --output jsonoutput rather than assumed from the GitHub shape. Four of themdiffer in ways that fail silently:
iidis the per-project number userssee (
idis global and would render a number matching nothing), the bodyis
descriptionand isnullrather than''when unset, assignees carryusernamenotlogin, andlabelsis an array of plain strings whereghreturns objects with aname— mapping that one as objects yieldsempty labels and no error.
iid/idchoice,the
descriptionfield, the assignee key, both routing branches, theunsupported-host refusal, and the credential redaction were each broken in
turn and confirmed to turn the suite red.
Not covered: clicking the button in a running Electron window, and any
self-hosted GitLab or GitHub Enterprise instance (explicitly out of scope — such
a host is refused, not guessed at).
Checklist
npm run typecheckpasses.npm run test:focusedpasses.npm run buildsucceeds.commented-out code, or unrelated formatting churn in it.
DESIGN.md/tokens.ts— no ad-hoc colors,spacing, or fonts. (No UI changed.)
ATTRIBUTION.md. (No art.)