Skip to content

Commit 6f4ce53

Browse files
committed
Merge remote-tracking branch 'origin/main' into dependabot/npm_and_yarn/markdown-to-jsx-9.8.0
2 parents 95a6247 + 3bf16cf commit 6f4ce53

2 files changed

Lines changed: 142 additions & 3 deletions

File tree

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { aplCodeRepoApiSchema } from './create-edit-codeRepositories.validator'
2+
3+
const baseRepo = {
4+
kind: 'AplTeamCodeRepo',
5+
spec: {
6+
gitService: 'github',
7+
repositoryUrl: 'https://github.com/linode/apl-examples',
8+
private: false,
9+
},
10+
metadata: {
11+
name: 'repo-name',
12+
labels: {
13+
'apl.io/teamId': 'team1',
14+
},
15+
},
16+
status: {},
17+
}
18+
19+
describe('aplCodeRepoApiSchema', () => {
20+
describe('repositoryUrl validation', () => {
21+
it.each(['https://github.com/linode/apl-examples', 'git@github.com:linode/apl-examples.git'])(
22+
'accepts valid github url: %s',
23+
async (repositoryUrl) => {
24+
await expect(
25+
aplCodeRepoApiSchema.validate({
26+
...baseRepo,
27+
spec: {
28+
...baseRepo.spec,
29+
gitService: 'github',
30+
repositoryUrl,
31+
},
32+
}),
33+
).resolves.toBeTruthy()
34+
},
35+
)
36+
37+
it('rejects duplicate url when only .git differs', async () => {
38+
await expect(
39+
aplCodeRepoApiSchema.validate(
40+
{
41+
...baseRepo,
42+
spec: {
43+
...baseRepo.spec,
44+
repositoryUrl: 'https://github.com/linode/apl-examples.git',
45+
},
46+
},
47+
{
48+
context: {
49+
validateOnSubmit: true,
50+
codeRepoUrls: ['https://github.com/linode/apl-examples'],
51+
},
52+
},
53+
),
54+
).rejects.toThrow('Repository URL must be unique.')
55+
})
56+
57+
it('rejects duplicate url when only trailing slash differs', async () => {
58+
await expect(
59+
aplCodeRepoApiSchema.validate(
60+
{
61+
...baseRepo,
62+
spec: {
63+
...baseRepo.spec,
64+
repositoryUrl: 'https://github.com/linode/apl-examples/',
65+
},
66+
},
67+
{
68+
context: {
69+
validateOnSubmit: true,
70+
codeRepoUrls: ['https://github.com/linode/apl-examples'],
71+
},
72+
},
73+
),
74+
).rejects.toThrow('Repository URL must be unique.')
75+
})
76+
77+
it('accepts unique repository url', async () => {
78+
await expect(
79+
aplCodeRepoApiSchema.validate(baseRepo, {
80+
context: {
81+
validateOnSubmit: true,
82+
codeRepoUrls: ['https://github.com/linode/other-repo'],
83+
},
84+
}),
85+
).resolves.toBeTruthy()
86+
})
87+
88+
it('skips uniqueness validation when validateOnSubmit is false', async () => {
89+
await expect(
90+
aplCodeRepoApiSchema.validate(baseRepo, {
91+
context: {
92+
validateOnSubmit: false,
93+
codeRepoUrls: ['https://github.com/linode/apl-examples'],
94+
},
95+
}),
96+
).resolves.toBeTruthy()
97+
})
98+
})
99+
100+
describe('private repository secret', () => {
101+
it('requires secret when private=true', async () => {
102+
await expect(
103+
aplCodeRepoApiSchema.validate({
104+
...baseRepo,
105+
spec: {
106+
...baseRepo.spec,
107+
private: true,
108+
},
109+
}),
110+
).rejects.toThrow('Secret is required when private is true.')
111+
})
112+
113+
it('accepts secret when private=true', async () => {
114+
await expect(
115+
aplCodeRepoApiSchema.validate({
116+
...baseRepo,
117+
spec: {
118+
...baseRepo.spec,
119+
private: true,
120+
secret: 'my-secret',
121+
},
122+
}),
123+
).resolves.toBeTruthy()
124+
})
125+
})
126+
})

src/pages/code-repositories/create-edit/create-edit-codeRepositories.validator.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import * as yup from 'yup'
22

3+
const normalizeRepoUrl = (url: string) =>
4+
url
5+
.trim()
6+
.replace(/\/$/, '') // remove trailing slash
7+
.replace(/\.git$/, '') // remove trailing .git
8+
.toLowerCase()
9+
310
const repoUrlValidation = yup
411
.string()
512
.test('is-valid-url', 'Invalid URL for the selected git service', function (value) {
@@ -8,15 +15,21 @@ const repoUrlValidation = yup
815
if (!value || !gitService) return true
916

1017
if (gitService === 'gitea') return value.startsWith('https://gitea')
18+
1119
if (gitService === 'github') return /^(https:\/\/github\.com\/.+|git@github\.com:.+\.git)$/.test(value)
20+
1221
if (gitService === 'gitlab') return /^(https:\/\/gitlab\.com\/.+|git@gitlab\.com:.+\.git)$/.test(value)
22+
1323
return true
1424
})
1525
.test('is-unique', 'Repository URL must be unique.', function (value) {
1626
const { codeRepoUrls, validateOnSubmit } = (this.options.context || {}) as any
17-
if (!validateOnSubmit) return true
18-
if (!value) return true
19-
return !codeRepoUrls?.some((repoUrl: string) => repoUrl === value)
27+
28+
if (!validateOnSubmit || !value) return true
29+
30+
const normalizedValue = normalizeRepoUrl(value)
31+
32+
return !codeRepoUrls?.some((repoUrl: string) => normalizeRepoUrl(repoUrl) === normalizedValue)
2033
})
2134

2235
export const aplCodeRepoApiSchema = yup.object({

0 commit comments

Comments
 (0)