xref: /aosp_15_r20/external/skia/infra/bots/gen_tasks_logic/job_builder.go (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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	}
119
120	// Infra tests.
121	if b.extraConfig("InfraTests") {
122		b.infra()
123		return
124	}
125
126	// Housekeepers.
127	if b.Name == "Housekeeper-PerCommit" {
128		b.housekeeper()
129		return
130	}
131	if b.Name == "Housekeeper-PerCommit-CheckGeneratedFiles" {
132		b.checkGeneratedFiles()
133		return
134	}
135	if b.Name == "Housekeeper-PerCommit-GoLinters" {
136		b.goLinters()
137		return
138	}
139	if b.Name == "Housekeeper-PerCommit-RunGnToBp" {
140		b.checkGnToBp()
141		return
142	}
143	if b.Name == "Housekeeper-OnDemand-Presubmit" {
144		b.priority(1)
145		b.presubmit()
146		return
147	}
148
149	// Compile bots.
150	if b.role("Build") {
151		b.compile()
152		return
153	}
154
155	// BuildStats bots. This computes things like binary size.
156	if b.role("BuildStats") {
157		b.buildstats()
158		return
159	}
160
161	if b.role("CodeSize") {
162		b.codesize()
163		return
164	}
165
166	// Valgrind runs at a low priority so that it doesn't occupy all the bots.
167	if b.extraConfig("Valgrind") {
168		// Priority of 0.085 should result in Valgrind tasks with a blamelist of ~10 commits having the
169		// same score as other tasks with a blamelist of 1 commit, when we have insufficient bot
170		// capacity to run more frequently.
171		b.priority(0.085)
172	}
173
174	// Test bots.
175	if b.role("Test") {
176		if b.extraConfig("WasmGMTests") {
177			b.runWasmGMTests()
178			return
179		}
180		b.dm()
181		return
182	}
183
184	// Canary bots.
185	if b.role("Canary") {
186		if b.project("G3") {
187			b.g3FrameworkCanary()
188			return
189		} else if b.project("Android") {
190			b.canary("android-master-autoroll", "Canary-Android-Topic", "https://googleplex-android-review.googlesource.com/q/topic:")
191			return
192		} else if b.project("Chromium") {
193			b.canary("skia-autoroll", "Canary-Chromium-CL", "https://chromium-review.googlesource.com/c/")
194			return
195		} else if b.project("Flutter") {
196			b.canary("skia-flutter-autoroll", "Canary-Flutter-PR", "https://github.com/flutter/engine/pull/")
197			return
198		}
199	}
200
201	if b.extraConfig("Puppeteer") {
202		// TODO(kjlubick) make this a new role
203		b.puppeteer()
204		return
205	}
206
207	// Perf bots.
208	if b.role("Perf") {
209		b.perf()
210		return
211	}
212
213	if b.role("BazelBuild") {
214		b.bazelBuild()
215		return
216	}
217
218	if b.role("BazelTest") {
219		b.bazelTest()
220		return
221	}
222
223	log.Fatalf("Don't know how to handle job %q", b.Name)
224}
225
226func (b *jobBuilder) finish() {
227	// Add the Job spec.
228	if b.frequency("Nightly") {
229		b.trigger(specs.TRIGGER_NIGHTLY)
230	} else if b.frequency("Weekly") {
231		b.trigger(specs.TRIGGER_WEEKLY)
232	} else if b.extraConfig("Flutter", "CreateDockerImage", "PushAppsFromSkiaDockerImage", "PushBazelAppsFromWASMDockerImage") {
233		b.trigger(specs.TRIGGER_MAIN_ONLY)
234	} else if b.frequency("OnDemand") || b.role("Canary") {
235		b.trigger(specs.TRIGGER_ON_DEMAND)
236	} else {
237		b.trigger(specs.TRIGGER_ANY_BRANCH)
238	}
239	b.MustAddJob(b.Name, b.Spec)
240}
241