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