-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchecker.go
116 lines (97 loc) · 2.84 KB
/
checker.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package codeowners
import (
"bufio"
"fmt"
"os"
"path/filepath"
"strings"
)
var availableCheckers map[string]Checker
func init() {
availableCheckers = make(map[string]Checker)
}
// AvailableCheckers returns list of registered checkers
func AvailableCheckers() []string {
names := make([]string, len(availableCheckers))
i := 0
for checkerName := range availableCheckers {
names[i] = checkerName
i++
}
return names
}
// RegisterChecker adds checker to be used later when checking CODEOWNERS files
func RegisterChecker(name string, checker Checker) error {
_, found := availableCheckers[name]
if found {
return fmt.Errorf("Checker %s already exists", name)
}
availableCheckers[name] = checker
return nil
}
// Check evaluates the file contents against the checkers and return the results back.
func Check(options CheckOptions) ([]CheckResult, error) {
fileLocation, result := findCodeownersFile(options.Directory)
if result != nil {
return []CheckResult{*result}, nil
}
file, err := os.Open(filepath.Join(options.Directory, fileLocation))
if err != nil {
return nil, err
}
defer file.Close()
results := []CheckResult{}
scanner := bufio.NewScanner(file)
lineNo := 0
validators := make(map[string]Validator)
for _, checker := range options.Checkers {
c, ok := availableCheckers[checker]
if !ok {
return nil, fmt.Errorf("'%s' not found", checker)
}
validators[checker] = c.NewValidator(ValidatorOptions{
Directory: options.Directory,
CodeownersFileLocation: fileLocation,
GithubToken: options.GithubToken,
GithubTokenType: options.GithubTokenType,
})
}
for scanner.Scan() {
line := scanner.Text()
lineNo++
for _, c := range validators {
lineResults := c.ValidateLine(lineNo, line)
if lineResults != nil {
results = append(results, lineResults...)
}
}
}
if len(results) > 0 {
return results, nil
}
return nil, nil
}
func fileExists(file string) bool {
info, err := os.Stat(file)
return !os.IsNotExist(err) && !info.IsDir()
}
func findCodeownersFile(dir string) (string, *CheckResult) {
codeownersLocation := ""
filesFound := []string{}
for _, fileLocation := range DefaultLocations {
currentFile := filepath.Join(dir, fileLocation)
if fileExists(currentFile) {
filesFound = append(filesFound, fileLocation)
if len(codeownersLocation) == 0 {
codeownersLocation = fileLocation
}
}
}
if len(filesFound) == 0 {
return "", &CheckResult{Position: Position{FilePath: "CODEOWNERS"}, Message: "No CODEOWNERS file found", Severity: Error, CheckName: "NoCodeowners"}
}
if len(filesFound) > 1 {
return "", &CheckResult{Position: Position{FilePath: codeownersLocation}, Message: fmt.Sprintf("Multiple CODEOWNERS files found (%s)", strings.Join(filesFound, ", ")), Severity: Warning, CheckName: "MultipleCodeowners"}
}
return codeownersLocation, nil
}