Skip to content

Commit

Permalink
Exit Codes (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
fmenezes authored Aug 18, 2020
1 parent b666551 commit 7dd54d6
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 86 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ Simply calling `codeowners` will kick off the cli on the current directory.
| d | . | Directory: specifies the directory you want to use to lint the CODEOWNERS file |
| f | | Format: specifies the format you want to return lint results |

##### Exit Codes

| Exit Code | Description |
| ------------- | ---------------------------------------------------------------- |
| 0 | Success: no errors returned |
| 1 | Warnings: linter returned a few warnings but no errors |
| 2 | Errors: linter returned a few errors |
| 3 | Unexpected errors: errors that prevented the linter from running |

## Compatibility

:warning: This module is on a v0 mode and it is not ready to be used, once it reaches the v1 we will lock the API.
43 changes: 33 additions & 10 deletions cmd/codeowners/linter.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"fmt"
"io"
"path/filepath"
"text/template"
Expand All @@ -14,33 +15,55 @@ type options struct {
format string
}

func run(wr io.Writer, opt options) error {
type exitCode int

const (
successCode exitCode = iota
warningCode
errorCode
unexpectedErrorCode
)

func run(wr io.Writer, opt options) exitCode {
dir, err := filepath.Abs(opt.directory)
if err != nil {
return err
fmt.Fprintf(wr, "Unexpected error when parsing directory: %v", err)
return unexpectedErrorCode
}

format := "{{range .}}{{ .Position }} ::{{ .Severity }}:: {{ .Message }} [{{ .CheckName }}]\n{{end}}"
format := "{{ .Position }} ::{{ .Severity }}:: {{ .Message }} [{{ .CheckName }}]"
if len(opt.format) > 0 {
format = opt.format
}
format = fmt.Sprintf("%s\n", format)
tpl, err := template.New("main").Parse(format)
if err != nil {
return err
fmt.Fprintf(wr, "Unexpected error when parsing format: %v", err)
return unexpectedErrorCode
}

checkers := codeowners.AvailableCheckers()

checks, _ := codeowners.Check(dir, checkers...)

if len(checks) > 0 {
err = tpl.Execute(wr, checks)
code := successCode
for _, check := range checks {
err = tpl.Execute(wr, check)
if err != nil {
return err
fmt.Fprintf(wr, "Unexpected error when writing results: %v", err)
return unexpectedErrorCode
}
switch check.Severity {
case codeowners.Error:
if code < errorCode {
code = errorCode
}
case codeowners.Warning:
if code < warningCode {
code = warningCode
}
}
} else {
wr.Write([]byte("Everything ok ;)\n"))
}

return nil
return code
}
117 changes: 45 additions & 72 deletions cmd/codeowners/linter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,104 +5,77 @@ import (
"testing"
)

func testRun(opt options) (string, error) {
func testRun(opt options) (string, exitCode) {
var output bytes.Buffer
err := run(&output, opt)
if err != nil {
return "", err
}
return output.String(), nil
exitCode := run(&output, opt)
return output.String(), exitCode
}

func TestPass(t *testing.T) {
opt := options{
directory: "../../test/data/pass",
format: "",
}
func assertCode(t *testing.T, opt options, want exitCode) {
_, got := testRun(opt)

got, err := testRun(opt)
if err != nil {
t.Error(err)
if got != want {
t.Errorf("Input: %v Want: %d Got: %d", opt, want, got)
}
}

want := `Everything ok ;)
`
if got != want {
t.Errorf("Input: %v Want: '%s' Got: '%s'", opt, want, got)
func assert(t *testing.T, opt options, wantCode exitCode, want string) {
got, gotCode := testRun(opt)

if gotCode != wantCode || got != want {
t.Errorf("Input: %v Want: %d '%s' Got: %d '%s'", opt, wantCode, want, gotCode, got)
}
}

func TestPass(t *testing.T) {
assertCode(t, options{
directory: "../../test/data/pass",
format: "",
}, successCode)
}

func TestNoOwners(t *testing.T) {
opt := options{
assert(t, options{
directory: "../../test/data/no_owners",
format: "",
}

got, err := testRun(opt)
if err != nil {
t.Error(err)
}

want := `1 ::Error:: No owners specified [NoOwner]
`
if got != want {
t.Errorf("Input: %v Want: '%s' Got: '%s'", opt, want, got)
}
}, errorCode, `1 ::Error:: No owners specified [NoOwner]
`)
}

func TestCustomFormat(t *testing.T) {
opt := options{
assert(t, options{
directory: "../../test/data/noowners",
format: "test",
}

got, err := testRun(opt)
if err != nil {
t.Error(err)
}

want := `test`
if got != want {
t.Errorf("Input: %v Want: '%s' Got: '%s'", opt, want, got)
}
}, errorCode, `test
`)
}

func TestInvalidFormat(t *testing.T) {
opt := options{
func TestInvalidFormatParse(t *testing.T) {
assertCode(t, options{
directory: "../../test/data/noowners",
format: " {{template \"one\"}} ",
}

_, err := testRun(opt)
if err == nil {
t.Errorf("Should have errored")
}
format: " {{template \"one ",
}, unexpectedErrorCode)
}

opt = options{
func TestInvalidFormatExec(t *testing.T) {
assertCode(t, options{
directory: "../../test/data/noowners",
format: " {{ . ",
}

_, err = testRun(opt)
if err == nil {
t.Errorf("Should have errored")
}
format: " {{template \"one\"}} ",
}, unexpectedErrorCode)
}

func TestInvalidDirectory(t *testing.T) {
opt := options{
assert(t, options{
directory: "'",
format: "",
}

got, err := testRun(opt)
if err != nil {
t.Error(err)
}
}, errorCode, `0 ::Error:: No CODEOWNERS file found [NoCodeowners]
`)
}

want := `0 ::Error:: No CODEOWNERS file found [NoCodeowners]
`
if got != want {
t.Errorf("Input: %v Want: '%s' Got: '%s'", opt, want, got)
}
func TestMultipleCodeOwners(t *testing.T) {
assert(t, options{
directory: "../../test/data/multiple_codeowners",
format: "",
}, warningCode, `0 ::Warning:: Multiple CODEOWNERS files found (CODEOWNERS, docs/CODEOWNERS) [MultipleCodeowners]
`)
}
10 changes: 6 additions & 4 deletions cmd/codeowners/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package main

import (
"flag"
"log"
"fmt"
"os"
)

Expand All @@ -17,8 +17,10 @@ func main() {
directory: *dir,
format: *format,
}

if err := run(os.Stdout, opt); err != nil {
log.Fatal(err)
exitCode := run(os.Stderr, opt)
if exitCode == successCode {
fmt.Println("Everything ok ;)")
return
}
os.Exit(int(exitCode))
}

0 comments on commit 7dd54d6

Please sign in to comment.