├── sh ├── testdata │ ├── success.sh │ ├── malformat.sh │ └── shellcheck.sh ├── sh_test.go ├── check.go ├── sh.go └── fmt.go ├── .gitignore ├── renovate.json ├── .github └── dependabot.yml ├── status ├── status_test.go └── status.go ├── Dockerfile ├── main_test.go ├── .travis.yml ├── go.mod ├── goreleaser.yml ├── get.sh ├── Makefile ├── LICENSE.md ├── CONTRIBUTING.md ├── README.md ├── main.go ├── go.sum └── CODE_OF_CONDUCT.md /sh/testdata/success.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo foo 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | coverage.txt 3 | dist 4 | bin 5 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /sh/testdata/malformat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | foo() { 4 | echo hi 5 | } 6 | 7 | foo 8 | -------------------------------------------------------------------------------- /sh/testdata/shellcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | foo() { 4 | echo hi 5 | } 6 | 7 | foo $@ 8 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "08:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /status/status_test.go: -------------------------------------------------------------------------------- 1 | package status 2 | 3 | import "testing" 4 | 5 | func TestAllStatuses(t *testing.T) { 6 | var file = "/path/to/my/file.sh" 7 | Ignore(file) 8 | Success(file) 9 | Fail(file) 10 | } 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | LABEL maintainer="docker@carlosbecker.com" 3 | ENTRYPOINT ["/usr/local/bin/shcheck"] 4 | CMD [ "-h" ] 5 | 6 | RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/* 7 | 8 | COPY shcheck /usr/local/bin/shcheck 9 | -------------------------------------------------------------------------------- /main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestIgnore(t *testing.T) { 10 | var assert = assert.New(t) 11 | assert.True(ignore([]string{"vendor/**/*"}, "vendor/blah/adad/asdasd")) 12 | assert.False(ignore([]string{"vendor/**"}, "vendor/blah/adad/asdasd")) 13 | } 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: '1.13.x' 3 | env: 4 | - GO111MODULE=on 5 | install: make setup 6 | script: make ci 7 | after_success: 8 | - bash <(curl -s https://codecov.io/bash) 9 | notifications: 10 | email: false 11 | deploy: 12 | - provider: script 13 | skip_cleanup: true 14 | script: curl -sL http://git.io/goreleaser | bash 15 | on: 16 | tags: true 17 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/caarlos0/shcheck 2 | 3 | require ( 4 | github.com/alecthomas/kingpin v2.2.6+incompatible 5 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect 6 | github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect 7 | github.com/fatih/color v1.12.0 8 | github.com/mattn/go-zglob v0.0.3 9 | github.com/pmezard/go-difflib v1.0.0 10 | github.com/stretchr/testify v1.7.0 11 | ) 12 | 13 | go 1.13 14 | -------------------------------------------------------------------------------- /status/status.go: -------------------------------------------------------------------------------- 1 | package status 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/fatih/color" 7 | ) 8 | 9 | // Success status 10 | func Success(file string) { 11 | print(" OK ", file, color.FgGreen) 12 | } 13 | 14 | // Fail status 15 | func Fail(file string) { 16 | print("FAIL", file, color.FgRed) 17 | } 18 | 19 | // Ignore status 20 | func Ignore(file string) { 21 | print("SKIP", file, color.FgWhite) 22 | } 23 | 24 | func print(text, file string, col color.Attribute) { 25 | fmt.Printf( 26 | "[%s] %s\n", 27 | color.New(col).Sprint(text), 28 | color.New(color.Bold).Sprint(file), 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /goreleaser.yml: -------------------------------------------------------------------------------- 1 | archives: 2 | - name_template: '{{ .Binary }}_{{ .Os }}_{{ .Arch }}' 3 | replacements: 4 | darwin: Darwin 5 | linux: Linux 6 | 386: i386 7 | amd64: x86_64 8 | brews: 9 | - folder: Formula 10 | github: 11 | owner: caarlos0 12 | name: homebrew-tap 13 | dockers: 14 | - image_templates: 15 | - "caarlos0/shcheck:latest" 16 | - "caarlos0/shcheck:{{ .Tag }}" 17 | build_flag_templates: 18 | - "--label=org.label-schema.schema-version=1.0" 19 | - "--label=org.label-schema.version={{ .Version }}" 20 | - "--label=org.label-schema.name={{ .ProjectName }}" 21 | -------------------------------------------------------------------------------- /sh/sh_test.go: -------------------------------------------------------------------------------- 1 | package sh 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestSuccess(t *testing.T) { 10 | var assert = assert.New(t) 11 | for _, checker := range Checkers(Options{}) { 12 | assert.NoError(checker.Check("testdata/success.sh")) 13 | } 14 | } 15 | 16 | func TestShellcheckError(t *testing.T) { 17 | var assert = assert.New(t) 18 | var checker = &shellcheck{} 19 | assert.Error(checker.Check("testdata/shellcheck.sh")) 20 | } 21 | 22 | func TestShfmtError(t *testing.T) { 23 | var assert = assert.New(t) 24 | var checker = &shfmt{} 25 | assert.Error(checker.Check("testdata/malformat.sh")) 26 | } 27 | -------------------------------------------------------------------------------- /get.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | TAR_FILE="/tmp/shcheck.tar.gz" 5 | DOWNLOAD_URL="https://github.com/caarlos0/shcheck/releases/download" 6 | 7 | get_latest() { 8 | url="https://api.github.com/repos/caarlos0/shcheck/releases/latest" 9 | if test -n "$GITHUB_TOKEN"; then 10 | curl --fail -sSL -H "Authorization: token $GITHUB_TOKEN" "$url" 11 | else 12 | curl --fail -sSL "$url" 13 | fi 14 | } 15 | 16 | last_version() { 17 | get_latest | 18 | grep tag_name | 19 | cut -f4 -d'"' 20 | } 21 | 22 | download() { 23 | test -z "$VERSION" && VERSION="$(last_version)" 24 | test -z "$VERSION" && { 25 | echo "Unable to get caarlos0/shcheck version." >&2 26 | get_latest 27 | exit 1 28 | } 29 | rm -f "$TAR_FILE" 30 | curl -s -L -o "$TAR_FILE" \ 31 | "$DOWNLOAD_URL/$VERSION/shcheck_$(uname -s)_$(uname -m).tar.gz" 32 | } 33 | 34 | download 35 | tar -xf "$TAR_FILE" -C /tmp 36 | # shellcheck disable=SC2048,SC2086 37 | /tmp/shcheck $* 38 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SOURCE_FILES?=./... 2 | TEST_PATTERN?=. 3 | TEST_OPTIONS?= 4 | 5 | export PATH := ./bin:$(PATH) 6 | export GO111MODULE := on 7 | 8 | # Install all the build and lint dependencies 9 | setup: 10 | curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh 11 | go mod download 12 | 13 | # Run all the tests 14 | test: 15 | go test $(TEST_OPTIONS) -covermode=atomic -coverprofile=coverage.txt ./... -run $(TEST_PATTERN) -timeout=30s 16 | 17 | # Run all the tests and opens the coverage report 18 | cover: test 19 | go tool cover -html=coverage.txt 20 | 21 | # gofmt and goimports all go files 22 | fmt: 23 | find . -name '*.go' | while read -r file; do gofmt -w -s "$$file"; goimports -w "$$file"; done 24 | 25 | # Run all the linters 26 | lint: 27 | golangci-lint run --enable-all ./... 28 | 29 | # Run shcheck against itself 30 | run: 31 | go run main.go --ignore='sh/testdata/*.sh' 32 | 33 | # Run all the tests and code checks 34 | ci: run lint test 35 | 36 | # Build a local version 37 | build: 38 | go build . 39 | 40 | # Install to $GOPATH/src 41 | install: 42 | go install 43 | 44 | .DEFAULT_GOAL := build 45 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Carlos Alexandro Becker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | By participating to this project, you agree to abide our [code of 4 | conduct](/CODE_OF_CONDUCT.md). 5 | 6 | ## Setup your machine 7 | 8 | `example` is written in [Go](https://golang.org/). 9 | 10 | Prerequisites are: 11 | 12 | * Build: 13 | * `make` 14 | * [Go 1.8+](http://golang.org/doc/install) 15 | 16 | Clone `example` from source into `$GOPATH`: 17 | 18 | ```sh 19 | $ go get github.com/caarlos0/example 20 | $ cd $GOPATH/src/github.com/caarlos0/example 21 | ``` 22 | 23 | Install the build and lint dependencies: 24 | 25 | ``` sh 26 | $ make setup 27 | ``` 28 | 29 | A good way of making sure everything is all right is running the test suite: 30 | 31 | ``` sh 32 | $ make test 33 | ``` 34 | 35 | ## Test your change 36 | 37 | You can create a branch for your changes and try to build from the source as you go: 38 | 39 | ``` sh 40 | $ go build 41 | ``` 42 | 43 | When you are satisfied with the changes, we suggest you run: 44 | 45 | ``` sh 46 | $ make ci 47 | ``` 48 | 49 | Which runs all the linters and tests. 50 | 51 | ## Submit a pull request 52 | 53 | Push your branch to your `example` fork and open a pull request against the 54 | master branch. 55 | -------------------------------------------------------------------------------- /sh/check.go: -------------------------------------------------------------------------------- 1 | package sh 2 | 3 | import ( 4 | "fmt" 5 | "os/exec" 6 | "strings" 7 | ) 8 | 9 | // ShellcheckOptions pass down options to the shellcheck binary 10 | type ShellcheckOptions struct { 11 | Exclude []string 12 | } 13 | 14 | type shellcheck struct { 15 | options ShellcheckOptions 16 | } 17 | 18 | // Check a file with shellcheck 19 | func (s *shellcheck) Check(file string) error { 20 | bin, err := s.Install() 21 | if err != nil { 22 | return err 23 | } 24 | var args = []string{"--external-sources"} 25 | if len(s.options.Exclude) != 0 { 26 | args = append(args, "--exclude", strings.Join(s.options.Exclude, ",")) 27 | } 28 | args = append(args, file) 29 | out, err := exec.Command(bin, args...).CombinedOutput() 30 | if err == nil { 31 | return nil 32 | } 33 | return fmt.Errorf("shellcheck failed: %v", string(out)) 34 | } 35 | 36 | // Install shellcheck 37 | func (*shellcheck) Install() (string, error) { 38 | return install( 39 | map[string]string{ 40 | "linuxamd64": "https://github.com/caarlos0/shellcheck-docker/releases/download/v0.7.0/shellcheck_linux", 41 | "darwinamd64": "https://github.com/caarlos0/shellcheck-docker/releases/download/v0.7.0/shellcheck_darwin", 42 | }, 43 | "/tmp/shellcheck", 44 | ) 45 | } 46 | -------------------------------------------------------------------------------- /sh/sh.go: -------------------------------------------------------------------------------- 1 | package sh 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "net/http" 7 | "os" 8 | "runtime" 9 | ) 10 | 11 | // Checker interface 12 | type Checker interface { 13 | Check(file string) error 14 | Install() (string, error) 15 | } 16 | 17 | // Options provides options to the underline checkers 18 | type Options struct { 19 | Shellcheck ShellcheckOptions 20 | } 21 | 22 | // Checkers all checkers 23 | func Checkers(opts Options) []Checker { 24 | return []Checker{ 25 | &shellcheck{opts.Shellcheck}, 26 | &shfmt{}, 27 | } 28 | } 29 | 30 | func download(url, target string) error { 31 | out, err := os.Create(target) 32 | if err != nil { 33 | return err 34 | } 35 | defer func() { _ = out.Close() }() 36 | resp, err := http.Get(url) // nolint: gosec 37 | if err != nil { 38 | return err 39 | } 40 | defer func() { _ = resp.Body.Close() }() 41 | if _, err = io.Copy(out, resp.Body); err != nil { 42 | return err 43 | } 44 | return os.Chmod(target, 0755) 45 | } 46 | 47 | func install(urls map[string]string, path string) (string, error) { 48 | var url = urls[runtime.GOOS+runtime.GOARCH] 49 | if url == "" { 50 | return "", fmt.Errorf("no binary for %s %s", runtime.GOOS, runtime.GOARCH) 51 | } 52 | if _, err := os.Stat(path); os.IsNotExist(err) { 53 | return path, download(url, path) 54 | } 55 | return path, nil 56 | } 57 | -------------------------------------------------------------------------------- /sh/fmt.go: -------------------------------------------------------------------------------- 1 | package sh 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os/exec" 7 | 8 | "github.com/pmezard/go-difflib/difflib" 9 | ) 10 | 11 | type shfmt struct { 12 | } 13 | 14 | // Check a file with shfmt 15 | func (s *shfmt) Check(file string) error { 16 | shfmt, err := s.Install() 17 | if err != nil { 18 | return err 19 | } 20 | out, err := exec.Command(shfmt, file).CombinedOutput() 21 | if err != nil { 22 | return fmt.Errorf("shfmt failed: %v", string(out)) 23 | } 24 | contents, err := ioutil.ReadFile(file) 25 | if err != nil { 26 | return fmt.Errorf("shfmt failed: %v", err) 27 | } 28 | if string(out) == string(contents) { 29 | return nil 30 | } 31 | diff, err := difflib.GetUnifiedDiffString( 32 | difflib.UnifiedDiff{ 33 | A: difflib.SplitLines(string(contents)), 34 | B: difflib.SplitLines(string(out)), 35 | FromFile: "Original", 36 | ToFile: "Fixed", 37 | Context: 3, 38 | }, 39 | ) 40 | if err != nil { 41 | return err 42 | } 43 | return fmt.Errorf("shfmt failed: file format is wrong, fix it with shfmt -w %s. diff:\n%s", file, diff) 44 | } 45 | 46 | // Install shfmt 47 | func (*shfmt) Install() (string, error) { 48 | return install( 49 | map[string]string{ 50 | "linuxamd64": "https://github.com/mvdan/sh/releases/download/v2.6.4/shfmt_v2.6.4_linux_amd64", 51 | "darwinamd64": "https://github.com/mvdan/sh/releases/download/v2.6.4/shfmt_v2.6.4_darwin_amd64", 52 | }, 53 | "/tmp/shfmt", 54 | ) 55 | } 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # shcheck 2 | 3 | A tool to easily bind shellcheck and shfmt to your CI, so your 4 | shellscripts can be checked. 5 | 6 | This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. 7 | We appreciate your contribution. Please refer to our [contributing guidelines](CONTRIBUTING.md). 8 | 9 | [![Release](https://img.shields.io/github/release/caarlos0/shcheck.svg?style=flat-square)](https://github.com/caarlos0/shcheck/releases/latest) 10 | [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md) 11 | [![Travis](https://img.shields.io/travis/caarlos0/shcheck.svg?style=flat-square)](https://travis-ci.org/caarlos0/shcheck) 12 | [![Coverage Status](https://img.shields.io/codecov/c/github/caarlos0/shcheck/master.svg?style=flat-square)](https://codecov.io/gh/caarlos0/shcheck) 13 | [![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](http://godoc.org/github.com/caarlos0/shcheck) 14 | [![Go Report Card](https://goreportcard.com/badge/github.com/caarlos0/shcheck?style=flat-square)](https://goreportcard.com/report/github.com/caarlos0/shcheck) 15 | [![SayThanks.io](https://img.shields.io/badge/SayThanks.io-%E2%98%BC-1EAEDB.svg?style=flat-square)](https://saythanks.io/to/caarlos0) 16 | [![Powered By: GoReleaser](https://img.shields.io/badge/powered%20by-goreleaser-green.svg?style=flat-square)](https://github.com/goreleaser) 17 | 18 | 19 | ## Usage 20 | 21 | Just add it to your travis.yml: 22 | 23 | ```yaml 24 | script: 25 | - curl -sL https://git.io/shcheck | bash -s 26 | ``` 27 | 28 | You can also pass files and folders to be ignored, like this: 29 | 30 | ```yaml 31 | script: 32 | - curl -sL https://git.io/shcheck | bash -s -f -- --ignore=somefile.sh --ignore='folder/**/*' 33 | ``` 34 | 35 | Or with Docker: 36 | 37 | ```sh 38 | docker run --rm -v `pwd`:/scripts --workdir=/scripts caarlos0/shcheck 39 | ``` 40 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/alecthomas/kingpin" 8 | "github.com/caarlos0/shcheck/sh" 9 | "github.com/caarlos0/shcheck/status" 10 | zglob "github.com/mattn/go-zglob" 11 | ) 12 | 13 | // nolint: gochecknoglobals,lll 14 | var ( 15 | version = "master" 16 | app = kingpin.New("shcheck", "shcheck validates your scripts against both shellcheck and shfmt") 17 | ignoredFiles = app.Flag("ignore", "ignore files or folders").HintOptions("folder/**/*", "*.bash").Short('i').Strings() 18 | shellcheckExcludes = app.Flag("shellcheck-exclude", "exclude some shellcheck checks").HintOptions("SC1090", "SC1004").Short('e').Strings() 19 | ) 20 | 21 | func main() { 22 | app.Version("shfmt version " + version) 23 | app.VersionFlag.Short('v') 24 | app.HelpFlag.Short('h') 25 | kingpin.MustParse(app.Parse(os.Args[1:])) 26 | 27 | // nolint: godox 28 | // TODO: also look for executables with a valid shell shebang 29 | files, err := zglob.Glob(`**/*.*sh`) 30 | kingpin.FatalIfError(err, "fail to find all shell files") 31 | 32 | var fail bool 33 | for _, file := range files { 34 | if err := check(file); err != nil { 35 | fail = true 36 | } 37 | } 38 | if fail { 39 | kingpin.Fatalf("\nsome checks failed. check output above.\n") 40 | } 41 | } 42 | 43 | func check(file string) error { 44 | if ignore(*ignoredFiles, file) { 45 | status.Ignore(file) 46 | return nil 47 | } 48 | var options = sh.Options{ 49 | Shellcheck: sh.ShellcheckOptions{ 50 | Exclude: *shellcheckExcludes, 51 | }, 52 | } 53 | var errors []error 54 | for _, check := range sh.Checkers(options) { 55 | if err := check.Check(file); err != nil { 56 | errors = append(errors, err) 57 | } 58 | } 59 | if len(errors) == 0 { 60 | status.Success(file) 61 | return nil 62 | } 63 | status.Fail(file) 64 | for _, err := range errors { 65 | fmt.Println(err) 66 | } 67 | return fmt.Errorf("check failed") 68 | } 69 | 70 | func ignore(patterns []string, file string) bool { 71 | for _, pattern := range patterns { 72 | if ok, err := zglob.Match(pattern, file); ok && err == nil { 73 | return true 74 | } 75 | } 76 | return false 77 | } 78 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/alecthomas/kingpin v2.2.6+incompatible h1:5svnBTFgJjZvGKyYBtMB0+m5wvrbUHiqye8wRJMlnYI= 2 | github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= 3 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= 4 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 5 | github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= 6 | github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= 7 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 8 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= 10 | github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= 11 | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= 12 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 13 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 14 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 15 | github.com/mattn/go-zglob v0.0.3 h1:6Ry4EYsScDyt5di4OI6xw1bYhOqfE5S33Z1OPy+d+To= 16 | github.com/mattn/go-zglob v0.0.3/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= 17 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 18 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 19 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 20 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 21 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 22 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 23 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 24 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= 25 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 26 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 27 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 28 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 29 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 30 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 31 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at root@carlosbecker.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | --------------------------------------------------------------------------------