github.com/joshdk/godel@v0.0.0-20170529232908-862138a45aee/apps/okgo/cmd/check.go (about) 1 // Copyright 2016 Palantir Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "fmt" 19 "io" 20 "os" 21 "strings" 22 23 "github.com/nmiyake/pkg/dirs" 24 "github.com/palantir/amalgomate/amalgomated" 25 "github.com/palantir/pkg/cli" 26 "github.com/palantir/pkg/cli/cfgcli" 27 "github.com/palantir/pkg/cli/flag" 28 "github.com/palantir/pkg/pkgpath" 29 "github.com/pkg/errors" 30 31 "github.com/palantir/godel/apps/okgo/checkoutput" 32 "github.com/palantir/godel/apps/okgo/checks" 33 "github.com/palantir/godel/apps/okgo/cmd/cmdlib" 34 "github.com/palantir/godel/apps/okgo/config" 35 "github.com/palantir/godel/apps/okgo/params" 36 ) 37 38 const ( 39 // releaseTagEnvVar the environment variable used to override the latest release tag that should be used in the 40 // default Go build context. See #72 for details. 41 releaseTagEnvVar = "OKGO_RELEASE_TAG" 42 packagesFlagName = "packages" 43 ) 44 45 var packagesFlag = flag.StringSlice{ 46 Name: packagesFlagName, 47 Usage: "Packages to check", 48 Optional: true, 49 } 50 51 func SetReleaseTagEnvVar(releaseTag string) error { 52 if releaseTag != "" { 53 if err := os.Setenv(releaseTagEnvVar, releaseTag); err != nil { 54 return err 55 } 56 } 57 return nil 58 } 59 60 func GetReleaseTagEnvVar() string { 61 return os.Getenv(releaseTagEnvVar) 62 } 63 64 func RunAllCommand(supplier amalgomated.CmderSupplier) cli.Command { 65 return cli.Command{ 66 Name: "runAll", 67 Usage: "Run all checks", 68 Flags: []flag.Flag{ 69 packagesFlag, 70 }, 71 Action: func(ctx cli.Context) error { 72 cfg, err := config.Load(cfgcli.ConfigPath, cfgcli.ConfigJSON) 73 if err != nil { 74 return err 75 } 76 wd, err := dirs.GetwdEvalSymLinks() 77 if err != nil { 78 return err 79 } 80 return DoRunAll(ctx.Slice(packagesFlagName), cfg, supplier, wd, ctx.App.Stdout) 81 }, 82 } 83 } 84 85 func DoRunAll(pkgs []string, cfg params.OKGo, supplier amalgomated.CmderSupplier, wd string, stdout io.Writer) error { 86 var checksWithOutput []amalgomated.Cmd 87 for _, cmd := range cmdlib.Instance().Cmds() { 88 // if "omit" is true, skip the check 89 if cmdCfg, ok := cfg.Checks[cmd]; ok && cmdCfg.Skip { 90 continue 91 } 92 93 cmder, err := supplier(cmd) 94 if err != nil { 95 return errors.Wrapf(err, "%s is not a valid command", cmd.Name()) 96 } 97 98 producedOutput, err := executeSingleCheckWithOutput(cmd, cmder, cfg, pkgs, wd, stdout) 99 if err != nil { 100 // indicates unexpected hard failure -- check returning non-0 exit code will not trigger 101 return errors.Wrapf(err, "check %s failed", cmd.Name()) 102 } 103 104 if producedOutput { 105 checksWithOutput = append(checksWithOutput, cmd) 106 } 107 } 108 109 if len(checksWithOutput) != 0 { 110 return errors.Errorf("Checks produced output: %v", checksWithOutput) 111 } 112 return nil 113 } 114 115 func SingleCheckCommand(cmd amalgomated.Cmd, supplier amalgomated.CmderSupplier) cli.Command { 116 return cli.Command{ 117 Name: cmd.Name(), 118 Usage: "Run " + cmd.Name(), 119 Flags: []flag.Flag{ 120 packagesFlag, 121 }, 122 Action: func(ctx cli.Context) error { 123 cfg, err := config.Load(cfgcli.ConfigPath, cfgcli.ConfigJSON) 124 if err != nil { 125 return err 126 } 127 wd, err := dirs.GetwdEvalSymLinks() 128 if err != nil { 129 return err 130 } 131 if err := SetReleaseTagEnvVar(cfg.ReleaseTag); err != nil { 132 return err 133 } 134 135 cmder, err := supplier(cmd) 136 if err != nil { 137 return errors.Wrapf(err, "failed to create Cmder for %s", cmd.Name()) 138 } 139 140 if producedOutput, err := executeSingleCheckWithOutput(cmd, cmder, cfg, ctx.Slice(packagesFlagName), wd, ctx.App.Stdout); producedOutput { 141 return fmt.Errorf("") 142 } else if err != nil { 143 return err 144 } 145 return nil 146 }, 147 } 148 } 149 150 // executeSingleCheckWithOutput runs the specified check and outputs the result to stdOut. Returns true if the check 151 // produced any output, false otherwise. 152 func executeSingleCheckWithOutput(cmd amalgomated.Cmd, cmder amalgomated.Cmder, cfg params.OKGo, pkgs []string, wd string, stdout io.Writer) (bool, error) { 153 output, err := singleCheck(cmd, cmder, cfg, pkgs, wd, stdout) 154 if err != nil { 155 return false, err 156 } 157 158 producedOutput := len(output) != 0 159 if producedOutput { 160 outputLines := make([]string, len(output)) 161 for i, currLine := range output { 162 outputLines[i] = currLine.String() 163 } 164 fmt.Fprintln(stdout, strings.Join(outputLines, "\n")) 165 } 166 return producedOutput, nil 167 } 168 169 func singleCheck(cmd amalgomated.Cmd, cmder amalgomated.Cmder, cfg params.OKGo, pkgs []string, cmdWd string, stdout io.Writer) ([]checkoutput.Issue, error) { 170 checker, err := checks.GetChecker(cmd) 171 if err != nil { 172 return nil, err 173 } 174 175 fmt.Fprintf(stdout, "Running %v...\n", cmd.Name()) 176 177 if len(pkgs) == 0 { 178 // if no arguments were provided, run check on "all" 179 return checker.Check(cmder, cmdWd, cfg) 180 } 181 182 // convert arguments to packages 183 packages, err := pkgpath.PackagesFromPaths(cmdWd, pkgs) 184 if err != nil { 185 return nil, errors.Wrapf(err, "failed to convert arguments to packages: %v", pkgs) 186 } 187 188 // run check on specified packages 189 return checker.CheckPackages(cmder, packages, cfg) 190 }