github.com/jonsyu1/godel@v0.0.0-20171017211503-64567a0cf169/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 }