github.com/jdhenke/godel@v0.0.0-20161213181855-abeb3861bf0d/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  	"strings"
    21  
    22  	"github.com/nmiyake/pkg/dirs"
    23  	"github.com/palantir/amalgomate/amalgomated"
    24  	"github.com/palantir/pkg/cli"
    25  	"github.com/palantir/pkg/cli/cfgcli"
    26  	"github.com/palantir/pkg/cli/flag"
    27  	"github.com/palantir/pkg/pkgpath"
    28  	"github.com/pkg/errors"
    29  
    30  	"github.com/palantir/godel/apps/okgo/checkoutput"
    31  	"github.com/palantir/godel/apps/okgo/checks"
    32  	"github.com/palantir/godel/apps/okgo/cmd/cmdlib"
    33  	"github.com/palantir/godel/apps/okgo/config"
    34  	"github.com/palantir/godel/apps/okgo/params"
    35  )
    36  
    37  const packagesFlagName = "packages"
    38  
    39  var packagesFlag = flag.StringSlice{
    40  	Name:     packagesFlagName,
    41  	Usage:    "Packages to check",
    42  	Optional: true,
    43  }
    44  
    45  func RunAllCommand(supplier amalgomated.CmderSupplier) cli.Command {
    46  	return cli.Command{
    47  		Name:  "runAll",
    48  		Usage: "Run all checks",
    49  		Flags: []flag.Flag{
    50  			packagesFlag,
    51  		},
    52  		Action: func(ctx cli.Context) error {
    53  			cfg, err := config.Load(cfgcli.ConfigPath, cfgcli.ConfigJSON)
    54  			if err != nil {
    55  				return err
    56  			}
    57  			wd, err := dirs.GetwdEvalSymLinks()
    58  			if err != nil {
    59  				return err
    60  			}
    61  			return DoRunAll(ctx.Slice(packagesFlagName), cfg, supplier, wd, ctx.App.Stdout)
    62  		},
    63  	}
    64  }
    65  
    66  func DoRunAll(pkgs []string, cfg params.OKGo, supplier amalgomated.CmderSupplier, wd string, stdout io.Writer) error {
    67  	var checksWithOutput []amalgomated.Cmd
    68  	for _, cmd := range cmdlib.Instance().Cmds() {
    69  		// if "omit" is true, skip the check
    70  		if cmdCfg, ok := cfg.Checks[cmd]; ok && cmdCfg.Skip {
    71  			continue
    72  		}
    73  
    74  		cmder, err := supplier(cmd)
    75  		if err != nil {
    76  			return errors.Wrapf(err, "%s is not a valid command", cmd.Name())
    77  		}
    78  
    79  		producedOutput, err := executeSingleCheckWithOutput(cmd, cmder, cfg, pkgs, wd, stdout)
    80  		if err != nil {
    81  			// indicates unexpected hard failure -- check returning non-0 exit code will not trigger
    82  			return errors.Wrapf(err, "check %s failed", cmd.Name())
    83  		}
    84  
    85  		if producedOutput {
    86  			checksWithOutput = append(checksWithOutput, cmd)
    87  		}
    88  	}
    89  
    90  	if len(checksWithOutput) != 0 {
    91  		return errors.Errorf("Checks produced output: %v", checksWithOutput)
    92  	}
    93  	return nil
    94  }
    95  
    96  func SingleCheckCommand(cmd amalgomated.Cmd, supplier amalgomated.CmderSupplier) cli.Command {
    97  	return cli.Command{
    98  		Name:  cmd.Name(),
    99  		Usage: "Run " + cmd.Name(),
   100  		Flags: []flag.Flag{
   101  			packagesFlag,
   102  		},
   103  		Action: func(ctx cli.Context) error {
   104  			cfg, err := config.Load(cfgcli.ConfigPath, cfgcli.ConfigJSON)
   105  			if err != nil {
   106  				return err
   107  			}
   108  			wd, err := dirs.GetwdEvalSymLinks()
   109  			if err != nil {
   110  				return err
   111  			}
   112  
   113  			cmder, err := supplier(cmd)
   114  			if err != nil {
   115  				return errors.Wrapf(err, "failed to create Cmder for %s", cmd.Name())
   116  			}
   117  
   118  			if producedOutput, err := executeSingleCheckWithOutput(cmd, cmder, cfg, ctx.Slice(packagesFlagName), wd, ctx.App.Stdout); producedOutput {
   119  				return fmt.Errorf("")
   120  			} else if err != nil {
   121  				return err
   122  			}
   123  			return nil
   124  		},
   125  	}
   126  }
   127  
   128  // executeSingleCheckWithOutput runs the specified check and outputs the result to stdOut. Returns true if the check
   129  // produced any output, false otherwise.
   130  func executeSingleCheckWithOutput(cmd amalgomated.Cmd, cmder amalgomated.Cmder, cfg params.OKGo, pkgs []string, wd string, stdout io.Writer) (bool, error) {
   131  	output, err := singleCheck(cmd, cmder, cfg, pkgs, wd, stdout)
   132  	if err != nil {
   133  		return false, err
   134  	}
   135  
   136  	producedOutput := len(output) != 0
   137  	if producedOutput {
   138  		outputLines := make([]string, len(output))
   139  		for i, currLine := range output {
   140  			outputLines[i] = currLine.String()
   141  		}
   142  		fmt.Fprintln(stdout, strings.Join(outputLines, "\n"))
   143  	}
   144  	return producedOutput, nil
   145  }
   146  
   147  func singleCheck(cmd amalgomated.Cmd, cmder amalgomated.Cmder, cfg params.OKGo, pkgs []string, cmdWd string, stdout io.Writer) ([]checkoutput.Issue, error) {
   148  	checker, err := checks.GetChecker(cmd)
   149  	if err != nil {
   150  		return nil, err
   151  	}
   152  
   153  	fmt.Fprintf(stdout, "Running %v...\n", cmd.Name())
   154  
   155  	if len(pkgs) == 0 {
   156  		// if no arguments were provided, run check on "all"
   157  		return checker.Check(cmder, cmdWd, cfg)
   158  	}
   159  
   160  	// convert arguments to packages
   161  	packages, err := pkgpath.PackagesFromPaths(cmdWd, pkgs)
   162  	if err != nil {
   163  		return nil, errors.Wrapf(err, "failed to convert arguments to packages: %v", pkgs)
   164  	}
   165  
   166  	// run check on specified packages
   167  	return checker.CheckPackages(cmder, packages, cfg)
   168  }