Skip to content

Commit 549201f

Browse files
fix(clients): default GitHub clones to HTTPS (#7760)
Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>
1 parent 9f12eab commit 549201f

4 files changed

Lines changed: 68 additions & 4 deletions

File tree

‎apps/mobile/src/features/projects/AddProjectScreen.tsx‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
getCloneDestinationBrowsePath,
1111
getCloneDestinationPath,
1212
getCloneDirectoryName,
13+
getDefaultCloneUrl,
14+
normalizePastedCloneUrl,
1315
resolveAddProjectPath,
1416
sortAddProjectProviderSources,
1517
type AddProjectRemoteSource,
@@ -662,7 +664,7 @@ export function AddProjectRepositoryScreen(props: {
662664
setIsSubmitting(true);
663665
const provider = addProjectRemoteSourceProvider(source);
664666
if (!provider) {
665-
const remoteUrl = repositoryInput.trim();
667+
const remoteUrl = normalizePastedCloneUrl(repositoryInput);
666668
navigation.dispatch(
667669
StackActions.push("AddProjectDestination", {
668670
environmentId: environment.environmentId,
@@ -691,7 +693,7 @@ export function AddProjectRepositoryScreen(props: {
691693
StackActions.push("AddProjectDestination", {
692694
environmentId: environment.environmentId,
693695
source,
694-
remoteUrl: repository.sshUrl,
696+
remoteUrl: getDefaultCloneUrl(repository),
695697
repositoryTitle: repository.nameWithOwner,
696698
repositoryName: getCloneDirectoryName(repository.nameWithOwner),
697699
}),

‎apps/web/src/components/CommandPalette.tsx‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
66
getCloneDestinationBrowsePath,
77
getCloneDestinationPath,
88
getCloneDirectoryName,
9+
getDefaultCloneUrl,
10+
normalizePastedCloneUrl,
911
} from "@t3tools/client-runtime/operations/projects";
1012
import { connectionStatusText } from "@t3tools/client-runtime/connection";
1113
import { threadSearchMatchKey } from "@t3tools/client-runtime/state/thread-search";
@@ -1874,7 +1876,7 @@ function OpenCommandPaletteDialog(props: {
18741876
source: addProjectCloneFlow.source,
18751877
repositoryInput: rawRepository,
18761878
repository: null,
1877-
remoteUrl: rawRepository,
1879+
remoteUrl: normalizePastedCloneUrl(rawRepository),
18781880
});
18791881
setHighlightedItemValue(null);
18801882
setQuery(destinationPath);
@@ -1914,7 +1916,7 @@ function OpenCommandPaletteDialog(props: {
19141916
source: addProjectCloneFlow.source,
19151917
repositoryInput: rawRepository,
19161918
repository,
1917-
remoteUrl: repository.sshUrl,
1919+
remoteUrl: getDefaultCloneUrl(repository),
19181920
});
19191921
setHighlightedItemValue(null);
19201922
setQuery(destinationPath);

‎packages/client-runtime/src/operations/projects.test.ts‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {
1616
getCloneDestinationBrowsePath,
1717
getCloneDestinationPath,
1818
getCloneDirectoryName,
19+
getDefaultCloneUrl,
20+
normalizePastedCloneUrl,
1921
resolveAddProjectPath,
2022
sortAddProjectProviderSources,
2123
} from "./projects.ts";
@@ -46,6 +48,46 @@ describe("add project shared logic", () => {
4648
expect(getCloneDirectoryName(null)).toBe("");
4749
});
4850

51+
it("routes owner/repository shorthand to GitHub over HTTPS", () => {
52+
expect(normalizePastedCloneUrl("imputnet/helium")).toBe(
53+
"https://github.com/imputnet/helium.git",
54+
);
55+
expect(normalizePastedCloneUrl(" pingdotgg/t3code ")).toBe(
56+
"https://github.com/pingdotgg/t3code.git",
57+
);
58+
});
59+
60+
it("keeps explicit clone URLs and local paths unchanged", () => {
61+
expect(normalizePastedCloneUrl("https://gitlab.com/group/project.git")).toBe(
62+
"https://gitlab.com/group/project.git",
63+
);
64+
expect(normalizePastedCloneUrl("git@github.com:owner/repo.git")).toBe(
65+
"git@github.com:owner/repo.git",
66+
);
67+
expect(normalizePastedCloneUrl("group/subgroup/project")).toBe("group/subgroup/project");
68+
expect(normalizePastedCloneUrl("/srv/git/repo.git")).toBe("/srv/git/repo.git");
69+
});
70+
71+
it("uses HTTPS for repositories selected through a provider", () => {
72+
expect(
73+
getDefaultCloneUrl({
74+
provider: "github",
75+
url: "https://github.com/imputnet/helium",
76+
sshUrl: "git@github.com:imputnet/helium.git",
77+
}),
78+
).toBe("https://github.com/imputnet/helium");
79+
});
80+
81+
it("preserves existing clone transport behavior for other providers", () => {
82+
expect(
83+
getDefaultCloneUrl({
84+
provider: "gitlab",
85+
url: "https://gitlab.com/group/project.git",
86+
sshUrl: "git@gitlab.com:group/project.git",
87+
}),
88+
).toBe("git@gitlab.com:group/project.git");
89+
});
90+
4991
it("derives the clone folder name from any pasted clone URL", () => {
5092
expect(getCloneDirectoryName("https://github.com/owner/repo.git")).toBe("repo");
5193
expect(getCloneDirectoryName("https://github.com/owner/repo")).toBe("repo");

‎packages/client-runtime/src/operations/projects.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,24 @@ export function addProjectRemoteSourceProvider(
106106
return source === "url" ? null : source;
107107
}
108108

109+
const GITHUB_REPOSITORY_SHORTHAND =
110+
/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})\/[A-Za-z0-9._-]+(?:\.git)?$/;
111+
112+
/** Treat the common owner/repository shorthand as a public GitHub HTTPS URL. */
113+
export function normalizePastedCloneUrl(input: string): string {
114+
const trimmed = input.trim();
115+
if (!GITHUB_REPOSITORY_SHORTHAND.test(trimmed)) return trimmed;
116+
const repository = trimmed.endsWith(".git") ? trimmed : `${trimmed}.git`;
117+
return `https://github.com/${repository}`;
118+
}
119+
120+
/** GitHub defaults to HTTPS; other providers retain their existing SSH default. */
121+
export function getDefaultCloneUrl(
122+
repository: Pick<SourceControlRepositoryInfo, "provider" | "url" | "sshUrl">,
123+
): string {
124+
return repository.provider === "github" ? repository.url : repository.sshUrl;
125+
}
126+
109127
export function sortAddProjectProviderSources(
110128
readinessBySource: AddProjectRemoteSourceReadiness,
111129
): ReadonlyArray<AddProjectRemoteProviderKind> {

0 commit comments

Comments
 (0)