Skip to content

Commit 9a24ed4

Browse files
allow custom git domains to support internal dns at companies
1 parent c2d840c commit 9a24ed4

File tree

2 files changed

+36
-29
lines changed

2 files changed

+36
-29
lines changed

src/services/package-manager/PackageManagerSourceValidation.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,18 @@ export function isValidGitRepositoryUrl(url: string): boolean {
3232
// - https://gitlab.com/username/repo
3333
// - https://bitbucket.org/username/repo
3434
const httpsPattern =
35-
/^https?:\/\/(github\.com|gitlab\.com|bitbucket\.org|dev\.azure\.com)\/[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(\/.+)*(\.git)?$/
35+
/^https?:\/\/[a-zA-Z0-9_.-]+(\.[a-zA-Z0-9_.-]+)*\/[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(\/.+)*(\.git)?$/
3636

3737
// SSH pattern
3838
// Examples:
3939
// - [email protected]:username/repo.git
4040
// - [email protected]:username/repo.git
41-
const sshPattern = /^git@(github\.com|gitlab\.com|bitbucket\.org):([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)(\.git)?$/
41+
const sshPattern = /^git@[a-zA-Z0-9_.-]+(\.[a-zA-Z0-9_.-]+)*:([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)(\.git)?$/
4242

4343
// Git protocol pattern
4444
// Examples:
4545
// - git://github.com/username/repo.git
46-
const gitProtocolPattern =
47-
/^git:\/\/(github\.com|gitlab\.com|bitbucket\.org)\/[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(\.git)?$/
46+
const gitProtocolPattern = /^git:\/\/[a-zA-Z0-9_.-]+(\.[a-zA-Z0-9_.-]+)*\/[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(\.git)?$/
4847

4948
return httpsPattern.test(trimmedUrl) || sshPattern.test(trimmedUrl) || gitProtocolPattern.test(trimmedUrl)
5049
}
@@ -85,7 +84,7 @@ export function validateSourceUrl(url: string): ValidationError[] {
8584
if (!isValidGitRepositoryUrl(url)) {
8685
errors.push({
8786
field: "url",
88-
message: "URL must be a valid Git repository URL (e.g., https://github.com/username/repo)",
87+
message: "URL must be a valid Git repository URL (e.g., https://git.example.com/username/repo)",
8988
})
9089
}
9190

src/services/package-manager/__tests__/PackageManagerSourceValidation.test.ts

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,31 @@ import { PackageManagerSource } from "../types"
1212
describe("PackageManagerSourceValidation", () => {
1313
describe("isValidGitRepositoryUrl", () => {
1414
const validUrls = [
15+
// Public Git hosting services
1516
"https://github.com/username/repo",
16-
"https://github.com/username/repo.git",
1717
"https://gitlab.com/username/repo",
1818
"https://bitbucket.org/username/repo",
19-
"[email protected]:username/repo.git",
20-
"[email protected]:username/repo.git",
21-
"git://github.com/username/repo.git",
19+
20+
// Custom/self-hosted domains
21+
"https://git.company.com/username/repo",
22+
"https://git.internal.dev/username/repo.git",
23+
"[email protected]:username/repo.git",
24+
"git://git.internal.dev/username/repo.git",
25+
26+
// Subdomains and longer TLDs
27+
"https://git.dev.company.co.uk/username/repo",
28+
"[email protected]:username/repo.git",
2229
]
2330

2431
const invalidUrls = [
2532
"",
2633
" ",
2734
"not-a-url",
28-
"http://invalid-domain.com/repo",
29-
"https://github.com", // Missing username/repo
30-
"[email protected]", // Missing repo
31-
"git://invalid-domain.com/repo.git",
35+
"https://example.com", // Missing username/repo parts
36+
"[email protected]", // Missing repo part
37+
"https://git.company.com/repo", // Missing username part
38+
"git://example.com/repo", // Missing username part
39+
"https://git.company.com/", // Missing both username and repo
3240
]
3341

3442
test.each(validUrls)("should accept valid URL: %s", (url) => {
@@ -78,7 +86,7 @@ describe("PackageManagerSourceValidation", () => {
7886
expect(errors).toHaveLength(1)
7987
expect(errors[0]).toEqual({
8088
field: "url",
81-
message: "URL must be a valid Git repository URL (e.g., https://github.com/username/repo)",
89+
message: "URL must be a valid Git repository URL (e.g., https://git.example.com/username/repo)",
8290
})
8391
})
8492
})
@@ -115,13 +123,13 @@ describe("PackageManagerSourceValidation", () => {
115123

116124
describe("validateSourceDuplicates", () => {
117125
const existingSources: PackageManagerSource[] = [
118-
{ url: "https://github.com/user1/repo1", name: "Source 1", enabled: true },
119-
{ url: "https://github.com/user2/repo2", name: "Source 2", enabled: true },
126+
{ url: "https://git.company.com/user1/repo1", name: "Source 1", enabled: true },
127+
{ url: "https://git.company.com/user2/repo2", name: "Source 2", enabled: true },
120128
]
121129

122130
test("should accept unique sources", () => {
123131
const newSource: PackageManagerSource = {
124-
url: "https://github.com/user3/repo3",
132+
url: "https://git.company.com/user3/repo3",
125133
name: "Source 3",
126134
enabled: true,
127135
}
@@ -131,7 +139,7 @@ describe("PackageManagerSourceValidation", () => {
131139

132140
test("should reject duplicate URLs (case insensitive)", () => {
133141
const newSource: PackageManagerSource = {
134-
url: "HTTPS://GITHUB.COM/USER1/REPO1",
142+
url: "HTTPS://GIT.COMPANY.COM/USER1/REPO1",
135143
name: "Different Name",
136144
enabled: true,
137145
}
@@ -143,7 +151,7 @@ describe("PackageManagerSourceValidation", () => {
143151

144152
test("should reject duplicate names (case insensitive)", () => {
145153
const newSource: PackageManagerSource = {
146-
url: "https://github.com/user3/repo3",
154+
url: "https://git.company.com/user3/repo3",
147155
name: "SOURCE 1",
148156
enabled: true,
149157
}
@@ -155,9 +163,9 @@ describe("PackageManagerSourceValidation", () => {
155163

156164
test("should detect duplicates within source list", () => {
157165
const sourcesWithDuplicates: PackageManagerSource[] = [
158-
{ url: "https://github.com/user1/repo1", name: "Source 1", enabled: true },
159-
{ url: "https://github.com/user1/repo1", name: "Source 2", enabled: true }, // Duplicate URL
160-
{ url: "https://github.com/user3/repo3", name: "Source 1", enabled: true }, // Duplicate name
166+
{ url: "https://git.company.com/user1/repo1", name: "Source 1", enabled: true },
167+
{ url: "https://git.company.com/user1/repo1", name: "Source 2", enabled: true }, // Duplicate URL
168+
{ url: "https://git.company.com/user3/repo3", name: "Source 1", enabled: true }, // Duplicate name
161169
]
162170
const errors = validateSourceDuplicates(sourcesWithDuplicates)
163171
expect(errors).toHaveLength(4) // Two URL duplicates (bidirectional) and two name duplicates (bidirectional)
@@ -178,12 +186,12 @@ describe("PackageManagerSourceValidation", () => {
178186

179187
describe("validateSource", () => {
180188
const existingSources: PackageManagerSource[] = [
181-
{ url: "https://github.com/user1/repo1", name: "Source 1", enabled: true },
189+
{ url: "https://git.company.com/user1/repo1", name: "Source 1", enabled: true },
182190
]
183191

184192
test("should accept valid source", () => {
185193
const source: PackageManagerSource = {
186-
url: "https://github.com/user2/repo2",
194+
url: "https://git.company.com/user2/repo2",
187195
name: "Source 2",
188196
enabled: true,
189197
}
@@ -193,7 +201,7 @@ describe("PackageManagerSourceValidation", () => {
193201

194202
test("should accumulate multiple validation errors", () => {
195203
const source: PackageManagerSource = {
196-
url: "https://github.com/user1/repo1", // Duplicate URL
204+
url: "https://git.company.com/user1/repo1", // Duplicate URL
197205
name: "This name is way too long to be valid\t", // Too long and has tab
198206
enabled: true,
199207
}
@@ -205,17 +213,17 @@ describe("PackageManagerSourceValidation", () => {
205213
describe("validateSources", () => {
206214
test("should accept valid source list", () => {
207215
const sources: PackageManagerSource[] = [
208-
{ url: "https://github.com/user1/repo1", name: "Source 1", enabled: true },
209-
{ url: "https://github.com/user2/repo2", name: "Source 2", enabled: true },
216+
{ url: "https://git.company.com/user1/repo1", name: "Source 1", enabled: true },
217+
{ url: "https://git.company.com/user2/repo2", name: "Source 2", enabled: true },
210218
]
211219
const errors = validateSources(sources)
212220
expect(errors).toHaveLength(0)
213221
})
214222

215223
test("should detect multiple issues across sources", () => {
216224
const sources: PackageManagerSource[] = [
217-
{ url: "https://github.com/user1/repo1", name: "Source 1", enabled: true },
218-
{ url: "https://github.com/user1/repo1", name: "Source 1", enabled: true }, // Duplicate URL and name
225+
{ url: "https://git.company.com/user1/repo1", name: "Source 1", enabled: true },
226+
{ url: "https://git.company.com/user1/repo1", name: "Source 1", enabled: true }, // Duplicate URL and name
219227
{ url: "invalid-url", name: "This name is way too long\t", enabled: true }, // Invalid URL and name
220228
]
221229
const errors = validateSources(sources)

0 commit comments

Comments
 (0)