github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/scripts/run-linter.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "flag" 6 "fmt" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "runtime" 11 "strings" 12 "time" 13 ) 14 15 type result struct { 16 name string 17 cmd string 18 passed bool 19 duration time.Duration 20 output []string 21 } 22 23 // String prints the results of a linter run in gotest format. 24 func (r *result) String() string { 25 buf := &bytes.Buffer{} 26 27 fmt.Fprintln(buf, "=== RUN", r.name) 28 if r.passed { 29 fmt.Fprintf(buf, "--- PASS: %s (%s)", r.name, r.duration) 30 } else { 31 // fmt.Fprintln(buf, " CMD:", r.cmd) 32 fmt.Fprintf(buf, strings.Join(r.output, "\n")) 33 fmt.Fprintf(buf, "--- FAIL: %s (%s)", r.name, r.duration) 34 } 35 36 return buf.String() 37 } 38 39 // fixup goes through the output and improves the output generated by 40 // specific linters so that all output includes the relative path to the 41 // error, instead of mixing relative and absolute paths. 42 func (r *result) fixup(dirname string) { 43 for idx, ln := range r.output { 44 if strings.HasPrefix(ln, dirname) { 45 r.output[idx] = ln[len(dirname)+1:] 46 } 47 } 48 } 49 50 // runs the gometalinter on a list of packages; integrating with the "make lint" target. 51 func main() { 52 var ( 53 lintArgs string 54 lintBin string 55 packageList string 56 output string 57 packages []string 58 results []*result 59 hasFailingTest bool 60 61 gopath = os.Getenv("GOPATH") 62 ) 63 64 flag.StringVar(&lintArgs, "lintArgs", "", "args to pass to gometalinter") 65 flag.StringVar(&lintBin, "lintBin", filepath.Join(gopath, "bin", "gometalinter"), "path to go metalinter") 66 flag.StringVar(&packageList, "packages", "", "list of space separated packages") 67 flag.StringVar(&output, "output", "", "output file for to write results.") 68 flag.Parse() 69 70 packages = strings.Split(strings.Replace(packageList, "-", "/", -1), " ") 71 dirname, _ := os.Getwd() 72 cwd := filepath.Base(dirname) 73 gopath, _ = filepath.Abs(gopath) 74 lintArgs += fmt.Sprintf(" --concurrency=%d", runtime.NumCPU()/2) 75 76 for _, pkg := range packages { 77 args := []string{lintBin, lintArgs} 78 if cwd == pkg { 79 args = append(args, ".") 80 } else { 81 args = append(args, "./"+pkg) 82 } 83 84 startAt := time.Now() 85 cmd := strings.Join(args, " ") 86 out, err := exec.Command("sh", "-c", cmd).CombinedOutput() 87 88 r := &result{ 89 cmd: strings.Join(args, " "), 90 name: "lint-" + strings.Replace(pkg, "/", "-", -1), 91 passed: err == nil, 92 duration: time.Since(startAt), 93 output: strings.Split(string(out), "\n"), 94 } 95 r.fixup(dirname) 96 97 if !r.passed { 98 hasFailingTest = true 99 } 100 101 results = append(results, r) 102 fmt.Println(r) 103 } 104 105 if output != "" { 106 f, err := os.Create(output) 107 if err != nil { 108 os.Exit(1) 109 } 110 defer func() { 111 if err != f.Close() { 112 panic(err) 113 } 114 }() 115 116 for _, r := range results { 117 f.WriteString(r.String() + "\n") 118 } 119 } 120 121 if hasFailingTest { 122 os.Exit(1) 123 } 124 }