github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/mungegithub/mungers/check-labels.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package mungers 18 19 import ( 20 "fmt" 21 "os" 22 23 "k8s.io/kubernetes/pkg/util/sets" 24 "k8s.io/kubernetes/pkg/util/yaml" 25 "k8s.io/test-infra/mungegithub/features" 26 githubhelper "k8s.io/test-infra/mungegithub/github" 27 "k8s.io/test-infra/mungegithub/mungers/mungerutil" 28 "k8s.io/test-infra/mungegithub/options" 29 30 "bytes" 31 "io/ioutil" 32 33 "github.com/golang/glog" 34 "github.com/google/go-github/github" 35 ) 36 37 type labelAccessor interface { 38 AddLabel(label *github.Label) error 39 GetLabels() ([]*github.Label, error) 40 } 41 42 // CheckLabelsMunger will check that the labels specified in the labels yaml file 43 // are created. 44 type CheckLabelsMunger struct { 45 labelFilePath string 46 prevHash string 47 labelAccessor labelAccessor 48 features *features.Features 49 readFunc func() ([]byte, error) 50 } 51 52 func init() { 53 RegisterMungerOrDie(&CheckLabelsMunger{}) 54 } 55 56 // Name is the name usable in --pr-mungers 57 func (c *CheckLabelsMunger) Name() string { return "check-labels" } 58 59 // RequiredFeatures is a slice of 'features' that must be provided. 60 func (c *CheckLabelsMunger) RequiredFeatures() []string { return []string{features.RepoFeatureName} } 61 62 // Initialize will initialize the munger. 63 func (c *CheckLabelsMunger) Initialize(config *githubhelper.Config, features *features.Features) error { 64 c.labelAccessor = config 65 c.features = features 66 c.readFunc = func() ([]byte, error) { 67 return ioutil.ReadFile(c.labelFilePath) 68 } 69 70 return c.validateFilePath() 71 } 72 73 func (c *CheckLabelsMunger) validateFilePath() error { 74 if len(c.labelFilePath) == 0 { 75 return fmt.Errorf("no 'label-file' option specified, cannot check labels") 76 } 77 if _, err := os.Stat(c.labelFilePath); os.IsNotExist(err) { 78 return fmt.Errorf("failed to stat the check label config: %v", err) 79 } 80 return nil 81 } 82 83 // EachLoop is called at the start of every munge loop 84 func (c *CheckLabelsMunger) EachLoop() error { 85 fileContents, err := c.readFunc() 86 if err != nil { 87 glog.Errorf("Failed to read the check label config: %v", err) 88 return err 89 } 90 hash := mungerutil.GetHash(fileContents) 91 if c.prevHash != hash { 92 // Get all labels from file. 93 fileLabels := map[string][]*github.Label{} 94 if err := yaml.NewYAMLToJSONDecoder(bytes.NewReader(fileContents)).Decode(&fileLabels); err != nil { 95 return fmt.Errorf("Failed to decode the check label config: %v", err) 96 } 97 98 // Get all labels from repository. 99 repoLabels, err := c.labelAccessor.GetLabels() 100 if err != nil { 101 return err 102 } 103 c.addMissingLabels(repoLabels, fileLabels["labels"]) 104 c.prevHash = hash 105 } 106 return nil 107 } 108 109 // addMissingLabels will not remove any labels. It will add those which are present in the yaml file and not in 110 // the repository. 111 func (c *CheckLabelsMunger) addMissingLabels(repoLabels, fileLabels []*github.Label) { 112 repoLabelSet := sets.NewString() 113 for _, repoLabel := range repoLabels { 114 repoLabelSet.Insert(*repoLabel.Name) 115 } 116 117 // Compare against labels in local file. 118 for _, label := range fileLabels { 119 if !repoLabelSet.Has(*label.Name) { 120 err := c.labelAccessor.AddLabel(label) 121 if err != nil { 122 glog.Errorf("Error %s in adding label %s", err, *label.Name) 123 } 124 } 125 } 126 } 127 128 // RegisterOptions registers options for this munger; returns any that require a restart when changed. 129 func (c *CheckLabelsMunger) RegisterOptions(opts *options.Options) sets.String { 130 opts.RegisterString(&c.labelFilePath, "label-file", "", "Path from repository root to file containing list of labels.") 131 opts.RegisterUpdateCallback(func(changed sets.String) error { 132 if changed.Has("label-file") { 133 return c.validateFilePath() 134 } 135 return nil 136 }) 137 return nil 138 } 139 140 // Munge is unused by this munger. 141 func (c *CheckLabelsMunger) Munge(obj *githubhelper.MungeObject) {}