Skip to content

Commit 4b35724

Browse files
authored
feat: add a global config (#1663)
Fixes #1656
1 parent 709adc0 commit 4b35724

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed

internal/config/global_config.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package config
16+
17+
import (
18+
"fmt"
19+
)
20+
21+
// GlobalConfig defines the contract for the config.yaml file.
22+
type GlobalConfig struct {
23+
GlobalFilesAllowlist []*GlobalFile `yaml:"global_files_allowlist"`
24+
}
25+
26+
// GlobalFile defines the global files in language repositories.
27+
type GlobalFile struct {
28+
Path string `yaml:"path"`
29+
Permissions string `yaml:"permissions"`
30+
}
31+
32+
var validPermissions = map[string]bool{
33+
"read-only": true,
34+
"write-only": true,
35+
"read-write": true,
36+
}
37+
38+
// Validate checks that the GlobalConfig is valid.
39+
func (g *GlobalConfig) Validate() error {
40+
for i, globalFile := range g.GlobalFilesAllowlist {
41+
path, permissions := globalFile.Path, globalFile.Permissions
42+
if !isValidDirPath(path) {
43+
return fmt.Errorf("invalid global file path at index %d: %q", i, path)
44+
}
45+
if _, ok := validPermissions[permissions]; !ok {
46+
return fmt.Errorf("invalid global file permissions at index %d: %q", i, permissions)
47+
}
48+
}
49+
50+
return nil
51+
}

internal/config/global_config_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package config
16+
17+
import (
18+
"strings"
19+
"testing"
20+
)
21+
22+
func TestGlobalConfig_Validate(t *testing.T) {
23+
for _, test := range []struct {
24+
name string
25+
config *GlobalConfig
26+
wantErr bool
27+
wantErrMsg string
28+
}{
29+
{
30+
name: "valid config",
31+
config: &GlobalConfig{
32+
GlobalFilesAllowlist: []*GlobalFile{
33+
{
34+
Path: "a/path",
35+
Permissions: "read-only",
36+
},
37+
{
38+
Path: "another/path",
39+
Permissions: "write-only",
40+
},
41+
{
42+
Path: "other/paths",
43+
Permissions: "read-write",
44+
},
45+
},
46+
},
47+
},
48+
{
49+
name: "invalid path in config",
50+
config: &GlobalConfig{
51+
GlobalFilesAllowlist: []*GlobalFile{
52+
{
53+
Path: "a/path",
54+
Permissions: "read-only",
55+
},
56+
{
57+
Path: "/another/absolute/path",
58+
Permissions: "write-only",
59+
},
60+
},
61+
},
62+
wantErr: true,
63+
wantErrMsg: "invalid global file path",
64+
},
65+
{
66+
name: "invalid permission in config",
67+
config: &GlobalConfig{
68+
GlobalFilesAllowlist: []*GlobalFile{
69+
{
70+
Path: "a/path",
71+
Permissions: "write-only",
72+
},
73+
{
74+
Path: "another/path",
75+
Permissions: "unknown",
76+
},
77+
},
78+
},
79+
wantErr: true,
80+
wantErrMsg: "invalid global file permissions",
81+
},
82+
} {
83+
t.Run(test.name, func(t *testing.T) {
84+
err := test.config.Validate()
85+
if test.wantErr {
86+
if err == nil {
87+
t.Errorf("GlobalConfig.Validate() should return error")
88+
}
89+
90+
if !strings.Contains(err.Error(), test.wantErrMsg) {
91+
t.Errorf("GlobalConfig.Validate() err = %v, want error containing %q", err, test.wantErrMsg)
92+
}
93+
94+
return
95+
}
96+
97+
if err != nil {
98+
t.Errorf("GlobalConfig.Validate() error = %v, wantErr %v", err, test.wantErr)
99+
}
100+
})
101+
}
102+
}

0 commit comments

Comments
 (0)