1// Copyright 2020 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4package gen_tasks_logic 5 6import ( 7 "log" 8 "strings" 9 10 "go.skia.org/infra/task_scheduler/go/specs" 11) 12 13// jobBuilder provides helpers for creating a job. 14type jobBuilder struct { 15 *builder 16 parts 17 Name string 18 Spec *specs.JobSpec 19} 20 21// newJobBuilder returns a jobBuilder for the given job name. 22func newJobBuilder(b *builder, name string) *jobBuilder { 23 p, err := b.jobNameSchema.ParseJobName(name) 24 if err != nil { 25 log.Fatal(err) 26 } 27 return &jobBuilder{ 28 builder: b, 29 parts: p, 30 Name: name, 31 Spec: &specs.JobSpec{}, 32 } 33} 34 35// priority sets the priority of the job. 36func (b *jobBuilder) priority(p float64) { 37 b.Spec.Priority = p 38} 39 40// trigger dictates when the job should be triggered. 41func (b *jobBuilder) trigger(trigger string) { 42 b.Spec.Trigger = trigger 43} 44 45// Create a taskBuilder and run the given function for it. 46func (b *jobBuilder) addTask(name string, fn func(*taskBuilder)) { 47 tb := newTaskBuilder(b, name) 48 fn(tb) 49 b.MustAddTask(tb.Name, tb.Spec) 50 // Add the task to the Job's dependency set, removing any which are 51 // accounted for by the new task's dependencies. 52 b.Spec.TaskSpecs = append(b.Spec.TaskSpecs, tb.Name) 53 newSpecs := make([]string, 0, len(b.Spec.TaskSpecs)) 54 for _, t := range b.Spec.TaskSpecs { 55 if !In(t, tb.Spec.Dependencies) { 56 newSpecs = append(newSpecs, t) 57 } 58 } 59 b.Spec.TaskSpecs = newSpecs 60} 61 62// uploadCIPDAssetToCAS generates a task to isolate the given CIPD asset. Returns 63// the name of the task. 64func (b *jobBuilder) uploadCIPDAssetToCAS(asset string) string { 65 cfg, ok := ISOLATE_ASSET_MAPPING[asset] 66 if !ok { 67 log.Fatalf("No isolate task for asset %q", asset) 68 } 69 b.addTask(cfg.uploadTaskName, func(b *taskBuilder) { 70 b.cipd(b.MustGetCipdPackageFromAsset(asset)) 71 b.cmd("/bin/cp", "-rL", cfg.path, "${ISOLATED_OUTDIR}") 72 b.linuxGceDimensions(MACHINE_TYPE_SMALL) 73 b.idempotent() 74 b.cas(CAS_EMPTY) 75 }) 76 return cfg.uploadTaskName 77} 78 79// genTasksForJob generates the tasks needed by this job. 80func (b *jobBuilder) genTasksForJob() { 81 // Bundle Recipes. 82 if b.Name == BUNDLE_RECIPES_NAME { 83 b.bundleRecipes() 84 return 85 } 86 if strings.HasPrefix(b.Name, BUILD_TASK_DRIVERS_PREFIX) { 87 parts := strings.Split(b.Name, "_") 88 b.buildTaskDrivers(parts[1], parts[2]) 89 return 90 } 91 92 // Isolate CIPD assets. 93 if b.matchExtraConfig("Isolate") { 94 for asset, cfg := range ISOLATE_ASSET_MAPPING { 95 if cfg.uploadTaskName == b.Name { 96 b.uploadCIPDAssetToCAS(asset) 97 return 98 } 99 } 100 } 101 102 // RecreateSKPs. 103 if b.extraConfig("RecreateSKPs") { 104 b.recreateSKPs() 105 return 106 } 107 108 // Create docker image. 109 if b.extraConfig("CreateDockerImage") { 110 b.createDockerImage(b.extraConfig("WASM")) 111 return 112 } 113 114 // Push apps from docker image. 115 if b.extraConfig("PushAppsFromSkiaDockerImage") { 116 b.createPushAppsFromSkiaDockerImage() 117 return 118 } else if b.extraConfig("PushBazelAppsFromWASMDockerImage") { 119 b.createPushBazelAppsFromWASMDockerImage() 120 return 121 } 122 123 // Infra tests. 124 if b.extraConfig("InfraTests") { 125 b.infra() 126 return 127 } 128 129 // Housekeepers. 130 if b.Name == "Housekeeper-PerCommit" { 131 b.housekeeper() 132 return 133 } 134 if b.Name == "Housekeeper-PerCommit-CheckGeneratedFiles" { 135 b.checkGeneratedFiles() 136 return 137 } 138 if b.Name == "Housekeeper-PerCommit-GoLinters" { 139 b.goLinters() 140 return 141 } 142 if b.Name == "Housekeeper-PerCommit-RunGnToBp" { 143 b.checkGnToBp() 144 return 145 } 146 if b.Name == "Housekeeper-OnDemand-Presubmit" { 147 b.priority(1) 148 b.presubmit() 149 return 150 } 151 152 // Compile bots. 153 if b.role("Build") { 154 b.compile() 155 return 156 } 157 158 // BuildStats bots. This computes things like binary size. 159 if b.role("BuildStats") { 160 b.buildstats() 161 return 162 } 163 164 if b.role("CodeSize") { 165 b.codesize() 166 return 167 } 168 169 // Valgrind runs at a low priority so that it doesn't occupy all the bots. 170 if b.extraConfig("Valgrind") { 171 // Priority of 0.085 should result in Valgrind tasks with a blamelist of ~10 commits having the 172 // same score as other tasks with a blamelist of 1 commit, when we have insufficient bot 173 // capacity to run more frequently. 174 b.priority(0.085) 175 } 176 177 // Test bots. 178 if b.role("Test") { 179 if b.extraConfig("WasmGMTests") { 180 b.runWasmGMTests() 181 return 182 } 183 b.dm() 184 return 185 } 186 187 // Canary bots. 188 if b.role("Canary") { 189 if b.project("G3") { 190 b.g3FrameworkCanary() 191 return 192 } else if b.project("Android") { 193 b.canary("android-master-autoroll", "Canary-Android-Topic", "https://googleplex-android-review.googlesource.com/q/topic:") 194 return 195 } else if b.project("Chromium") { 196 b.canary("skia-autoroll", "Canary-Chromium-CL", "https://chromium-review.googlesource.com/c/") 197 return 198 } else if b.project("Flutter") { 199 b.canary("skia-flutter-autoroll", "Canary-Flutter-PR", "https://github.com/flutter/engine/pull/") 200 return 201 } 202 } 203 204 if b.extraConfig("Puppeteer") { 205 // TODO(kjlubick) make this a new role 206 b.puppeteer() 207 return 208 } 209 210 // Perf bots. 211 if b.role("Perf") { 212 b.perf() 213 return 214 } 215 216 if b.role("BazelBuild") { 217 b.bazelBuild() 218 return 219 } 220 221 if b.role("BazelTest") { 222 b.bazelTest() 223 return 224 } 225 226 log.Fatalf("Don't know how to handle job %q", b.Name) 227} 228 229func (b *jobBuilder) finish() { 230 // Add the Job spec. 231 if b.frequency("Nightly") { 232 b.trigger(specs.TRIGGER_NIGHTLY) 233 } else if b.frequency("Weekly") { 234 b.trigger(specs.TRIGGER_WEEKLY) 235 } else if b.extraConfig("Flutter", "CreateDockerImage", "PushAppsFromSkiaDockerImage", "PushBazelAppsFromWASMDockerImage") { 236 b.trigger(specs.TRIGGER_MAIN_ONLY) 237 } else if b.frequency("OnDemand") || b.role("Canary") { 238 b.trigger(specs.TRIGGER_ON_DEMAND) 239 } else { 240 b.trigger(specs.TRIGGER_ANY_BRANCH) 241 } 242 b.MustAddJob(b.Name, b.Spec) 243} 244