diff --git a/packages/shared/src/sourceControl.test.ts b/packages/shared/src/sourceControl.test.ts index d6c3bc5e1f81..b72f35793de5 100644 --- a/packages/shared/src/sourceControl.test.ts +++ b/packages/shared/src/sourceControl.test.ts @@ -110,6 +110,23 @@ describe("detectSourceControlProviderFromRemoteUrl", () => { }); }); + it("does not reuse SSH ports for HTTPS provider URLs", () => { + expect( + detectSourceControlProviderFromRemoteUrl("ssh://git@gitlab.example.test:24/group/repo.git"), + ).toEqual({ + kind: "gitlab", + name: "GitLab Self-Hosted", + baseUrl: "https://gitlab.example.test", + }); + expect( + detectSourceControlProviderFromRemoteUrl("ssh://git@code.example.test:24/team/project.git"), + ).toEqual({ + kind: "unknown", + name: "code.example.test", + baseUrl: "https://code.example.test", + }); + }); + it("matches self-hosted providers by complete DNS labels", () => { expect( detectSourceControlProviderFromRemoteUrl("https://github.example.com/owner/repo.git")?.kind, diff --git a/packages/shared/src/sourceControl.ts b/packages/shared/src/sourceControl.ts index 0b2e0e2699c6..ddfa3bdf9b46 100644 --- a/packages/shared/src/sourceControl.ts +++ b/packages/shared/src/sourceControl.ts @@ -146,6 +146,10 @@ export function isSshRemoteUrl(remoteUrl: string): boolean { return SCP_SSH_REMOTE_PATTERN.test(trimmed) || trimmed.toLowerCase().startsWith("ssh://"); } +/** + * Extracts the normalized host used for provider detection. SCP-style and SSH remotes return the + * hostname only, while other URL schemes retain explicit ports for non-default web endpoints. + */ function parseRemoteHost(remoteUrl: string): string | null { const trimmed = remoteUrl.trim(); if (trimmed.length === 0) { @@ -158,7 +162,8 @@ function parseRemoteHost(remoteUrl: string): string | null { } try { - return new URL(trimmed).host.toLowerCase(); + const url = new URL(trimmed); + return (url.protocol === "ssh:" ? url.hostname : url.host).toLowerCase(); } catch { return null; }