github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/prow/config/jobs.go (about) 1 /* 2 Copyright 2017 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 config 18 19 import ( 20 "regexp" 21 "time" 22 23 "k8s.io/test-infra/prow/kube" 24 ) 25 26 // Presubmit is the job-specific trigger info. 27 type Presubmit struct { 28 // eg kubernetes-pull-build-test-e2e-gce 29 Name string `json:"name"` 30 // Run for every PR, or only when a comment triggers it. 31 AlwaysRun bool `json:"always_run"` 32 // Run if the PR modifies a file that matches this regex. 33 RunIfChanged string `json:"run_if_changed"` 34 // Context line for GitHub status. 35 Context string `json:"context"` 36 // eg @k8s-bot e2e test this 37 Trigger string `json:"trigger"` 38 // Valid rerun command to give users. Must match Trigger. 39 RerunCommand string `json:"rerun_command"` 40 // Whether or not to skip commenting and setting status on GitHub. 41 SkipReport bool `json:"skip_report"` 42 // Maximum number of this job running concurrently, 0 implies no limit. 43 MaxConcurrency int `json:"max_concurrency"` 44 // Agent that will take care of running this job. 45 Agent string `json:"agent"` 46 // Kubernetes pod spec. 47 Spec *kube.PodSpec `json:"spec,omitempty"` 48 // Run these jobs after successfully running this one. 49 RunAfterSuccess []Presubmit `json:"run_after_success"` 50 51 Brancher 52 53 // We'll set these when we load it. 54 re *regexp.Regexp // from Trigger. 55 reChanges *regexp.Regexp // from RunIfChanged 56 } 57 58 // Postsubmit runs on push events. 59 type Postsubmit struct { 60 Name string `json:"name"` 61 // Agent that will take care of running this job. 62 Agent string `json:"agent"` 63 // Kubernetes pod spec. 64 Spec *kube.PodSpec `json:"spec,omitempty"` 65 // Maximum number of this job running concurrently, 0 implies no limit. 66 MaxConcurrency int `json:"max_concurrency"` 67 68 Brancher 69 // Run these jobs after successfully running this one. 70 RunAfterSuccess []Postsubmit `json:"run_after_success"` 71 } 72 73 // Periodic runs on a timer. 74 type Periodic struct { 75 Name string `json:"name"` 76 // Agent that will take care of running this job. 77 Agent string `json:"agent"` 78 // Kubernetes pod spec. 79 Spec *kube.PodSpec `json:"spec,omitempty"` 80 // Interval to wait between two runs of the job. 81 Interval string `json:"interval"` 82 Tags []string `json:"tags,omitempty"` 83 // Run these jobs after successfully running this one. 84 RunAfterSuccess []Periodic `json:"run_after_success"` 85 86 interval time.Duration 87 } 88 89 func (p *Periodic) SetInterval(d time.Duration) { 90 p.interval = d 91 } 92 93 func (p *Periodic) GetInterval() time.Duration { 94 return p.interval 95 } 96 97 // Brancher is for shared code between jobs that only run against certain 98 // branches. An empty brancher runs against all branches. 99 type Brancher struct { 100 // Do not run against these branches. Default is no branches. 101 SkipBranches []string `json:"skip_branches"` 102 // Only run against these branches. Default is all branches. 103 Branches []string `json:"branches"` 104 } 105 106 func (br Brancher) RunsAgainstAllBranch() bool { 107 return len(br.SkipBranches) == 0 && len(br.Branches) == 0 108 } 109 110 func (br Brancher) RunsAgainstBranch(branch string) bool { 111 if br.RunsAgainstAllBranch() { 112 return true 113 } 114 115 // Favor SkipBranches over Branches 116 for _, s := range br.SkipBranches { 117 if s == branch { 118 return false 119 } 120 } 121 if len(br.Branches) == 0 { 122 return true 123 } 124 for _, b := range br.Branches { 125 if b == branch { 126 return true 127 } 128 } 129 return false 130 } 131 132 func (ps Presubmit) RunsAgainstChanges(changes []string) bool { 133 for _, change := range changes { 134 if ps.reChanges.MatchString(change) { 135 return true 136 } 137 } 138 return false 139 } 140 141 func matching(j Presubmit, body string, testAll bool) (out []Presubmit) { 142 if j.re.MatchString(body) || (testAll && j.AlwaysRun) { 143 out = append(out, j) 144 } 145 146 for _, child := range j.RunAfterSuccess { 147 out = append(out, matching(child, body, testAll)...) 148 } 149 150 return 151 } 152 153 func (c *Config) MatchingPresubmits(fullRepoName, body string, testAll *regexp.Regexp) []Presubmit { 154 var result []Presubmit 155 ott := testAll.MatchString(body) 156 if jobs, ok := c.Presubmits[fullRepoName]; ok { 157 for _, job := range jobs { 158 result = append(result, matching(job, body, ott)...) 159 } 160 } 161 return result 162 } 163 164 // RetestPresubmits returns all presubmits that should be run given a /retest command. 165 // This is the set of all presubmits intersected with ((alwaysRun + runContexts) - skipContexts) 166 func (c *Config) RetestPresubmits(fullRepoName string, skipContexts, runContexts map[string]bool) []Presubmit { 167 var result []Presubmit 168 if jobs, ok := c.Presubmits[fullRepoName]; ok { 169 for _, job := range jobs { 170 if (job.AlwaysRun || runContexts[job.Context]) && !skipContexts[job.Context] { 171 result = append(result, job) 172 } 173 } 174 } 175 return result 176 } 177 178 // GetPresubmit returns the presubmit job for the provided repo and job name. 179 func (c *Config) GetPresubmit(repo, jobName string) *Presubmit { 180 presubmits := c.AllPresubmits([]string{repo}) 181 for i := range presubmits { 182 ps := presubmits[i] 183 if ps.Name == jobName { 184 return &ps 185 } 186 } 187 return nil 188 } 189 190 func (c *Config) SetPresubmits(jobs map[string][]Presubmit) error { 191 nj := map[string][]Presubmit{} 192 for k, v := range jobs { 193 nj[k] = make([]Presubmit, len(v)) 194 copy(nj[k], v) 195 for i := range v { 196 re, err := regexp.Compile(v[i].Trigger) 197 if err != nil { 198 return err 199 } 200 nj[k][i].re = re 201 } 202 } 203 c.Presubmits = nj 204 return nil 205 } 206 207 // AllPresubmits returns all prow presubmit jobs in repos. 208 // if repos is empty, return all presubmits. 209 func (c *Config) AllPresubmits(repos []string) []Presubmit { 210 var res []Presubmit 211 var listPres func(ps []Presubmit) []Presubmit 212 listPres = func(ps []Presubmit) []Presubmit { 213 var res []Presubmit 214 for _, p := range ps { 215 res = append(res, p) 216 res = append(res, listPres(p.RunAfterSuccess)...) 217 } 218 return res 219 } 220 221 for repo, v := range c.Presubmits { 222 if len(repos) == 0 { 223 res = append(res, listPres(v)...) 224 } else { 225 for _, r := range repos { 226 if r == repo { 227 res = append(res, listPres(v)...) 228 break 229 } 230 } 231 } 232 } 233 234 return res 235 } 236 237 // AllPostsubmits returns all prow postsubmit jobs in repos. 238 // if repos is empty, return all postsubmits. 239 func (c *Config) AllPostsubmits(repos []string) []Postsubmit { 240 var res []Postsubmit 241 var listPost func(ps []Postsubmit) []Postsubmit 242 listPost = func(ps []Postsubmit) []Postsubmit { 243 var res []Postsubmit 244 for _, p := range ps { 245 res = append(res, p) 246 res = append(res, listPost(p.RunAfterSuccess)...) 247 } 248 return res 249 } 250 251 for repo, v := range c.Postsubmits { 252 if len(repos) == 0 { 253 res = append(res, listPost(v)...) 254 } else { 255 for _, r := range repos { 256 if r == repo { 257 res = append(res, listPost(v)...) 258 break 259 } 260 } 261 } 262 } 263 264 return res 265 } 266 267 // AllPostsubmits returns all prow periodic jobs. 268 func (c *Config) AllPeriodics() []Periodic { 269 var listPeriodic func(ps []Periodic) []Periodic 270 listPeriodic = func(ps []Periodic) []Periodic { 271 var res []Periodic 272 for _, p := range ps { 273 res = append(res, p) 274 res = append(res, listPeriodic(p.RunAfterSuccess)...) 275 } 276 return res 277 } 278 279 return listPeriodic(c.Periodics) 280 }