diff --git a/cmd/enforce.go b/cmd/enforce.go index e84e05d6..1374bb15 100644 --- a/cmd/enforce.go +++ b/cmd/enforce.go @@ -28,24 +28,23 @@ var enforceCmd = &cobra.Command{ Use: "enforce", Short: "", Long: ``, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) (err error) { if len(args) != 1 { - return fmt.Errorf("Invalid argument") + err = fmt.Errorf("Invalid arguments %v", args) + + return err } - err := checkDockerVersion() + err = checkDockerVersion() if err != nil { - return err + return } e, err := conform.NewEnforcer(args[0]) if err != nil { - return err + return } err = e.ExecuteRule() - if err != nil { - return err - } - return nil + return }, } @@ -54,25 +53,27 @@ func init() { RootCmd.Flags().BoolVar(&debug, "debug", false, "Debug rendering") } -func checkDockerVersion() error { +func checkDockerVersion() (err error) { cli, err := client.NewEnvClient() if err != nil { - return err + return } serverVersion, err := cli.ServerVersion(context.Background()) if err != nil { - return err + return } minVersion, err := semver.NewVersion(minDockerVersion) if err != nil { - return err + return } serverSemVer := semver.MustParse(serverVersion.Version) i := serverSemVer.Compare(minVersion) if i < 0 { - return fmt.Errorf("At least Docker version %s is required", minDockerVersion) + err = fmt.Errorf("At least Docker version %s is required", minDockerVersion) + + return err } - return nil + return } diff --git a/cmd/root.go b/cmd/root.go index 16e0fdd2..e93a0813 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -29,9 +29,7 @@ const ( ) var ( - target string - imageName string - debug bool + debug bool ) // RootCmd represents the base command when called without any subcommands diff --git a/conform.yaml b/conform.yaml index 4eb2096d..13937163 100644 --- a/conform.yaml +++ b/conform.yaml @@ -67,7 +67,8 @@ templates: test: | FROM golang:1.8.3 as test WORKDIR /go/src/github.com/autonomy/conform - RUN go get -u github.com/golang/lint/golint + RUN go get -u gopkg.in/alecthomas/gometalinter.v1 + RUN gometalinter.v1 --install COPY --from=build /go/src/github.com/autonomy/conform . RUN chmod +x ./scripts/test.sh; sync; ./scripts/test.sh image: | diff --git a/conform/enforce.go b/conform/enforce.go index 6a823521..3c72bfe7 100644 --- a/conform/enforce.go +++ b/conform/enforce.go @@ -24,29 +24,30 @@ type Enforcer struct { } // NewEnforcer instantiates and returns an executer. -func NewEnforcer(rule string) (*Enforcer, error) { - e := &Enforcer{} - gitInfo := git.NewInfo() +func NewEnforcer(rule string) (enforcer *Enforcer, err error) { + enforcer = &Enforcer{} + gitInfo, err := git.NewInfo() + if err != nil { + return + } date := []byte{} if gitInfo.IsTag { - _date, err := exec.Command("date").Output() + date, err = exec.Command("/bin/date").Output() if err != nil { - fmt.Print(err) + return } - - date = _date } c, err := config.NewConfig() if err != nil { - return nil, err + return } - e.config = c - e.GitInfo = gitInfo - e.Built = strings.TrimSuffix(string(date), "\n") - e.rule = rule + enforcer.config = c + enforcer.GitInfo = gitInfo + enforcer.Built = strings.TrimSuffix(string(date), "\n") + enforcer.rule = rule - return e, nil + return } // ExecuteBuild executes a docker build. @@ -56,19 +57,22 @@ func (e *Enforcer) ExecuteBuild() error { image = e.FormatImageNameDirty() } - os.Setenv("CONFORM_IMAGE", image) + err := os.Setenv("CONFORM_IMAGE", image) + if err != nil { + return err + } args := append([]string{"build", "--tag", image, "."}) command := exec.Command("docker", args...) command.Stdout = os.Stdout command.Stderr = os.Stderr - command.Start() - err := command.Wait() + err = command.Start() if err != nil { return err } + err = command.Wait() - return nil + return err } // RenderDockerfile writes the final Dockerfile to disk. @@ -87,7 +91,10 @@ func (e *Enforcer) RenderDockerfile(target *config.Rule) error { if e.config.Debug { fmt.Println(dockerfile) } else { - ioutil.WriteFile("Dockerfile", []byte(dockerfile), 0644) + err := ioutil.WriteFile("Dockerfile", []byte(dockerfile), 0644) + if err != nil { + return err + } } return nil @@ -127,8 +134,11 @@ func (e *Enforcer) ExecuteScript(script string) error { command := exec.Command("bash", "-c", s) command.Stdout = os.Stdout command.Stderr = os.Stderr - command.Start() - err := command.Wait() + err := command.Start() + if err != nil { + return err + } + err = command.Wait() if err != nil { return fmt.Errorf("Failed executing %q: %v", script, err) } diff --git a/conform/enforce_test.go b/conform/enforce_test.go index e7e2cd98..df2b1254 100644 --- a/conform/enforce_test.go +++ b/conform/enforce_test.go @@ -32,17 +32,27 @@ rules: - after ` +func RemoveAll(dir string) { + err := os.RemoveAll(dir) + if err != nil { + log.Fatal(err) + } +} + func TestNewEnforcer(t *testing.T) { dir, err := ioutil.TempDir("", "test") if err != nil { log.Fatal(err) } - defer os.RemoveAll(dir) + defer RemoveAll(dir) tmpfn := filepath.Join(dir, "conform.yaml") if err = ioutil.WriteFile(tmpfn, []byte(conformYAML), 0666); err != nil { log.Fatal(err) } - os.Chdir(dir) + err = os.Chdir(dir) + if err != nil { + t.Error(err) + } output, err := exec.Command("git", "init").Output() if err != nil { t.Fatal(output) diff --git a/conform/git/git.go b/conform/git/git.go index 99e8b9e3..fb3691de 100644 --- a/conform/git/git.go +++ b/conform/git/git.go @@ -2,7 +2,6 @@ package git import ( "fmt" - "log" "os" "os/exec" "strconv" @@ -22,66 +21,115 @@ type Info struct { } // NewInfo instantiates and returns info. -func NewInfo() *Info { - branch, err := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD").Output() +func NewInfo() (info *Info, err error) { + branch, err := Branch() if err != nil { - log.Fatalf("Failed to get branch [%v]", err) + return } - fmt.Printf("Branch: %s\n", strings.TrimSuffix(string(branch), "\n")) - os.Setenv("CONFORM_BRANCH", strings.TrimSuffix(string(branch), "\n")) - sha, err := exec.Command("git", "rev-parse", "--short", "HEAD").Output() + sha, err := SHA() if err != nil { - log.Fatalf("Failed to get sha [%v]", err) + return } - fmt.Printf("SHA: %s\n", strings.TrimSuffix(string(sha), "\n")) - os.Setenv("CONFORM_SHA", strings.TrimSuffix(string(sha), "\n")) - tag := "undefined" - isTag := false - _tag, err := exec.Command("git", "describe", "--exact-match", "--tags", "HEAD").Output() - if err == nil { - isTag = true + tag, isTag, err := Tag() + if err != nil { + return } - if isTag { - tag = string(_tag) + + _, isDirty, err := Status() + if err != nil { + return } - fmt.Printf("IsTag: %v\n", isTag) - os.Setenv("CONFORM_IS_TAG", strconv.FormatBool(isTag)) - fmt.Printf("Tag: %s\n", strings.TrimSuffix(string(tag), "\n")) - os.Setenv("CONFORM_TAG", strings.TrimSuffix(string(tag), "\n")) - status, err := exec.Command("git", "status", "--porcelain").Output() + info = &Info{ + Branch: branch, + SHA: sha, + Tag: strings.TrimSuffix(tag, "\n"), + IsTag: isTag, + IsDirty: isDirty, + } + + return +} + +// Branch returns the current git branch name. +func Branch() (branch string, err error) { + branchBytes, err := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD").Output() if err != nil { - log.Fatal(err) + return } - fmt.Printf("Status: %s\n", strings.TrimSuffix(string(status), "\n")) + branch = strings.TrimSuffix(string(branchBytes), "\n") + err = ExportConformVar("branch", branch) + fmt.Printf("Branch: %s\n", branch) - isDirty := false - if strings.TrimSuffix(string(status), "\n") != "" { - isDirty = true + return +} + +// SHA returns the sha of the current commit. +func SHA() (sha string, err error) { + shaBytes, err := exec.Command("git", "rev-parse", "--short", "HEAD").Output() + if err != nil { + return } - fmt.Printf("IsDirty: %v\n", isDirty) - os.Setenv("CONFORM_IS_DIRTY", strconv.FormatBool(isDirty)) + sha = strings.TrimSuffix(string(shaBytes), "\n") + err = ExportConformVar("sha", sha) + fmt.Printf("SHA: %s\n", sha) + + return +} - prerelease := "" +// Tag returns the tag name if HEAD is a tag. +func Tag() (tag string, isTag bool, err error) { + tagBytes, isTagErr := exec.Command("git", "describe", "--exact-match", "--tags", "HEAD").Output() + if isTagErr == nil { + isTag = true + } + tag = strings.TrimSuffix(string(tagBytes), "\n") if isTag { - sv, err := semver.NewVersion(strings.TrimSuffix(string(tag[1:]), "\n")) + _, err = semver.NewVersion(tag[1:]) if err != nil { - log.Fatal(err) + return } + } + err = ExportConformVar("tag", tag) + if err != nil { + return + } + err = ExportConformVar("is_tag", strconv.FormatBool(isTag)) + if err != nil { + return + } + fmt.Printf("IsTag: %v\n", isTag) + fmt.Printf("Tag: %s\n", tag) + + return +} - prerelease = sv.Prerelease() +// Status returns the status of the working tree. +func Status() (status string, isDirty bool, err error) { + statusBytes, err := exec.Command("git", "status", "--porcelain").Output() + if err != nil { + return } - fmt.Printf("Prerelease: %s\n", prerelease) - os.Setenv("CONFORM_PRERELEASE", prerelease) - - return &Info{ - Branch: strings.TrimSuffix(string(branch), "\n"), - SHA: strings.TrimSuffix(string(sha), "\n"), - Tag: strings.TrimSuffix(string(tag), "\n"), - Prerelease: prerelease, - IsTag: isTag, - IsDirty: isDirty, + status = strings.TrimSuffix(string(statusBytes), "\n") + if status != "" { + isDirty = true } + err = ExportConformVar("is_dirty", strconv.FormatBool(isDirty)) + if err != nil { + return + } + fmt.Printf("Status: %s\n", status) + fmt.Printf("IsDirty: %v\n", isDirty) + + return +} + +// ExportConformVar exports variable prefixed with CONFORM_ +func ExportConformVar(name, value string) (err error) { + variable := fmt.Sprintf("CONFORM_%s", strings.ToUpper(name)) + err = os.Setenv(variable, value) + + return } diff --git a/scripts/test.sh b/scripts/test.sh index b0589b4f..2c527983 100644 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -2,19 +2,17 @@ set -e -GOPACKAGES=$(go list ./... | grep -v /vendor/ | grep -v /api) -GOFILES=$(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./api/*") +GOPACKAGES=$(go list ./... | grep -v /vendor/) +GOFILES=$(find . -type f -name '*.go' -not -path "./vendor/*") COVERAGE_REPORT=coverage.txt PROFILE=profile.out +echo "Running tests" if [[ -f ${COVERAGE_REPORT} ]]; then rm ${COVERAGE_REPORT} fi - touch ${COVERAGE_REPORT} - -echo "Running tests" for package in ${GOPACKAGES[@]}; do go test -v -race -coverprofile=${PROFILE} -covermode=atomic $package if [ -f ${PROFILE} ]; then @@ -23,17 +21,8 @@ for package in ${GOPACKAGES[@]}; do fi done -echo "Vetting packages" -go vet ${GOPACKAGES} -if [ $? -eq 1 ]; then - exit 1 -fi - echo "Linting packages" -golint -set_exit_status ${GOPACKAGES} -if [ $? -eq 1 ]; then - exit 1 -fi +gometalinter.v1 --vendor --disable=gas --disable=gotype --sort=linter --deadline=120s ./... echo "Formatting go files" if [ ! -z "$(gofmt -l -s ${GOFILES})" ]; then