github.com/joshdk/godel@v0.0.0-20170529232908-862138a45aee/apps/okgo/config/config.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 config
    16  
    17  import (
    18  	"encoding/json"
    19  	"io/ioutil"
    20  
    21  	"github.com/palantir/amalgomate/amalgomated"
    22  	"github.com/palantir/pkg/matcher"
    23  	"github.com/pkg/errors"
    24  	"gopkg.in/yaml.v2"
    25  
    26  	"github.com/palantir/godel/apps/okgo/checkoutput"
    27  	"github.com/palantir/godel/apps/okgo/cmd/cmdlib"
    28  	"github.com/palantir/godel/apps/okgo/params"
    29  )
    30  
    31  type OKGo struct {
    32  	// ReleaseTag specifies the newest Go release build tag supported by the codebase being checked. If this value
    33  	// is not specified, it defaults to the Go release that was used to build the check tool. If the code being
    34  	// checked is known to use a version of Go that is earlier than the version of Go used to build the check tool
    35  	// and the codebase being checked contains build tags for the newer Go version, this value should be explicitly
    36  	// set. For example, if the check tool was compiled using Go 1.8 but the codebase being checked uses Go 1.7 and
    37  	// contains files that use the "// +build go1.8" build tag, then this should be set to "go1.7".
    38  	ReleaseTag string `yaml:"release-tag" json:"release-tag"`
    39  
    40  	// Checks specifies the configuration used by the checks. The key is the name of the check and the value is the
    41  	// custom configuration for that check.
    42  	Checks map[string]Checker `yaml:"checks" json:"checks"`
    43  
    44  	// Exclude specifies the files that should be excluded from tests.
    45  	Exclude matcher.NamesPathsCfg `yaml:"exclude" json:"exclude"`
    46  }
    47  
    48  type Checker struct {
    49  	// Skip specifies whether or not the check should be skipped entirely.
    50  	Skip bool `yaml:"skip" json:"skip"`
    51  
    52  	// Args specifies the command-line arguments provided to the check.
    53  	Args []string `yaml:"args" json:"args"`
    54  
    55  	// Filters specifies the filter definitions. Raw output lines that match the filter are excluded from
    56  	// processing.
    57  	Filters []Filter `yaml:"filters" json:"filters"`
    58  }
    59  
    60  type Filter struct {
    61  	// Type specifies the type of the filter: "message", "name" or "path". If blank, defaults to "message".
    62  	Type string `yaml:"type" json:"type"`
    63  
    64  	// The value of the filter.
    65  	Value string `yaml:"value" json:"value"`
    66  }
    67  
    68  func (r *OKGo) ToParams() (params.OKGo, error) {
    69  	checks := make(map[amalgomated.Cmd]params.Checker)
    70  	for key, value := range r.Checks {
    71  		singleParam, err := value.ToParam()
    72  		if err != nil {
    73  			return params.OKGo{}, err
    74  		}
    75  		cmd, err := cmdlib.Instance().NewCmd(key)
    76  		if err != nil {
    77  			return params.OKGo{}, errors.Wrapf(err, "unable to convert %s into a command", key)
    78  		}
    79  		checks[cmd] = singleParam
    80  	}
    81  	return params.OKGo{
    82  		ReleaseTag: r.ReleaseTag,
    83  		Checks:     checks,
    84  		Exclude:    r.Exclude.Matcher(),
    85  	}, nil
    86  }
    87  
    88  func (r *Checker) ToParam() (params.Checker, error) {
    89  	var lineFilters []checkoutput.Filterer
    90  	for _, cfg := range r.Filters {
    91  		checkFilter, err := cfg.toFilter(checkoutput.MessageRegexpFilter)
    92  		if err != nil {
    93  			return params.Checker{}, errors.Wrapf(err, "failed to parse filter: %v", cfg)
    94  		}
    95  		lineFilters = append(lineFilters, checkFilter)
    96  	}
    97  	return params.Checker{
    98  		Skip:        r.Skip,
    99  		Args:        r.Args,
   100  		LineFilters: lineFilters,
   101  	}, nil
   102  }
   103  
   104  func (f *Filter) toFilter(filterForBlankType func(name string) checkoutput.Filterer) (checkoutput.Filterer, error) {
   105  	switch f.Type {
   106  	case "message":
   107  		return checkoutput.MessageRegexpFilter(f.Value), nil
   108  	case "name":
   109  		return checkoutput.NamePathFilter(f.Value), nil
   110  	case "path":
   111  		return checkoutput.RelativePathFilter(f.Value), nil
   112  	case "":
   113  		if filterForBlankType != nil {
   114  			return filterForBlankType(f.Value), nil
   115  		}
   116  		fallthrough
   117  	default:
   118  		return nil, errors.Errorf("unknown filter type: %v", f.Type)
   119  	}
   120  }
   121  
   122  func Load(configPath, jsonContent string) (params.OKGo, error) {
   123  	var yml []byte
   124  	if configPath != "" {
   125  		var err error
   126  		yml, err = ioutil.ReadFile(configPath)
   127  		if err != nil {
   128  			return params.OKGo{}, errors.Wrapf(err, "failed to read file %s", configPath)
   129  		}
   130  	}
   131  	cfg, err := LoadRawConfig(string(yml), jsonContent)
   132  	if err != nil {
   133  		return params.OKGo{}, err
   134  	}
   135  	return cfg.ToParams()
   136  }
   137  
   138  func LoadRawConfig(ymlContent, jsonContent string) (OKGo, error) {
   139  	rawCfg := OKGo{}
   140  	if ymlContent != "" {
   141  		if err := yaml.Unmarshal([]byte(ymlContent), &rawCfg); err != nil {
   142  			return OKGo{}, errors.Wrapf(err, "failed to unmarshal YML %s", ymlContent)
   143  		}
   144  	}
   145  	if jsonContent != "" {
   146  		jsonCfg := OKGo{}
   147  		if err := json.Unmarshal([]byte(jsonContent), &jsonCfg); err != nil {
   148  			return OKGo{}, errors.Wrapf(err, "failed to parse JSON %s", jsonContent)
   149  		}
   150  		rawCfg.Exclude.Add(jsonCfg.Exclude)
   151  	}
   152  	return rawCfg, nil
   153  }