fix(glrepo): recognize an authenticated host with a port in --repo
Description
glab --repo HOST/OWNER/REPO (and GITLAB_REPO) ignores an authenticated host that has a port but no dot, such as localhost:3000 for a local development instance. After glab auth login --hostname localhost:3000, glab issue list -R localhost:3000/OWNER/REPO asks gitlab.com for a project named localhost:3000/OWNER/REPO instead of asking localhost:3000 for OWNER/REPO.
The cause is in FromFullName. Dots are allowed in group paths, so it compares the first segment with the authenticated hosts only when that segment contains a dot. A host with a port and no dot never reaches that comparison and falls through to the GROUP/NAMESPACE/REPO case on the default host.
This MR runs the same authenticated host check when the first segment contains a dot or a colon. A colon cannot appear in a GitLab group or project path (PATH_REGEX_STR allows letters, digits, _, - and .), so no valid group name changes meaning. The host still has to be in the authenticated list: a segment with a colon that does not match an authenticated host is read exactly as before.
Behavior change: a --repo or GITLAB_REPO value whose first segment contains a colon and matches an authenticated host now targets that host. Before, it was sent to the default host as a project path that GitLab cannot have.
A dotless host without a port (for example an intranet host named gitlab) is still not recognized, because its name can also be a valid group. I kept that out of this MR: checking every first segment against the authenticated hosts would cover it, but it would change how a group whose name matches an authenticated host is read, which seems a decision for the maintainers. !4188, open, proposes that rule for glab repo clone paths, where a configured host takes precedence over a group of the same name; it changes other files.
Related Issues
Closes #8679 (closed)
!3757 (merged) is related: it keyed the subfolder config lookup on the host with its port, in the same file.
How has this been tested?
I added two cases to the existing TestFromFullName table, with localhost:3000 added to its test config: an authenticated host with a port and no dot (localhost:3000/OWNER/REPO must resolve to host localhost:3000, project OWNER/REPO), and an unauthenticated host with a port (localhost:4000/OWNER/REPO must keep resolving to gitlab.com, project localhost:4000/OWNER/REPO, as it does today).
- Without the fix, the first case fails with
expected host "localhost:3000", got "gitlab.com"; the second passes. - With the fix,
make test-race(thetests:unitjob) passes: 6720 tests, 18 skipped, none failed. golangci-lint runandgolangci-lint fmt --diff(v2.14.0, the version of thelintjob) report nothing for the whole repository.scripts/comment-overlapreports 0 findings,make generateandmake gen-docschange no file,make check-embedandmake check-argspass, andscripts/commit-lint/lint.jsaccepts the title and the commit.- Reverting the condition to the dot-only check, checking only the colon, or accepting any segment with a colon without the authenticated list each makes a case of
TestFromFullNamefail.
End to end, I built glab from main and from this branch and ran glab issue list -R localhost:3123/OWNER/REPO with a configuration holding one authenticated host, localhost:3123, against a stub of the issues route on that port. HTTPS_PROXY pointed at a second stub that logs every CONNECT and refuses it, so nothing reached gitlab.com:
main: glab askedhttps://gitlab.com/api/v4/projects/localhost:3123%2FOWNER%2FREPO/issuesand failed with the proxy stub'sForbidden; the proxy stub loggedCONNECT gitlab.com:443, and the stub onlocalhost:3123saw nothing.- This branch: the stub on
localhost:3123receivedGET /api/v4/projects/OWNER%2FREPO/issues, and glab printedNo open issues match your search in OWNER/REPO. GITLAB_REPO=localhost:3123/OWNER/REPO glab issue listgave the same two results.
This comes from maintaining gitlab-mcp-server; its upstream-bugs.md records everything done on its dependencies and sibling projects.
Test output before and after the fix
Before (main at a6fd50ce, with the new test cases):
repo_test.go:454: expected host "localhost:3000", got "gitlab.com"
repo_test.go:457: expected owner "OWNER", got "localhost:3000/OWNER"
repo_test.go:463: expected group "", got "localhost:3000"
repo_test.go:466: expected fullname "OWNER/REPO", got "localhost:3000/OWNER/REPO"
--- FAIL: TestFromFullName/authenticated_hostname_with_port_and_no_dot (0.00s)
FAIL
FAIL gitlab.com/gitlab-org/cli/internal/glrepo 0.016s
FAILAfter:
--- PASS: TestFromFullName/authenticated_hostname_with_port_and_no_dot (0.00s)
--- PASS: TestFromFullName/unauthenticated_hostname_with_port (0.00s)
ok gitlab.com/gitlab-org/cli/internal/glrepo 0.021s
ok gitlab.com/gitlab-org/cli/internal/glrepo 0.572s
ok gitlab.com/gitlab-org/cli/internal/cmdutils 2.606smake test-race:
DONE 6720 tests, 18 skipped in 269.359sWhat the two stubs logged in the end-to-end run, main first:
proxy CONNECT gitlab.com:443 (refused)This branch:
instance GET /api/v4/projects/OWNER%2FREPO/issues?in=title%2Cdescription&order_by=created_at&page=1&per_page=30&sort=desc&state=opened Host=localhost:3123Environment: go1.27.3 linux/amd64, golangci-lint 2.14.0, Node.js 25 for the commit lint.
Screenshots (if appropriate):
Not applicable: no change to the output.