Skip to content

Commit b647db6

Browse files
committed
Improved validation and testing
1 parent 8d75f43 commit b647db6

File tree

2 files changed

+115
-48
lines changed

2 files changed

+115
-48
lines changed

config.go

+51-32
Original file line numberDiff line numberDiff line change
@@ -198,62 +198,81 @@ func validateConfig(yamlData []byte) error {
198198
return err
199199
}
200200

201-
// defaults and repositories sections are mandatory
202-
if _, ok := raw["defaults"]; !ok {
203-
return fmt.Errorf("defaults config section is missing")
201+
// skip checks if ".repositories" is empty
202+
if raw["repositories"] == nil {
203+
return nil
204204
}
205205

206-
if _, ok := raw["repositories"]; !ok {
207-
return fmt.Errorf("repositories config section is missing")
208-
}
209-
210-
// check config sections for unexpected keys
206+
// check all root config sections for unexpected keys
211207
allowedRepoPoolConfig := getAllowedKeys(mirror.RepoPoolConfig{})
212208
if key := findUnexpectedKey(raw, allowedRepoPoolConfig); key != "" {
213209
return fmt.Errorf("unexpected key: .%v", key)
214210
}
215211

216-
// check "defaults" section
217-
defaultsMap, ok := raw["defaults"].(map[string]interface{})
218-
if !ok {
219-
return fmt.Errorf("defaults section is missing or not valid")
220-
}
221-
allowedDefaults := getAllowedKeys(mirror.DefaultConfig{})
212+
// check ".defaults"
213+
if _, exists := raw["defaults"]; exists {
214+
defaultsMap, ok := raw["defaults"].(map[string]interface{})
215+
if !ok {
216+
return fmt.Errorf(".defaults config is not valid")
217+
}
218+
allowedDefaults := getAllowedKeys(mirror.DefaultConfig{})
222219

223-
if key := findUnexpectedKey(defaultsMap, allowedDefaults); key != "" {
224-
return fmt.Errorf("unexpected key: .defaults.%v", key)
225-
}
220+
if key := findUnexpectedKey(defaultsMap, allowedDefaults); key != "" {
221+
return fmt.Errorf("unexpected key: .defaults.%v", key)
222+
}
226223

227-
// check "auth" section in "defaults"
228-
if authMap, ok := defaultsMap["auth"].(map[string]interface{}); ok {
229-
allowedAuthKeys := getAllowedKeys(mirror.Auth{})
230-
if key := findUnexpectedKey(authMap, allowedAuthKeys); key != "" {
231-
return fmt.Errorf("unexpected key: .defaults.auth.%v", key)
224+
// check ".defaults.auth"
225+
if authMap, ok := defaultsMap["auth"].(map[string]interface{}); ok {
226+
allowedAuthKeys := getAllowedKeys(mirror.Auth{})
227+
if key := findUnexpectedKey(authMap, allowedAuthKeys); key != "" {
228+
return fmt.Errorf("unexpected key: .defaults.auth.%v", key)
229+
}
232230
}
233231
}
234232

235-
// check each repository in "repositories" section
233+
// check ".repositories"
234+
reposInterface, ok := raw["repositories"].([]interface{})
235+
if !ok {
236+
return fmt.Errorf(".repositories config must be an array")
237+
}
238+
239+
// check each repository in ".repositories"
236240
allowedRepoKeys := getAllowedKeys(mirror.RepositoryConfig{})
237-
for _, repoInterface := range raw["repositories"].([]interface{}) {
241+
242+
for _, repoInterface := range reposInterface {
238243
repoMap, ok := repoInterface.(map[string]interface{})
239244
if !ok {
240-
return fmt.Errorf("repositories config section is not valid")
245+
return fmt.Errorf(".repositories config is not valid")
241246
}
242247

243248
if key := findUnexpectedKey(repoMap, allowedRepoKeys); key != "" {
244249
return fmt.Errorf("unexpected key: .repositories[%v].%v", repoMap["remote"], key)
245250
}
246251

247-
// check each "worktrees" section in each repository
248-
for _, worktreeInterface := range repoMap["worktrees"].([]interface{}) {
249-
worktreeMap, ok := worktreeInterface.(map[string]interface{})
252+
// check "worktrees" in each repository
253+
if worktreesInterface, exists := repoMap["worktrees"]; exists {
254+
_, ok := repoMap["worktrees"].([]interface{})
250255
if !ok {
251-
return fmt.Errorf("worktrees config section is not valid in .repositories[%v]", repoMap["remote"])
256+
return fmt.Errorf("worktrees config must be an array in .repositories[%v]", repoMap["remote"])
252257
}
253258

254-
allowedWorktreeKeys := getAllowedKeys(mirror.WorktreeConfig{})
255-
if key := findUnexpectedKey(worktreeMap, allowedWorktreeKeys); key != "" {
256-
return fmt.Errorf("unexpected key: .repositories[%v].worktrees[%v].%v", repoMap["remote"], worktreeMap["link"], key)
259+
for _, worktreeInterface := range worktreesInterface.([]interface{}) {
260+
worktreeMap, ok := worktreeInterface.(map[string]interface{})
261+
if !ok {
262+
return fmt.Errorf("worktrees config is not valid in .repositories[%v]", repoMap["remote"])
263+
}
264+
265+
allowedWorktreeKeys := getAllowedKeys(mirror.WorktreeConfig{})
266+
if key := findUnexpectedKey(worktreeMap, allowedWorktreeKeys); key != "" {
267+
return fmt.Errorf("unexpected key: .repositories[%v].worktrees[%v].%v", repoMap["remote"], worktreeMap["link"], key)
268+
}
269+
270+
// Check "pathspecs" in each worktree
271+
if pathspecsInterface, exists := worktreeMap["pathspecs"]; exists {
272+
if _, ok := pathspecsInterface.([]interface{}); !ok {
273+
return fmt.Errorf("pathspecs config must be an array in .repositories[%v].worktrees[%v]", repoMap["remote"], worktreeMap["link"])
274+
}
275+
}
257276
}
258277
}
259278
}

config_test.go

+64-16
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ func Test_validateConfig(t *testing.T) {
240240
wantError bool
241241
}{
242242
{
243-
name: "valid",
243+
name: "valid - full config",
244244
yamlData: []byte(`
245245
defaults:
246246
root: /tmp/git-mirror
@@ -257,16 +257,43 @@ repositories:
257257
worktrees:
258258
- link: aaa
259259
ref: main
260-
pathspecs:
261-
- readme.md
262260
- link: bbb
263261
ref: main
264262
- remote: https://github.com/utilitywarehouse/another-repo
263+
root: /some/other/location
264+
link_root: /some/path
265+
interval: 1m
266+
mirror_timeout: 5m
267+
git_gc: always
268+
auth:
269+
ssh_key_path: /some/other/location
270+
ssh_known_hosts_path: /some/other/location
265271
worktrees:
266-
- link: ccc
272+
- link: alerts
267273
ref: main
268274
pathspecs:
269-
- readme.md
275+
- path
276+
- path2/*.yaml
277+
`),
278+
wantError: false,
279+
},
280+
{
281+
name: "valid - empty config",
282+
yamlData: []byte(`
283+
`),
284+
wantError: false,
285+
},
286+
{
287+
name: "valid - defaults config only",
288+
yamlData: []byte(`
289+
defaults:
290+
`),
291+
wantError: false,
292+
},
293+
{
294+
name: "valid - repositories config only",
295+
yamlData: []byte(`
296+
repositories:
270297
`),
271298
wantError: false,
272299
},
@@ -285,61 +312,81 @@ repositories:
285312
wantError: true,
286313
},
287314
{
288-
name: "invalid - defaults missing",
315+
name: "invalid - unexpected key in defaults",
289316
yamlData: []byte(`
317+
defaults:
318+
root: /tmp/git-mirror
319+
not_valid: test
320+
290321
repositories:
291322
- remote: https://github.com/utilitywarehouse/git-mirror
292323
`),
293324
wantError: true,
294325
},
295326
{
296-
name: "invalid - repositories missing",
327+
name: "invalid - unexpected key in auth",
297328
yamlData: []byte(`
298329
defaults:
299330
root: /tmp/git-mirror
331+
not_valid: test
332+
auth:
333+
not_valid: test
334+
335+
repositories:
336+
- remote: https://github.com/utilitywarehouse/git-mirror
300337
`),
301338
wantError: true,
302339
},
303340
{
304-
name: "invalid - unexpected key in defaults",
341+
name: "invalid - unexpected key in repositories",
305342
yamlData: []byte(`
306343
defaults:
307344
root: /tmp/git-mirror
308-
not_valid: test
309345
310346
repositories:
311347
- remote: https://github.com/utilitywarehouse/git-mirror
348+
not_valid: test
312349
`),
313350
wantError: true,
314351
},
315352
{
316-
name: "invalid - unexpected key in auth",
353+
name: "invalid - unexpected key in repository worktrees",
317354
yamlData: []byte(`
318355
defaults:
319356
root: /tmp/git-mirror
320-
not_valid: test
321-
auth:
322-
not_valid: test
323357
324358
repositories:
325359
- remote: https://github.com/utilitywarehouse/git-mirror
360+
worktrees:
361+
- link: aaa
362+
not_valid: test
326363
`),
327364
wantError: true,
328365
},
329366
{
330-
name: "invalid - unexpected key in repositories",
367+
name: "invalid - repositories is not an array",
368+
yamlData: []byte(`
369+
defaults:
370+
root: /tmp/git-mirror
371+
372+
repositories: https://github.com/utilitywarehouse/git-mirror
373+
`),
374+
wantError: true,
375+
},
376+
{
377+
name: "invalid - worktrees is not an array",
331378
yamlData: []byte(`
332379
defaults:
333380
root: /tmp/git-mirror
334381
335382
repositories:
336383
- remote: https://github.com/utilitywarehouse/git-mirror
337-
not_valid: test
384+
worktrees: test
338385
`),
339386
wantError: true,
340387
},
341388
{
342-
name: "invalid - unexpected key in repository worktrees",
389+
name: "invalid - pathspecs is not an array",
343390
yamlData: []byte(`
344391
defaults:
345392
root: /tmp/git-mirror
@@ -349,6 +396,7 @@ repositories:
349396
worktrees:
350397
- link: aaa
351398
not_valid: test
399+
pathspecs: readme.md
352400
`),
353401
wantError: true,
354402
},

0 commit comments

Comments
 (0)