blob: 3c57da9f2961faf7d0de7cb99ccfe96bb11f26ac [file] [log] [blame]
borenetdb182c72016-09-30 12:53:12 -07001// Copyright 2016 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.
4
5package main
6
7/*
8 Generate the tasks.json file.
9*/
10
11import (
borenetdb182c72016-09-30 12:53:12 -070012 "encoding/json"
Eric Boren27225492017-02-01 15:56:55 -050013 "flag"
borenetdb182c72016-09-30 12:53:12 -070014 "fmt"
Eric Boren27225492017-02-01 15:56:55 -050015 "io/ioutil"
borenetdb182c72016-09-30 12:53:12 -070016 "os"
17 "path"
Eric Boren7e3a3642017-06-14 15:25:31 -040018 "path/filepath"
Eric Boren27225492017-02-01 15:56:55 -050019 "regexp"
Eric Boren7e3a3642017-06-14 15:25:31 -040020 "runtime"
borenetdb182c72016-09-30 12:53:12 -070021 "sort"
Kevin Lubick32f318b2017-10-17 13:40:52 -040022 "strconv"
borenetdb182c72016-09-30 12:53:12 -070023 "strings"
Eric Boren4b254b92016-11-08 12:55:32 -050024 "time"
borenetdb182c72016-09-30 12:53:12 -070025
26 "github.com/skia-dev/glog"
Eric Boren7e3a3642017-06-14 15:25:31 -040027 "go.skia.org/infra/go/sklog"
borenetdb182c72016-09-30 12:53:12 -070028 "go.skia.org/infra/go/util"
29 "go.skia.org/infra/task_scheduler/go/specs"
30)
31
32const (
Kevin Lubick814b1492017-11-29 14:45:14 -050033 BUNDLE_RECIPES_NAME = "Housekeeper-PerCommit-BundleRecipes"
34 ISOLATE_SKIMAGE_NAME = "Housekeeper-PerCommit-IsolateSkImage"
35 ISOLATE_SKP_NAME = "Housekeeper-PerCommit-IsolateSKP"
36 ISOLATE_SVG_NAME = "Housekeeper-PerCommit-IsolateSVG"
37 ISOLATE_NDK_LINUX_NAME = "Housekeeper-PerCommit-IsolateAndroidNDKLinux"
38 ISOLATE_WIN_TOOLCHAIN_NAME = "Housekeeper-PerCommit-IsolateWinToolchain"
39 ISOLATE_WIN_VULKAN_SDK_NAME = "Housekeeper-PerCommit-IsolateWinVulkanSDK"
Eric Boren8b3f9e62017-04-04 09:06:16 -040040
Eric Boren170c39c2017-11-15 11:22:57 -050041 DEFAULT_OS_DEBIAN = "Debian-9.1"
42 DEFAULT_OS_LINUX_GCE = "Debian-9.2"
Ben Wagner3f679142017-11-27 13:02:25 -050043 DEFAULT_OS_MAC = "Mac-10.13.1"
Eric Boren170c39c2017-11-15 11:22:57 -050044 DEFAULT_OS_UBUNTU = "Ubuntu-14.04"
45 DEFAULT_OS_WIN = "Windows-2016Server-14393"
borenetdb182c72016-09-30 12:53:12 -070046
borenetdb182c72016-09-30 12:53:12 -070047 // Name prefix for upload jobs.
48 PREFIX_UPLOAD = "Upload"
49)
50
51var (
52 // "Constants"
53
Eric Boren27225492017-02-01 15:56:55 -050054 // Top-level list of all jobs to run at each commit; loaded from
55 // jobs.json.
56 JOBS []string
57
Eric Boren27225492017-02-01 15:56:55 -050058 // General configuration information.
59 CONFIG struct {
Kevin Lubickc795a4c2017-10-09 15:26:19 -040060 GsBucketCoverage string `json:"gs_bucket_coverage"`
61 GsBucketGm string `json:"gs_bucket_gm"`
62 GsBucketNano string `json:"gs_bucket_nano"`
Yuqian Li2ebf3d12017-10-24 09:43:21 -040063 GsBucketCalm string `json:"gs_bucket_calm"`
Kevin Lubickc795a4c2017-10-09 15:26:19 -040064 NoUpload []string `json:"no_upload"`
65 Pool string `json:"pool"`
borenetdb182c72016-09-30 12:53:12 -070066 }
67
Ben Wagner3d2a2f72017-06-13 17:01:16 -040068 // alternateSwarmDimensions can be set in an init function to override the default swarming bot
69 // dimensions for the given task.
70 alternateSwarmDimensions func(parts map[string]string) []string
71
Eric Borenfd4d60e2017-09-15 10:35:44 -040072 // internalHardwareLabelFn can be set in an init function to provide an
73 // internal_hardware_label variable to the recipe.
Eric Boren4dc4aaf2017-09-15 14:09:07 -040074 internalHardwareLabelFn func(parts map[string]string) *int
Eric Boren053d7a42017-09-15 08:35:31 -040075
borenetdb182c72016-09-30 12:53:12 -070076 // Defines the structure of job names.
77 jobNameSchema *JobNameSchema
Eric Boren27225492017-02-01 15:56:55 -050078
Eric Borenf4a5fc72017-06-06 08:27:09 -040079 // Git 2.13.
Eric Boren9d78afd2017-12-07 14:54:05 +000080 cipdGit1 = &specs.CipdPackage{
81 Name: fmt.Sprintf("infra/git/${platform}"),
82 Path: "git",
83 Version: fmt.Sprintf("version:2.13.0.chromium9"),
Eric Borenf4a5fc72017-06-06 08:27:09 -040084 }
Eric Boren9d78afd2017-12-07 14:54:05 +000085 cipdGit2 = &specs.CipdPackage{
86 Name: fmt.Sprintf("infra/tools/git/${platform}"),
87 Path: "git",
88 Version: fmt.Sprintf("git_revision:a78b5f3658c0578a017db48df97d20ac09822bcd"),
89 }
Eric Borenf4a5fc72017-06-06 08:27:09 -040090
Eric Boren27225492017-02-01 15:56:55 -050091 // Flags.
Eric Boren1f8be682017-02-07 09:16:30 -050092 builderNameSchemaFile = flag.String("builder_name_schema", "", "Path to the builder_name_schema.json file. If not specified, uses infra/bots/recipe_modules/builder_name_schema/builder_name_schema.json from this repo.")
93 assetsDir = flag.String("assets_dir", "", "Directory containing assets.")
94 cfgFile = flag.String("cfg_file", "", "JSON file containing general configuration information.")
Eric Boren1f8be682017-02-07 09:16:30 -050095 jobsFile = flag.String("jobs", "", "JSON file containing jobs to run.")
borenetdb182c72016-09-30 12:53:12 -070096)
97
Eric Borenfd4d60e2017-09-15 10:35:44 -040098// internalHardwareLabel returns the internal ID for the bot, if any.
Eric Boren4dc4aaf2017-09-15 14:09:07 -040099func internalHardwareLabel(parts map[string]string) *int {
Eric Borenfd4d60e2017-09-15 10:35:44 -0400100 if internalHardwareLabelFn != nil {
101 return internalHardwareLabelFn(parts)
Eric Boren053d7a42017-09-15 08:35:31 -0400102 }
103 return nil
104}
105
Eric Boren27225492017-02-01 15:56:55 -0500106// linuxGceDimensions are the Swarming dimensions for Linux GCE
107// instances.
108func linuxGceDimensions() []string {
109 return []string{
Ben Wagner4c9842e2017-09-25 12:56:53 -0400110 // Specify CPU to avoid running builds on bots with a more unique CPU.
111 "cpu:x86-64-Haswell_GCE",
Eric Boren27225492017-02-01 15:56:55 -0500112 "gpu:none",
Eric Boren170c39c2017-11-15 11:22:57 -0500113 fmt.Sprintf("os:%s", DEFAULT_OS_LINUX_GCE),
Eric Boren27225492017-02-01 15:56:55 -0500114 fmt.Sprintf("pool:%s", CONFIG.Pool),
115 }
116}
117
borenetdb182c72016-09-30 12:53:12 -0700118// deriveCompileTaskName returns the name of a compile task based on the given
119// job name.
120func deriveCompileTaskName(jobName string, parts map[string]string) string {
121 if parts["role"] == "Housekeeper" {
Eric Borenbb198fb2017-06-28 11:45:54 -0400122 return "Build-Debian9-GCC-x86_64-Release-Shared"
borenetdb182c72016-09-30 12:53:12 -0700123 } else if parts["role"] == "Test" || parts["role"] == "Perf" {
124 task_os := parts["os"]
Ben Wagner988d15e2017-04-27 13:08:50 -0400125 ec := []string{}
126 if val := parts["extra_config"]; val != "" {
127 ec = strings.Split(val, "_")
Mike Klein0c5fdcb2017-11-13 12:40:46 -0500128 ignore := []string{"Skpbench", "AbandonGpuContext", "PreAbandonGpuContext", "Valgrind", "ReleaseAndAbandonGpuContext", "CCPR", "FSAA", "FAAA", "FDAA", "NativeFonts", "GDI"}
Ben Wagner988d15e2017-04-27 13:08:50 -0400129 keep := make([]string, 0, len(ec))
130 for _, part := range ec {
131 if !util.In(part, ignore) {
132 keep = append(keep, part)
133 }
134 }
135 ec = keep
Eric Boren6ec17e32017-04-26 14:25:29 -0400136 }
borenetdb182c72016-09-30 12:53:12 -0700137 if task_os == "Android" {
Ben Wagner988d15e2017-04-27 13:08:50 -0400138 if !util.In("Android", ec) {
139 ec = append([]string{"Android"}, ec...)
borenetdb182c72016-09-30 12:53:12 -0700140 }
Eric Borenbb198fb2017-06-28 11:45:54 -0400141 task_os = "Debian9"
Kevin Lubickdcd2a902017-03-08 14:01:01 -0500142 } else if task_os == "Chromecast" {
Eric Borenbb198fb2017-06-28 11:45:54 -0400143 task_os = "Debian9"
Ben Wagner988d15e2017-04-27 13:08:50 -0400144 ec = append([]string{"Chromecast"}, ec...)
Kevin Lubickcb6f3982017-04-07 10:04:08 -0400145 } else if strings.Contains(task_os, "ChromeOS") {
Kevin Lubickb718fbb2017-11-02 09:34:08 -0400146 ec = append([]string{"Chromebook", "GLES"}, ec...)
Eric Borenbb198fb2017-06-28 11:45:54 -0400147 task_os = "Debian9"
borenetdb182c72016-09-30 12:53:12 -0700148 } else if task_os == "iOS" {
Ben Wagner988d15e2017-04-27 13:08:50 -0400149 ec = append([]string{task_os}, ec...)
borenetdb182c72016-09-30 12:53:12 -0700150 task_os = "Mac"
151 } else if strings.Contains(task_os, "Win") {
152 task_os = "Win"
Eric Borenbb198fb2017-06-28 11:45:54 -0400153 } else if strings.Contains(task_os, "Ubuntu") || strings.Contains(task_os, "Debian") {
154 task_os = "Debian9"
borenetdb182c72016-09-30 12:53:12 -0700155 }
Eric Boren50831302016-11-18 13:10:51 -0500156 jobNameMap := map[string]string{
borenetdb182c72016-09-30 12:53:12 -0700157 "role": "Build",
158 "os": task_os,
159 "compiler": parts["compiler"],
160 "target_arch": parts["arch"],
161 "configuration": parts["configuration"],
Eric Boren50831302016-11-18 13:10:51 -0500162 }
Ben Wagner988d15e2017-04-27 13:08:50 -0400163 if len(ec) > 0 {
164 jobNameMap["extra_config"] = strings.Join(ec, "_")
Eric Boren50831302016-11-18 13:10:51 -0500165 }
166 name, err := jobNameSchema.MakeJobName(jobNameMap)
borenetdb182c72016-09-30 12:53:12 -0700167 if err != nil {
168 glog.Fatal(err)
169 }
170 return name
171 } else {
172 return jobName
173 }
174}
175
176// swarmDimensions generates swarming bot dimensions for the given task.
177func swarmDimensions(parts map[string]string) []string {
Ben Wagner3d2a2f72017-06-13 17:01:16 -0400178 if alternateSwarmDimensions != nil {
179 return alternateSwarmDimensions(parts)
180 }
181 return defaultSwarmDimensions(parts)
182}
183
184// defaultSwarmDimensions generates default swarming bot dimensions for the given task.
185func defaultSwarmDimensions(parts map[string]string) []string {
borenetdb182c72016-09-30 12:53:12 -0700186 d := map[string]string{
Eric Boren27225492017-02-01 15:56:55 -0500187 "pool": CONFIG.Pool,
borenetdb182c72016-09-30 12:53:12 -0700188 }
189 if os, ok := parts["os"]; ok {
Ben Wagner3d2a2f72017-06-13 17:01:16 -0400190 d["os"], ok = map[string]string{
Kevin Lubick291547d2017-03-21 09:25:34 -0400191 "Android": "Android",
192 "Chromecast": "Android",
Kevin Lubickcb6f3982017-04-07 10:04:08 -0400193 "ChromeOS": "ChromeOS",
Eric Borenbb198fb2017-06-28 11:45:54 -0400194 "Debian9": DEFAULT_OS_DEBIAN,
Ben Wagnerd3fdcc92017-11-14 13:30:04 -0500195 "Mac": DEFAULT_OS_MAC,
Eric Borenbb198fb2017-06-28 11:45:54 -0400196 "Ubuntu14": DEFAULT_OS_UBUNTU,
Kevin Lubick291547d2017-03-21 09:25:34 -0400197 "Ubuntu16": "Ubuntu-16.10",
Eric Boren810c2b62017-07-11 08:11:15 -0400198 "Ubuntu17": "Ubuntu-17.04",
Ben Wagnerd3fdcc92017-11-14 13:30:04 -0500199 "Win": DEFAULT_OS_WIN,
Ben Wagner40226b42017-05-02 13:13:13 -0400200 "Win10": "Windows-10-15063",
Kevin Lubick291547d2017-03-21 09:25:34 -0400201 "Win2k8": "Windows-2008ServerR2-SP1",
Ben Wagnerd3fdcc92017-11-14 13:30:04 -0500202 "Win2016": DEFAULT_OS_WIN,
Ben Wagner56738d82017-04-18 15:38:15 -0400203 "Win7": "Windows-7-SP1",
Kevin Lubick291547d2017-03-21 09:25:34 -0400204 "Win8": "Windows-8.1-SP0",
Stephan Altmuellerddad85b2017-05-19 13:08:19 -0400205 "iOS": "iOS-10.3.1",
Eric Boren54ff2fc2016-12-02 12:09:10 -0500206 }[os]
Ben Wagner3d2a2f72017-06-13 17:01:16 -0400207 if !ok {
208 glog.Fatalf("Entry %q not found in OS mapping.", os)
209 }
borenetdb182c72016-09-30 12:53:12 -0700210 } else {
Eric Borenbb198fb2017-06-28 11:45:54 -0400211 d["os"] = DEFAULT_OS_DEBIAN
borenetdb182c72016-09-30 12:53:12 -0700212 }
Yuqian Liab246cb2017-11-02 13:48:23 -0400213 if parts["role"] == "Test" || parts["role"] == "Perf" || parts["role"] == "Calmbench" {
Kevin Lubick291547d2017-03-21 09:25:34 -0400214 if strings.Contains(parts["os"], "Android") || strings.Contains(parts["os"], "Chromecast") {
borenetdb182c72016-09-30 12:53:12 -0700215 // For Android, the device type is a better dimension
216 // than CPU or GPU.
Ben Wagner36682782017-06-14 10:01:45 -0400217 deviceInfo, ok := map[string][]string{
Ben Wagner3d2a2f72017-06-13 17:01:16 -0400218 "AndroidOne": {"sprout", "MOB30Q"},
219 "Chorizo": {"chorizo", "1.24_82923"},
Ben Wagner0762bdf2017-11-28 09:41:48 -0500220 "GalaxyS6": {"zerofltetmo", "NRD90M_G920TUVU5FQK1"},
Ben Wagner3d2a2f72017-06-13 17:01:16 -0400221 "GalaxyS7_G930A": {"heroqlteatt", "NRD90M_G930AUCS4BQC2"},
222 "GalaxyS7_G930FD": {"herolte", "NRD90M_G930FXXU1DQAS"},
Ben Wagner3d2a2f72017-06-13 17:01:16 -0400223 "MotoG4": {"athene", "NPJ25.93-14"},
Ben Wagneree3123c2017-12-06 16:29:04 -0500224 "NVIDIA_Shield": {"foster", "NRD90M_1915764_848"},
225 "Nexus10": {"manta", "LMY49J_2640980"},
226 "Nexus5": {"hammerhead", "M4B30Z_3437181"},
Ben Wagnereb549c82017-11-17 08:59:44 -0500227 "Nexus5x": {"bullhead", "OPR6.170623.023"},
Ben Wagneree3123c2017-12-06 16:29:04 -0500228 "Nexus7": {"grouper", "LMY47V_1836172"}, // 2012 Nexus 7
Ben Wagner9539a8c2017-11-02 14:09:32 -0400229 "NexusPlayer": {"fugu", "OPR6.170623.021"},
Kevin Lubick832b2222017-09-26 14:07:38 -0400230 "Pixel": {"sailfish", "OPR3.170623.008"},
Kevin Lubickb018f7b2017-10-31 14:44:08 -0400231 "Pixel2XL": {"taimen", "OPD1.170816.023"},
Kevin Lubick674027a2017-10-31 09:47:38 -0400232 "PixelC": {"dragon", "OPR1.170623.034"},
Kevin Lubick832b2222017-09-26 14:07:38 -0400233 "PixelXL": {"marlin", "OPR3.170623.008"},
Ben Wagner36682782017-06-14 10:01:45 -0400234 }[parts["model"]]
Eric Boren27225492017-02-01 15:56:55 -0500235 if !ok {
Ben Wagner36682782017-06-14 10:01:45 -0400236 glog.Fatalf("Entry %q not found in Android mapping.", parts["model"])
Eric Boren27225492017-02-01 15:56:55 -0500237 }
Eric Boren4b254b92016-11-08 12:55:32 -0500238 d["device_type"] = deviceInfo[0]
239 d["device_os"] = deviceInfo[1]
Kevin Lubick4fd283e2017-12-07 11:19:31 -0500240 // TODO(kjlubick): Remove the python dimension after we have removed the
241 // Nexus5x devices from the local lab (on Monday, Dec 11, 2017 should be fine).
Kevin Lubick0f727ff2017-12-06 15:05:29 -0500242 d["python"] = "2.7.9" // This indicates a RPI, e.g. in Skolo. Golo is 2.7.12
Kevin Lubick4fd283e2017-12-07 11:19:31 -0500243 if parts["model"] == "Nexus5x" {
244 d["python"] = "2.7.12"
245 }
borenetdb182c72016-09-30 12:53:12 -0700246 } else if strings.Contains(parts["os"], "iOS") {
Ben Wagner3d2a2f72017-06-13 17:01:16 -0400247 device, ok := map[string]string{
Eric Boren792079c2016-11-09 14:03:20 -0500248 "iPadMini4": "iPad5,1",
Stephan Altmueller63e843d2017-04-25 11:38:38 -0400249 "iPhone6": "iPhone7,2",
250 "iPhone7": "iPhone9,1",
251 "iPadPro": "iPad6,3",
borenetdb182c72016-09-30 12:53:12 -0700252 }[parts["model"]]
Ben Wagner3d2a2f72017-06-13 17:01:16 -0400253 if !ok {
254 glog.Fatalf("Entry %q not found in iOS mapping.", parts["model"])
255 }
256 d["device"] = device
borenetdb182c72016-09-30 12:53:12 -0700257 } else if parts["cpu_or_gpu"] == "CPU" {
Ben Wagner4c9842e2017-09-25 12:56:53 -0400258 modelMapping, ok := map[string]map[string]string{
259 "AVX": {
260 "MacMini7.1": "x86-64-E5-2697_v2",
261 "Golo": "x86-64-E5-2670",
262 },
263 "AVX2": {
Ben Wagner85fb42a2017-11-07 16:57:37 -0500264 "GCE": "x86-64-Haswell_GCE",
Mike Klein9a01a212017-11-03 12:19:54 -0400265 "NUC5i7RYH": "x86-64-i7-5557U",
Ben Wagner4c9842e2017-09-25 12:56:53 -0400266 },
Ben Wagnerb268d232017-09-28 16:38:34 -0400267 "AVX512": {
268 "GCE": "x86-64-Skylake_GCE",
269 },
borenetdb182c72016-09-30 12:53:12 -0700270 }[parts["cpu_or_gpu_value"]]
Ben Wagner3d2a2f72017-06-13 17:01:16 -0400271 if !ok {
272 glog.Fatalf("Entry %q not found in CPU mapping.", parts["cpu_or_gpu_value"])
273 }
Ben Wagner4c9842e2017-09-25 12:56:53 -0400274 cpu, ok := modelMapping[parts["model"]]
275 if !ok {
276 glog.Fatalf("Entry %q not found in %q model mapping.", parts["model"], parts["cpu_or_gpu_value"])
borenetdb182c72016-09-30 12:53:12 -0700277 }
Ben Wagner4c9842e2017-09-25 12:56:53 -0400278 d["cpu"] = cpu
Eric Boren170c39c2017-11-15 11:22:57 -0500279 if parts["model"] == "GCE" && d["os"] == DEFAULT_OS_DEBIAN {
280 d["os"] = DEFAULT_OS_LINUX_GCE
281 }
borenetdb182c72016-09-30 12:53:12 -0700282 } else {
Ben Wagner1d060782017-06-14 10:34:18 -0400283 if strings.Contains(parts["os"], "Win") {
284 gpu, ok := map[string]string{
Ben Wagner0d2b0912017-08-15 12:43:55 -0400285 "GT610": "10de:104a-22.21.13.8205",
Ben Wagner85fb42a2017-11-07 16:57:37 -0500286 "GTX1070": "10de:1ba1-23.21.13.8813",
287 "GTX660": "10de:11c0-23.21.13.8813",
288 "GTX960": "10de:1401-23.21.13.8813",
Ben Wagner1d060782017-06-14 10:34:18 -0400289 "IntelHD530": "8086:1912-21.20.16.4590",
Ben Wagner5698b002017-08-04 11:25:33 -0400290 "IntelHD4400": "8086:0a16-20.19.15.4703",
Ben Wagner3c286532017-08-11 10:35:57 -0400291 "IntelHD4600": "8086:0412-20.19.15.4703",
Ben Wagner1d060782017-06-14 10:34:18 -0400292 "IntelIris540": "8086:1926-21.20.16.4590",
Ben Wagner3c286532017-08-11 10:35:57 -0400293 "IntelIris6100": "8086:162b-20.19.15.4703",
Ben Wagner2040ed22017-11-22 11:22:22 -0500294 "RadeonHD7770": "1002:683d-22.19.165.512",
Ben Wagner1d060782017-06-14 10:34:18 -0400295 "RadeonR9M470X": "1002:6646-22.19.165.512",
Ben Wagnerae532f62017-08-02 23:24:16 -0400296 "QuadroP400": "10de:1cb3-22.21.13.8205",
Ben Wagner1d060782017-06-14 10:34:18 -0400297 }[parts["cpu_or_gpu_value"]]
298 if !ok {
299 glog.Fatalf("Entry %q not found in Win GPU mapping.", parts["cpu_or_gpu_value"])
300 }
301 d["gpu"] = gpu
Ben Wagner08435892017-02-18 23:28:26 -0500302
Ben Wagner4b1df022017-06-15 12:28:04 -0400303 // Specify cpu dimension for NUCs and ShuttleCs. We temporarily have two
304 // types of machines with a GTX960.
305 cpu, ok := map[string]string{
306 "NUC6i7KYK": "x86-64-i7-6770HQ",
307 "ShuttleC": "x86-64-i7-6700K",
Ben Wagner1d060782017-06-14 10:34:18 -0400308 }[parts["model"]]
309 if ok {
Ben Wagner4b1df022017-06-15 12:28:04 -0400310 d["cpu"] = cpu
Ben Wagner1d060782017-06-14 10:34:18 -0400311 }
Eric Borenbb198fb2017-06-28 11:45:54 -0400312 } else if strings.Contains(parts["os"], "Ubuntu") || strings.Contains(parts["os"], "Debian") {
Ben Wagner1d060782017-06-14 10:34:18 -0400313 gpu, ok := map[string]string{
Ben Wagner1d060782017-06-14 10:34:18 -0400314 // Intel drivers come from CIPD, so no need to specify the version here.
315 "IntelBayTrail": "8086:0f31",
316 "IntelHD2000": "8086:0102",
317 "IntelHD405": "8086:22b1",
318 "IntelIris540": "8086:1926",
Ben Wagnerc274ec42017-08-03 22:29:22 -0400319 "QuadroP400": "10de:1cb3-384.59",
Ben Wagner1d060782017-06-14 10:34:18 -0400320 }[parts["cpu_or_gpu_value"]]
321 if !ok {
322 glog.Fatalf("Entry %q not found in Ubuntu GPU mapping.", parts["cpu_or_gpu_value"])
323 }
324 d["gpu"] = gpu
325 } else if strings.Contains(parts["os"], "Mac") {
326 gpu, ok := map[string]string{
Ben Wagnercc4221b2017-08-17 17:29:04 -0400327 "IntelIris5100": "8086:0a2e",
Ben Wagner1d060782017-06-14 10:34:18 -0400328 }[parts["cpu_or_gpu_value"]]
329 if !ok {
330 glog.Fatalf("Entry %q not found in Mac GPU mapping.", parts["cpu_or_gpu_value"])
331 }
332 d["gpu"] = gpu
333 } else if strings.Contains(parts["os"], "ChromeOS") {
Kevin Lubick64ca6be2017-12-04 15:43:31 -0500334 version, ok := map[string]string{
335 "MaliT604": "9901.12.0",
336 "MaliT764": "10172.0.0",
337 "MaliT860": "10172.0.0",
Kevin Lubick0b1b9c22017-12-08 14:14:38 -0500338 "PowerVRGX6250": "10176.5.0",
Kevin Lubick64ca6be2017-12-04 15:43:31 -0500339 "TegraK1": "10172.0.0",
340 "IntelHDGraphics615": "10032.17.0",
Ben Wagner1d060782017-06-14 10:34:18 -0400341 }[parts["cpu_or_gpu_value"]]
342 if !ok {
343 glog.Fatalf("Entry %q not found in ChromeOS GPU mapping.", parts["cpu_or_gpu_value"])
344 }
Kevin Lubick64ca6be2017-12-04 15:43:31 -0500345 d["gpu"] = parts["cpu_or_gpu_value"]
346 d["release_version"] = version
Ben Wagner1d060782017-06-14 10:34:18 -0400347 } else {
348 glog.Fatalf("Unknown GPU mapping for OS %q.", parts["os"])
Ben Wagner08435892017-02-18 23:28:26 -0500349 }
borenetdb182c72016-09-30 12:53:12 -0700350 }
351 } else {
352 d["gpu"] = "none"
Eric Borenbb198fb2017-06-28 11:45:54 -0400353 if d["os"] == DEFAULT_OS_DEBIAN {
Kevin Lubick4610a9b2017-03-22 15:54:54 -0400354 return linuxGceDimensions()
Ben Wagnerd3fdcc92017-11-14 13:30:04 -0500355 } else if d["os"] == DEFAULT_OS_WIN {
356 // Windows CPU bots.
Ben Wagnera78f1bc2017-09-26 18:19:56 -0400357 d["cpu"] = "x86-64-Haswell_GCE"
Ben Wagnerd3fdcc92017-11-14 13:30:04 -0500358 } else if d["os"] == DEFAULT_OS_MAC {
359 // Mac CPU bots.
Ben Wagnera78f1bc2017-09-26 18:19:56 -0400360 d["cpu"] = "x86-64-E5-2697_v2"
Kevin Lubick4610a9b2017-03-22 15:54:54 -0400361 }
borenetdb182c72016-09-30 12:53:12 -0700362 }
Kevin Lubick4610a9b2017-03-22 15:54:54 -0400363
borenetdb182c72016-09-30 12:53:12 -0700364 rv := make([]string, 0, len(d))
365 for k, v := range d {
366 rv = append(rv, fmt.Sprintf("%s:%s", k, v))
367 }
368 sort.Strings(rv)
369 return rv
370}
371
Eric Boren7e3a3642017-06-14 15:25:31 -0400372// relpath returns the relative path to the given file from the config file.
373func relpath(f string) string {
374 _, filename, _, _ := runtime.Caller(0)
375 dir := path.Dir(filename)
376 rel := dir
377 if *cfgFile != "" {
378 rel = path.Dir(*cfgFile)
379 }
380 rv, err := filepath.Rel(rel, path.Join(dir, f))
381 if err != nil {
382 sklog.Fatal(err)
383 }
384 return rv
385}
386
Eric Boren8b3f9e62017-04-04 09:06:16 -0400387// bundleRecipes generates the task to bundle and isolate the recipes.
388func bundleRecipes(b *specs.TasksCfgBuilder) string {
389 b.MustAddTask(BUNDLE_RECIPES_NAME, &specs.TaskSpec{
Eric Boren9d78afd2017-12-07 14:54:05 +0000390 CipdPackages: []*specs.CipdPackage{cipdGit1, cipdGit2},
391 Dimensions: linuxGceDimensions(),
392 ExtraArgs: []string{
393 "--workdir", "../../..", "bundle_recipes",
394 fmt.Sprintf("buildername=%s", BUNDLE_RECIPES_NAME),
395 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
Eric Boren8b3f9e62017-04-04 09:06:16 -0400396 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000397 Isolate: relpath("bundle_recipes.isolate"),
Kevin Lubick07072942017-05-11 13:35:23 -0400398 Priority: 0.7,
Eric Boren8b3f9e62017-04-04 09:06:16 -0400399 })
400 return BUNDLE_RECIPES_NAME
401}
402
Eric Boren23a6ec62017-04-07 08:31:22 -0400403// useBundledRecipes returns true iff the given bot should use bundled recipes
404// instead of syncing recipe DEPS itself.
405func useBundledRecipes(parts map[string]string) bool {
406 // Use bundled recipes for all test/perf tasks.
407 return true
408}
409
Kevin Lubick07072942017-05-11 13:35:23 -0400410type isolateAssetCfg struct {
Eric Boren9d78afd2017-12-07 14:54:05 +0000411 isolateFile string
412 cipdPkg string
Kevin Lubick07072942017-05-11 13:35:23 -0400413}
414
415var ISOLATE_ASSET_MAPPING = map[string]isolateAssetCfg{
416 ISOLATE_SKIMAGE_NAME: {
Eric Boren9d78afd2017-12-07 14:54:05 +0000417 isolateFile: "isolate_skimage.isolate",
418 cipdPkg: "skimage",
Kevin Lubick07072942017-05-11 13:35:23 -0400419 },
420 ISOLATE_SKP_NAME: {
Eric Boren9d78afd2017-12-07 14:54:05 +0000421 isolateFile: "isolate_skp.isolate",
422 cipdPkg: "skp",
Kevin Lubick07072942017-05-11 13:35:23 -0400423 },
424 ISOLATE_SVG_NAME: {
Eric Boren9d78afd2017-12-07 14:54:05 +0000425 isolateFile: "isolate_svg.isolate",
426 cipdPkg: "svg",
Kevin Lubick07072942017-05-11 13:35:23 -0400427 },
Kevin Lubick814b1492017-11-29 14:45:14 -0500428 ISOLATE_NDK_LINUX_NAME: {
Eric Boren9d78afd2017-12-07 14:54:05 +0000429 isolateFile: "isolate_ndk_linux.isolate",
430 cipdPkg: "android_ndk_linux",
Kevin Lubick814b1492017-11-29 14:45:14 -0500431 },
432 ISOLATE_WIN_TOOLCHAIN_NAME: {
Eric Boren9d78afd2017-12-07 14:54:05 +0000433 isolateFile: "isolate_win_toolchain.isolate",
434 cipdPkg: "win_toolchain",
Kevin Lubick814b1492017-11-29 14:45:14 -0500435 },
436 ISOLATE_WIN_VULKAN_SDK_NAME: {
Eric Boren9d78afd2017-12-07 14:54:05 +0000437 isolateFile: "isolate_win_vulkan_sdk.isolate",
438 cipdPkg: "win_vulkan_sdk",
Kevin Lubick814b1492017-11-29 14:45:14 -0500439 },
Kevin Lubick07072942017-05-11 13:35:23 -0400440}
441
Eric Boren9d78afd2017-12-07 14:54:05 +0000442// bundleRecipes generates the task to bundle and isolate the recipes.
Kevin Lubick07072942017-05-11 13:35:23 -0400443func isolateCIPDAsset(b *specs.TasksCfgBuilder, name string) string {
444 b.MustAddTask(name, &specs.TaskSpec{
445 CipdPackages: []*specs.CipdPackage{
Eric Boren9d78afd2017-12-07 14:54:05 +0000446 b.MustGetCipdPackageFromAsset(ISOLATE_ASSET_MAPPING[name].cipdPkg),
Kevin Lubick07072942017-05-11 13:35:23 -0400447 },
448 Dimensions: linuxGceDimensions(),
Eric Boren9d78afd2017-12-07 14:54:05 +0000449 Isolate: relpath(ISOLATE_ASSET_MAPPING[name].isolateFile),
Kevin Lubick07072942017-05-11 13:35:23 -0400450 Priority: 0.7,
451 })
452 return name
453}
454
Kevin Lubick90189522017-05-15 08:30:27 -0400455// getIsolatedCIPDDeps returns the slice of Isolate_* tasks a given task needs.
456// This allows us to save time on I/O bound bots, like the RPIs.
457func getIsolatedCIPDDeps(parts map[string]string) []string {
458 deps := []string{}
Kevin Lubick07072942017-05-11 13:35:23 -0400459 // Only do this on the RPIs for now. Other, faster machines shouldn't see much
460 // benefit and we don't need the extra complexity, for now
Kevin Lubick90189522017-05-15 08:30:27 -0400461 rpiOS := []string{"Android", "ChromeOS", "iOS"}
462
463 if o := parts["os"]; strings.Contains(o, "Chromecast") {
464 // Chromecasts don't have enough disk space to fit all of the content,
465 // so we do a subset of the skps.
466 deps = append(deps, ISOLATE_SKP_NAME)
467 } else if e := parts["extra_config"]; strings.Contains(e, "Skpbench") {
468 // Skpbench only needs skps
469 deps = append(deps, ISOLATE_SKP_NAME)
470 } else if util.In(o, rpiOS) {
471 deps = append(deps, ISOLATE_SKP_NAME)
472 deps = append(deps, ISOLATE_SVG_NAME)
473 deps = append(deps, ISOLATE_SKIMAGE_NAME)
474 }
475
476 return deps
Kevin Lubick07072942017-05-11 13:35:23 -0400477}
478
borenetdb182c72016-09-30 12:53:12 -0700479// compile generates a compile task. Returns the name of the last task in the
480// generated chain of tasks, which the Job should add as a dependency.
boreneted20a702016-10-20 11:04:31 -0700481func compile(b *specs.TasksCfgBuilder, name string, parts map[string]string) string {
borenetdb182c72016-09-30 12:53:12 -0700482 // Collect the necessary CIPD packages.
483 pkgs := []*specs.CipdPackage{}
Eric Boren9d78afd2017-12-07 14:54:05 +0000484 deps := []string{}
borenetdb182c72016-09-30 12:53:12 -0700485
486 // Android bots require a toolchain.
487 if strings.Contains(name, "Android") {
borenetdb182c72016-09-30 12:53:12 -0700488 if strings.Contains(name, "Mac") {
boreneted20a702016-10-20 11:04:31 -0700489 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("android_ndk_darwin"))
Mike Klein86c2c0f2016-11-02 13:13:16 -0400490 } else if strings.Contains(name, "Win") {
Mike Kleine9215f02016-11-02 15:44:26 -0400491 pkg := b.MustGetCipdPackageFromAsset("android_ndk_windows")
492 pkg.Path = "n"
493 pkgs = append(pkgs, pkg)
borenetdb182c72016-09-30 12:53:12 -0700494 } else {
Kevin Lubick814b1492017-11-29 14:45:14 -0500495 deps = append(deps, isolateCIPDAsset(b, ISOLATE_NDK_LINUX_NAME))
borenetdb182c72016-09-30 12:53:12 -0700496 }
Kevin Lubickdcd2a902017-03-08 14:01:01 -0500497 } else if strings.Contains(name, "Chromecast") {
498 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("cast_toolchain"))
Kevin Lubickffce0792017-05-24 15:30:35 -0400499 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("chromebook_arm_gles"))
Kevin Lubick261ea192017-04-05 07:32:45 -0400500 } else if strings.Contains(name, "Chromebook") {
501 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("clang_linux"))
Kevin Lubickb718fbb2017-11-02 09:34:08 -0400502 if parts["target_arch"] == "x86_64" {
503 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("chromebook_x86_64_gles"))
504 } else if parts["target_arch"] == "arm" {
505 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("armhf_sysroot"))
506 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("chromebook_arm_gles"))
507 }
Eric Borenbb198fb2017-06-28 11:45:54 -0400508 } else if strings.Contains(name, "Debian") {
Kevin Lubick9c7dcac2017-01-18 09:24:56 -0500509 if strings.Contains(name, "Clang") {
510 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("clang_linux"))
511 }
512 if strings.Contains(name, "Vulkan") {
513 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("linux_vulkan_sdk"))
514 }
Kevin Lubickebf648e2017-09-21 13:45:16 -0400515 if strings.Contains(name, "EMCC") {
516 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("emscripten_sdk"))
517 }
Mike Klein27dcee12016-11-09 16:31:42 -0500518 } else if strings.Contains(name, "Win") {
Kevin Lubick814b1492017-11-29 14:45:14 -0500519 deps = append(deps, isolateCIPDAsset(b, ISOLATE_WIN_TOOLCHAIN_NAME))
Mike Klein8e3c42b2017-07-31 14:57:20 -0400520 if strings.Contains(name, "Clang") {
521 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("clang_win"))
522 }
borenetdb182c72016-09-30 12:53:12 -0700523 if strings.Contains(name, "Vulkan") {
Kevin Lubick814b1492017-11-29 14:45:14 -0500524 deps = append(deps, isolateCIPDAsset(b, ISOLATE_WIN_VULKAN_SDK_NAME))
borenetdb182c72016-09-30 12:53:12 -0700525 }
526 }
527
Stephan Altmueller5f3b9402017-03-20 13:38:45 -0400528 dimensions := swarmDimensions(parts)
Stephan Altmueller5f3b9402017-03-20 13:38:45 -0400529
borenetdb182c72016-09-30 12:53:12 -0700530 // Add the task.
boreneted20a702016-10-20 11:04:31 -0700531 b.MustAddTask(name, &specs.TaskSpec{
borenetdb182c72016-09-30 12:53:12 -0700532 CipdPackages: pkgs,
Eric Boren9d78afd2017-12-07 14:54:05 +0000533 Dimensions: dimensions,
534 Dependencies: deps,
535 ExtraArgs: []string{
536 "--workdir", "../../..", "compile",
skia.buildbots2478c732016-11-04 14:37:26 -0400537 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
borenetdb182c72016-09-30 12:53:12 -0700538 fmt.Sprintf("buildername=%s", name),
borenetdb182c72016-09-30 12:53:12 -0700539 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
540 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
Eric Boren09419502017-04-21 09:37:37 -0400541 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
borenet98b2e7a2016-10-13 06:23:45 -0700542 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
skia.buildbots2478c732016-11-04 14:37:26 -0400543 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
544 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
borenetdb182c72016-09-30 12:53:12 -0700545 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000546 Isolate: relpath("compile_skia.isolate"),
547 Priority: 0.8,
boreneted20a702016-10-20 11:04:31 -0700548 })
Eric Boren8615fe52016-12-12 14:30:12 -0500549 // All compile tasks are runnable as their own Job. Assert that the Job
550 // is listed in JOBS.
551 if !util.In(name, JOBS) {
552 glog.Fatalf("Job %q is missing from the JOBS list!", name)
553 }
borenetdb182c72016-09-30 12:53:12 -0700554 return name
555}
556
557// recreateSKPs generates a RecreateSKPs task. Returns the name of the last
558// task in the generated chain of tasks, which the Job should add as a
559// dependency.
Eric Boren9d78afd2017-12-07 14:54:05 +0000560func recreateSKPs(b *specs.TasksCfgBuilder, name string) string {
Eric Boren4b254b92016-11-08 12:55:32 -0500561 b.MustAddTask(name, &specs.TaskSpec{
Eric Boren9d78afd2017-12-07 14:54:05 +0000562 CipdPackages: []*specs.CipdPackage{b.MustGetCipdPackageFromAsset("go")},
563 Dimensions: linuxGceDimensions(),
564 ExecutionTimeout: 4 * time.Hour,
565 ExtraArgs: []string{
566 "--workdir", "../../..", "recreate_skps",
Eric Boren4b254b92016-11-08 12:55:32 -0500567 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
568 fmt.Sprintf("buildername=%s", name),
Eric Boren4b254b92016-11-08 12:55:32 -0500569 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
570 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
Eric Boren09419502017-04-21 09:37:37 -0400571 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
Eric Boren4b254b92016-11-08 12:55:32 -0500572 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
573 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
574 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
575 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000576 IoTimeout: 40 * time.Minute,
577 Isolate: relpath("compile_skia.isolate"),
578 Priority: 0.8,
Eric Boren4b254b92016-11-08 12:55:32 -0500579 })
borenetdb182c72016-09-30 12:53:12 -0700580 return name
581}
582
Ravi Mistry01b48e72017-05-17 14:28:06 -0400583// updateMetaConfig generates a UpdateMetaConfig task. Returns the name of the
584// last task in the generated chain of tasks, which the Job should add as a
585// dependency.
Eric Boren9d78afd2017-12-07 14:54:05 +0000586func updateMetaConfig(b *specs.TasksCfgBuilder, name string) string {
Ravi Mistry01b48e72017-05-17 14:28:06 -0400587 b.MustAddTask(name, &specs.TaskSpec{
Stephan Altmuellerddad85b2017-05-19 13:08:19 -0400588 CipdPackages: []*specs.CipdPackage{},
Eric Boren9d78afd2017-12-07 14:54:05 +0000589 Dimensions: linuxGceDimensions(),
590 ExtraArgs: []string{
591 "--workdir", "../../..", "update_meta_config",
Ravi Mistry01b48e72017-05-17 14:28:06 -0400592 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
593 fmt.Sprintf("buildername=%s", name),
594 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
595 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
596 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
597 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
598 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
599 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
600 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000601 Isolate: relpath("meta_config.isolate"),
602 Priority: 0.8,
Ravi Mistry01b48e72017-05-17 14:28:06 -0400603 })
604 return name
605}
606
borenetdb182c72016-09-30 12:53:12 -0700607// ctSKPs generates a CT SKPs task. Returns the name of the last task in the
608// generated chain of tasks, which the Job should add as a dependency.
Eric Boren9d78afd2017-12-07 14:54:05 +0000609func ctSKPs(b *specs.TasksCfgBuilder, name string) string {
Eric Boren4b254b92016-11-08 12:55:32 -0500610 b.MustAddTask(name, &specs.TaskSpec{
Ben Wagner21c3fb92017-08-04 14:13:27 -0400611 CipdPackages: []*specs.CipdPackage{},
Eric Boren9d78afd2017-12-07 14:54:05 +0000612 Dimensions: []string{
613 "pool:SkiaCT",
614 fmt.Sprintf("os:%s", DEFAULT_OS_LINUX_GCE),
615 },
616 ExecutionTimeout: 24 * time.Hour,
617 ExtraArgs: []string{
618 "--workdir", "../../..", "ct_skps",
Eric Boren4b254b92016-11-08 12:55:32 -0500619 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
620 fmt.Sprintf("buildername=%s", name),
Eric Boren4b254b92016-11-08 12:55:32 -0500621 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
622 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
Eric Boren09419502017-04-21 09:37:37 -0400623 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
Eric Boren4b254b92016-11-08 12:55:32 -0500624 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
625 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
626 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
627 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000628 IoTimeout: time.Hour,
629 Isolate: relpath("ct_skps_skia.isolate"),
630 Priority: 0.8,
Eric Boren4b254b92016-11-08 12:55:32 -0500631 })
borenetdb182c72016-09-30 12:53:12 -0700632 return name
633}
634
Eric Borenf7928b42017-07-28 07:35:28 -0400635// checkGeneratedFiles verifies that no generated SKSL files have been edited
636// by hand.
Eric Boren9d78afd2017-12-07 14:54:05 +0000637func checkGeneratedFiles(b *specs.TasksCfgBuilder, name string) string {
Eric Borenf7928b42017-07-28 07:35:28 -0400638 b.MustAddTask(name, &specs.TaskSpec{
639 CipdPackages: []*specs.CipdPackage{},
Eric Boren9d78afd2017-12-07 14:54:05 +0000640 Dimensions: linuxGceDimensions(),
641 ExtraArgs: []string{
642 "--workdir", "../../..", "check_generated_files",
Eric Borenf7928b42017-07-28 07:35:28 -0400643 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
644 fmt.Sprintf("buildername=%s", name),
645 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
646 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
647 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
648 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
649 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
650 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
651 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000652 Isolate: relpath("compile_skia.isolate"),
653 Priority: 0.8,
Eric Borenf7928b42017-07-28 07:35:28 -0400654 })
655 return name
656}
657
borenetdb182c72016-09-30 12:53:12 -0700658// housekeeper generates a Housekeeper task. Returns the name of the last task
659// in the generated chain of tasks, which the Job should add as a dependency.
Eric Boren9d78afd2017-12-07 14:54:05 +0000660func housekeeper(b *specs.TasksCfgBuilder, name, compileTaskName string) string {
Eric Boren4b254b92016-11-08 12:55:32 -0500661 b.MustAddTask(name, &specs.TaskSpec{
Eric Boren22f5ef72016-12-02 11:01:33 -0500662 CipdPackages: []*specs.CipdPackage{b.MustGetCipdPackageFromAsset("go")},
Eric Boren9d78afd2017-12-07 14:54:05 +0000663 Dependencies: []string{compileTaskName},
664 Dimensions: linuxGceDimensions(),
665 ExtraArgs: []string{
666 "--workdir", "../../..", "housekeeper",
Eric Boren4b254b92016-11-08 12:55:32 -0500667 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
668 fmt.Sprintf("buildername=%s", name),
Eric Boren4b254b92016-11-08 12:55:32 -0500669 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
670 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
Eric Boren09419502017-04-21 09:37:37 -0400671 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
Eric Boren4b254b92016-11-08 12:55:32 -0500672 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
673 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
674 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
675 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000676 Isolate: relpath("housekeeper_skia.isolate"),
677 Priority: 0.8,
Eric Boren4b254b92016-11-08 12:55:32 -0500678 })
borenetdb182c72016-09-30 12:53:12 -0700679 return name
680}
681
borenet2dbbfa52016-10-14 06:32:09 -0700682// infra generates an infra_tests task. Returns the name of the last task in the
683// generated chain of tasks, which the Job should add as a dependency.
Eric Boren9d78afd2017-12-07 14:54:05 +0000684func infra(b *specs.TasksCfgBuilder, name string) string {
boreneted20a702016-10-20 11:04:31 -0700685 b.MustAddTask(name, &specs.TaskSpec{
Eric Boren9d78afd2017-12-07 14:54:05 +0000686 CipdPackages: []*specs.CipdPackage{b.MustGetCipdPackageFromAsset("go")},
687 Dimensions: linuxGceDimensions(),
688 ExtraArgs: []string{
689 "--workdir", "../../..", "infra",
skia.buildbots2478c732016-11-04 14:37:26 -0400690 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
borenet2dbbfa52016-10-14 06:32:09 -0700691 fmt.Sprintf("buildername=%s", name),
borenet2dbbfa52016-10-14 06:32:09 -0700692 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
693 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
Eric Boren09419502017-04-21 09:37:37 -0400694 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
borenet2dbbfa52016-10-14 06:32:09 -0700695 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
skia.buildbots2478c732016-11-04 14:37:26 -0400696 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
697 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
borenet2dbbfa52016-10-14 06:32:09 -0700698 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000699 Isolate: relpath("infra_skia.isolate"),
700 Priority: 0.8,
boreneted20a702016-10-20 11:04:31 -0700701 })
borenet2dbbfa52016-10-14 06:32:09 -0700702 return name
703}
704
Yuqian Lic81aaaa2017-10-16 12:24:43 -0400705// calmbench generates a calmbench task. Returns the name of the last task in the
706// generated chain of tasks, which the Job should add as a dependency.
707func calmbench(b *specs.TasksCfgBuilder, name string, parts map[string]string) string {
708 s := &specs.TaskSpec{
709 CipdPackages: []*specs.CipdPackage{b.MustGetCipdPackageFromAsset("clang_linux")},
Eric Boren9d78afd2017-12-07 14:54:05 +0000710 Dimensions: swarmDimensions(parts),
711 ExtraArgs: []string{
712 "--workdir", "../../..", "calmbench",
Yuqian Lic81aaaa2017-10-16 12:24:43 -0400713 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
714 fmt.Sprintf("buildername=%s", name),
715 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
716 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
717 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
718 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
719 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
720 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
721 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000722 Isolate: relpath("infra_skia.isolate"),
723 Priority: 0.8,
Yuqian Lic81aaaa2017-10-16 12:24:43 -0400724 }
725
726 s.Dependencies = append(s.Dependencies, ISOLATE_SKP_NAME, ISOLATE_SVG_NAME)
727
728 b.MustAddTask(name, s)
729
Yuqian Li2ebf3d12017-10-24 09:43:21 -0400730 // Upload results if necessary.
731 if strings.Contains(name, "Release") && doUpload(name) {
732 uploadName := fmt.Sprintf("%s%s%s", PREFIX_UPLOAD, jobNameSchema.Sep, name)
733 b.MustAddTask(uploadName, &specs.TaskSpec{
Eric Boren9d78afd2017-12-07 14:54:05 +0000734 Dependencies: []string{name},
735 Dimensions: linuxGceDimensions(),
736 ExtraArgs: []string{
737 "--workdir", "../../..", "upload_calmbench_results",
Yuqian Li2ebf3d12017-10-24 09:43:21 -0400738 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
739 fmt.Sprintf("buildername=%s", name),
740 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
741 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
742 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
743 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
744 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
745 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
746 fmt.Sprintf("gs_bucket=%s", CONFIG.GsBucketCalm),
747 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000748 // We're using the same isolate as upload_nano_results
749 Isolate: relpath("upload_nano_results.isolate"),
750 Priority: 0.8,
Yuqian Li2ebf3d12017-10-24 09:43:21 -0400751 })
752 return uploadName
753 }
754
Yuqian Lic81aaaa2017-10-16 12:24:43 -0400755 return name
756}
757
borenetdb182c72016-09-30 12:53:12 -0700758// doUpload indicates whether the given Job should upload its results.
759func doUpload(name string) bool {
Eric Boren27225492017-02-01 15:56:55 -0500760 for _, s := range CONFIG.NoUpload {
761 m, err := regexp.MatchString(s, name)
762 if err != nil {
763 glog.Fatal(err)
764 }
765 if m {
borenetdb182c72016-09-30 12:53:12 -0700766 return false
767 }
768 }
769 return true
770}
771
772// test generates a Test task. Returns the name of the last task in the
773// generated chain of tasks, which the Job should add as a dependency.
boreneted20a702016-10-20 11:04:31 -0700774func test(b *specs.TasksCfgBuilder, name string, parts map[string]string, compileTaskName string, pkgs []*specs.CipdPackage) string {
Eric Boren4b254b92016-11-08 12:55:32 -0500775 s := &specs.TaskSpec{
Eric Boren9d78afd2017-12-07 14:54:05 +0000776 CipdPackages: pkgs,
777 Dependencies: []string{compileTaskName},
778 Dimensions: swarmDimensions(parts),
779 ExecutionTimeout: 4 * time.Hour,
780 Expiration: 20 * time.Hour,
781 ExtraArgs: []string{
782 "--workdir", "../../..", "test",
skia.buildbots2478c732016-11-04 14:37:26 -0400783 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
Eric Boren9a9e3872017-11-29 12:33:22 -0500784 fmt.Sprintf("buildbucket_build_id=%s", specs.PLACEHOLDER_BUILDBUCKET_BUILD_ID),
borenetdb182c72016-09-30 12:53:12 -0700785 fmt.Sprintf("buildername=%s", name),
borenetdb182c72016-09-30 12:53:12 -0700786 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
787 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
Eric Boren09419502017-04-21 09:37:37 -0400788 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
borenet98b2e7a2016-10-13 06:23:45 -0700789 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
skia.buildbots2478c732016-11-04 14:37:26 -0400790 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
791 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
borenetdb182c72016-09-30 12:53:12 -0700792 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000793 IoTimeout: 40 * time.Minute,
794 Isolate: relpath("test_skia.isolate"),
795 MaxAttempts: 1,
796 Priority: 0.8,
797 }
798 if useBundledRecipes(parts) {
799 s.Dependencies = append(s.Dependencies, BUNDLE_RECIPES_NAME)
800 if strings.Contains(parts["os"], "Win") {
801 s.Isolate = relpath("test_skia_bundled_win.isolate")
802 } else {
803 s.Isolate = relpath("test_skia_bundled_unix.isolate")
804 }
Eric Boren8b3f9e62017-04-04 09:06:16 -0400805 }
Kevin Lubick90189522017-05-15 08:30:27 -0400806 if deps := getIsolatedCIPDDeps(parts); len(deps) > 0 {
807 s.Dependencies = append(s.Dependencies, deps...)
Kevin Lubick07072942017-05-11 13:35:23 -0400808 }
Eric Boren4b254b92016-11-08 12:55:32 -0500809 if strings.Contains(parts["extra_config"], "Valgrind") {
810 s.ExecutionTimeout = 9 * time.Hour
811 s.Expiration = 48 * time.Hour
812 s.IoTimeout = time.Hour
Eric Borend696df72017-05-31 15:09:10 -0400813 s.CipdPackages = append(s.CipdPackages, b.MustGetCipdPackageFromAsset("valgrind"))
Kevin Lubickea613822017-12-04 10:20:23 -0500814 s.Dimensions = append(s.Dimensions, "valgrind:1")
Eric Boren4b254b92016-11-08 12:55:32 -0500815 } else if strings.Contains(parts["extra_config"], "MSAN") {
816 s.ExecutionTimeout = 9 * time.Hour
Ben Wagnera6b2ba22017-06-08 10:34:17 -0400817 } else if parts["arch"] == "x86" && parts["configuration"] == "Debug" {
818 // skia:6737
819 s.ExecutionTimeout = 6 * time.Hour
Eric Boren4b254b92016-11-08 12:55:32 -0500820 }
Eric Borenfd4d60e2017-09-15 10:35:44 -0400821 iid := internalHardwareLabel(parts)
Eric Boren053d7a42017-09-15 08:35:31 -0400822 if iid != nil {
Eric Boren4dc4aaf2017-09-15 14:09:07 -0400823 s.ExtraArgs = append(s.ExtraArgs, fmt.Sprintf("internal_hardware_label=%d", *iid))
Eric Boren053d7a42017-09-15 08:35:31 -0400824 }
Eric Boren4b254b92016-11-08 12:55:32 -0500825 b.MustAddTask(name, s)
826
Kevin Lubickc795a4c2017-10-09 15:26:19 -0400827 // Upload results if necessary. TODO(kjlubick): If we do coverage analysis at the same
828 // time as normal tests (which would be nice), cfg.json needs to have Coverage removed.
borenetdb182c72016-09-30 12:53:12 -0700829 if doUpload(name) {
830 uploadName := fmt.Sprintf("%s%s%s", PREFIX_UPLOAD, jobNameSchema.Sep, name)
boreneted20a702016-10-20 11:04:31 -0700831 b.MustAddTask(uploadName, &specs.TaskSpec{
Eric Boren9d78afd2017-12-07 14:54:05 +0000832 Dependencies: []string{name},
833 Dimensions: linuxGceDimensions(),
834 ExtraArgs: []string{
835 "--workdir", "../../..", "upload_dm_results",
skia.buildbots2478c732016-11-04 14:37:26 -0400836 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
borenetdb182c72016-09-30 12:53:12 -0700837 fmt.Sprintf("buildername=%s", name),
borenetdb182c72016-09-30 12:53:12 -0700838 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
839 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
Eric Boren09419502017-04-21 09:37:37 -0400840 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
borenet98b2e7a2016-10-13 06:23:45 -0700841 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
skia.buildbots2478c732016-11-04 14:37:26 -0400842 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
843 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
Eric Boren965861b2017-02-06 15:38:41 -0500844 fmt.Sprintf("gs_bucket=%s", CONFIG.GsBucketGm),
borenetdb182c72016-09-30 12:53:12 -0700845 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000846 Isolate: relpath("upload_dm_results.isolate"),
847 Priority: 0.8,
boreneted20a702016-10-20 11:04:31 -0700848 })
borenetdb182c72016-09-30 12:53:12 -0700849 return uploadName
Kevin Lubick32f318b2017-10-17 13:40:52 -0400850 }
851
852 return name
853}
854
855func coverage(b *specs.TasksCfgBuilder, name string, parts map[string]string, compileTaskName string, pkgs []*specs.CipdPackage) string {
856 shards := 1
857 deps := []string{}
858
859 tf := parts["test_filter"]
860 if strings.Contains(tf, "Shard") {
861 // Expected Shard_NN
862 shardstr := strings.Split(tf, "_")[1]
863 var err error
864 shards, err = strconv.Atoi(shardstr)
865 if err != nil {
866 glog.Fatalf("Expected int for number of shards %q in %s: %s", shardstr, name, err)
867 }
868 }
869 for i := 0; i < shards; i++ {
870 n := strings.Replace(name, tf, fmt.Sprintf("shard_%02d_%02d", i, shards), 1)
871 s := &specs.TaskSpec{
Eric Boren9d78afd2017-12-07 14:54:05 +0000872 CipdPackages: pkgs,
873 Dependencies: []string{compileTaskName},
874 Dimensions: swarmDimensions(parts),
875 ExecutionTimeout: 4 * time.Hour,
876 Expiration: 20 * time.Hour,
877 ExtraArgs: []string{
878 "--workdir", "../../..", "test",
Kevin Lubickc795a4c2017-10-09 15:26:19 -0400879 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
Kevin Lubick32f318b2017-10-17 13:40:52 -0400880 fmt.Sprintf("buildername=%s", n),
Kevin Lubickc795a4c2017-10-09 15:26:19 -0400881 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
882 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
883 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
884 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
885 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
886 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
Kevin Lubickc795a4c2017-10-09 15:26:19 -0400887 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000888 IoTimeout: 40 * time.Minute,
889 Isolate: relpath("test_skia.isolate"),
890 MaxAttempts: 1,
891 Priority: 0.8,
892 }
893 if useBundledRecipes(parts) {
894 s.Dependencies = append(s.Dependencies, BUNDLE_RECIPES_NAME)
895 if strings.Contains(parts["os"], "Win") {
896 s.Isolate = relpath("test_skia_bundled_win.isolate")
897 } else {
898 s.Isolate = relpath("test_skia_bundled_unix.isolate")
899 }
Kevin Lubick32f318b2017-10-17 13:40:52 -0400900 }
901 if deps := getIsolatedCIPDDeps(parts); len(deps) > 0 {
902 s.Dependencies = append(s.Dependencies, deps...)
903 }
904 b.MustAddTask(n, s)
905 deps = append(deps, n)
borenetdb182c72016-09-30 12:53:12 -0700906 }
Kevin Lubickc795a4c2017-10-09 15:26:19 -0400907
Kevin Lubick32f318b2017-10-17 13:40:52 -0400908 uploadName := fmt.Sprintf("%s%s%s", "Upload", jobNameSchema.Sep, name)
909 // We need clang_linux to get access to the llvm-profdata and llvm-cov binaries
910 // which are used to deal with the raw coverage data output by the Test step.
911 pkgs = append([]*specs.CipdPackage{}, b.MustGetCipdPackageFromAsset("clang_linux"))
912 deps = append(deps, compileTaskName)
913
914 b.MustAddTask(uploadName, &specs.TaskSpec{
915 // A dependency on compileTaskName makes the TaskScheduler link the
916 // isolated output of the compile step to the input of the upload step,
917 // which gives us access to the instrumented binary. The binary is
918 // needed to figure out symbol names and line numbers.
919 Dependencies: deps,
920 Dimensions: linuxGceDimensions(),
921 CipdPackages: pkgs,
Eric Boren9d78afd2017-12-07 14:54:05 +0000922 ExtraArgs: []string{
923 "--workdir", "../../..", "upload_coverage_results",
Kevin Lubick32f318b2017-10-17 13:40:52 -0400924 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
925 fmt.Sprintf("buildername=%s", name),
926 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
927 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
928 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
929 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
930 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
931 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
932 fmt.Sprintf("gs_bucket=%s", CONFIG.GsBucketCoverage),
933 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000934 Isolate: relpath("upload_coverage_results.isolate"),
Kevin Lubick32f318b2017-10-17 13:40:52 -0400935 Priority: 0.8,
936 })
937 return uploadName
borenetdb182c72016-09-30 12:53:12 -0700938}
939
940// perf generates a Perf task. Returns the name of the last task in the
941// generated chain of tasks, which the Job should add as a dependency.
boreneted20a702016-10-20 11:04:31 -0700942func perf(b *specs.TasksCfgBuilder, name string, parts map[string]string, compileTaskName string, pkgs []*specs.CipdPackage) string {
Eric Boren768f52f2017-04-10 08:14:33 -0400943 recipe := "perf"
Eric Boren9d78afd2017-12-07 14:54:05 +0000944 isolate := relpath("perf_skia.isolate")
Kevin Lubickb03b5ac2016-11-14 13:42:27 -0500945 if strings.Contains(parts["extra_config"], "Skpbench") {
Eric Boren768f52f2017-04-10 08:14:33 -0400946 recipe = "skpbench"
Eric Boren9d78afd2017-12-07 14:54:05 +0000947 isolate = relpath("skpbench_skia.isolate")
948 if useBundledRecipes(parts) {
949 if strings.Contains(parts["os"], "Win") {
950 isolate = relpath("skpbench_skia_bundled_win.isolate")
951 } else {
952 isolate = relpath("skpbench_skia_bundled_unix.isolate")
953 }
954 }
955 } else if useBundledRecipes(parts) {
956 if strings.Contains(parts["os"], "Win") {
957 isolate = relpath("perf_skia_bundled_win.isolate")
958 } else {
959 isolate = relpath("perf_skia_bundled_unix.isolate")
960 }
Kevin Lubickb03b5ac2016-11-14 13:42:27 -0500961 }
Eric Boren4b254b92016-11-08 12:55:32 -0500962 s := &specs.TaskSpec{
Eric Boren9d78afd2017-12-07 14:54:05 +0000963 CipdPackages: pkgs,
964 Dependencies: []string{compileTaskName},
965 Dimensions: swarmDimensions(parts),
966 ExecutionTimeout: 4 * time.Hour,
967 Expiration: 20 * time.Hour,
968 ExtraArgs: []string{
969 "--workdir", "../../..", recipe,
skia.buildbots2478c732016-11-04 14:37:26 -0400970 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
borenetdb182c72016-09-30 12:53:12 -0700971 fmt.Sprintf("buildername=%s", name),
borenetdb182c72016-09-30 12:53:12 -0700972 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
973 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
Eric Boren09419502017-04-21 09:37:37 -0400974 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
borenet98b2e7a2016-10-13 06:23:45 -0700975 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
skia.buildbots2478c732016-11-04 14:37:26 -0400976 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
977 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
borenetdb182c72016-09-30 12:53:12 -0700978 },
Eric Boren9d78afd2017-12-07 14:54:05 +0000979 IoTimeout: 40 * time.Minute,
980 Isolate: isolate,
981 MaxAttempts: 1,
982 Priority: 0.8,
983 }
984 if useBundledRecipes(parts) {
985 s.Dependencies = append(s.Dependencies, BUNDLE_RECIPES_NAME)
Eric Boren8b3f9e62017-04-04 09:06:16 -0400986 }
Kevin Lubick90189522017-05-15 08:30:27 -0400987 if deps := getIsolatedCIPDDeps(parts); len(deps) > 0 {
988 s.Dependencies = append(s.Dependencies, deps...)
989 }
990
Eric Boren4b254b92016-11-08 12:55:32 -0500991 if strings.Contains(parts["extra_config"], "Valgrind") {
992 s.ExecutionTimeout = 9 * time.Hour
993 s.Expiration = 48 * time.Hour
994 s.IoTimeout = time.Hour
Eric Borenc5a073d2017-06-01 07:13:33 -0400995 s.CipdPackages = append(s.CipdPackages, b.MustGetCipdPackageFromAsset("valgrind"))
Kevin Lubickea613822017-12-04 10:20:23 -0500996 s.Dimensions = append(s.Dimensions, "valgrind:1")
Eric Boren4b254b92016-11-08 12:55:32 -0500997 } else if strings.Contains(parts["extra_config"], "MSAN") {
998 s.ExecutionTimeout = 9 * time.Hour
Ben Wagnera6b2ba22017-06-08 10:34:17 -0400999 } else if parts["arch"] == "x86" && parts["configuration"] == "Debug" {
1000 // skia:6737
1001 s.ExecutionTimeout = 6 * time.Hour
Eric Boren4b254b92016-11-08 12:55:32 -05001002 }
Eric Borenfd4d60e2017-09-15 10:35:44 -04001003 iid := internalHardwareLabel(parts)
Eric Boren053d7a42017-09-15 08:35:31 -04001004 if iid != nil {
Eric Boren4dc4aaf2017-09-15 14:09:07 -04001005 s.ExtraArgs = append(s.ExtraArgs, fmt.Sprintf("internal_hardware_label=%d", *iid))
Eric Boren053d7a42017-09-15 08:35:31 -04001006 }
Eric Boren4b254b92016-11-08 12:55:32 -05001007 b.MustAddTask(name, s)
1008
borenetdb182c72016-09-30 12:53:12 -07001009 // Upload results if necessary.
1010 if strings.Contains(name, "Release") && doUpload(name) {
1011 uploadName := fmt.Sprintf("%s%s%s", PREFIX_UPLOAD, jobNameSchema.Sep, name)
boreneted20a702016-10-20 11:04:31 -07001012 b.MustAddTask(uploadName, &specs.TaskSpec{
Eric Boren9d78afd2017-12-07 14:54:05 +00001013 Dependencies: []string{name},
1014 Dimensions: linuxGceDimensions(),
1015 ExtraArgs: []string{
1016 "--workdir", "../../..", "upload_nano_results",
skia.buildbots2478c732016-11-04 14:37:26 -04001017 fmt.Sprintf("repository=%s", specs.PLACEHOLDER_REPO),
borenetdb182c72016-09-30 12:53:12 -07001018 fmt.Sprintf("buildername=%s", name),
borenetdb182c72016-09-30 12:53:12 -07001019 fmt.Sprintf("swarm_out_dir=%s", specs.PLACEHOLDER_ISOLATED_OUTDIR),
1020 fmt.Sprintf("revision=%s", specs.PLACEHOLDER_REVISION),
Eric Boren09419502017-04-21 09:37:37 -04001021 fmt.Sprintf("patch_repo=%s", specs.PLACEHOLDER_PATCH_REPO),
borenet98b2e7a2016-10-13 06:23:45 -07001022 fmt.Sprintf("patch_storage=%s", specs.PLACEHOLDER_PATCH_STORAGE),
skia.buildbots2478c732016-11-04 14:37:26 -04001023 fmt.Sprintf("patch_issue=%s", specs.PLACEHOLDER_ISSUE),
1024 fmt.Sprintf("patch_set=%s", specs.PLACEHOLDER_PATCHSET),
Eric Boren965861b2017-02-06 15:38:41 -05001025 fmt.Sprintf("gs_bucket=%s", CONFIG.GsBucketNano),
borenetdb182c72016-09-30 12:53:12 -07001026 },
Eric Boren9d78afd2017-12-07 14:54:05 +00001027 Isolate: relpath("upload_nano_results.isolate"),
1028 Priority: 0.8,
boreneted20a702016-10-20 11:04:31 -07001029 })
borenetdb182c72016-09-30 12:53:12 -07001030 return uploadName
1031 }
1032 return name
1033}
1034
1035// process generates tasks and jobs for the given job name.
boreneted20a702016-10-20 11:04:31 -07001036func process(b *specs.TasksCfgBuilder, name string) {
borenetdb182c72016-09-30 12:53:12 -07001037 deps := []string{}
1038
Eric Boren8b3f9e62017-04-04 09:06:16 -04001039 // Bundle Recipes.
1040 if name == BUNDLE_RECIPES_NAME {
1041 deps = append(deps, bundleRecipes(b))
1042 }
1043
Kevin Lubick07072942017-05-11 13:35:23 -04001044 // Isolate CIPD assets.
Kevin Lubick07072942017-05-11 13:35:23 -04001045 if _, ok := ISOLATE_ASSET_MAPPING[name]; ok {
1046 deps = append(deps, isolateCIPDAsset(b, name))
1047 }
1048
borenetdb182c72016-09-30 12:53:12 -07001049 parts, err := jobNameSchema.ParseJobName(name)
1050 if err != nil {
1051 glog.Fatal(err)
1052 }
1053
1054 // RecreateSKPs.
1055 if strings.Contains(name, "RecreateSKPs") {
Eric Boren9d78afd2017-12-07 14:54:05 +00001056 deps = append(deps, recreateSKPs(b, name))
borenetdb182c72016-09-30 12:53:12 -07001057 }
1058
Ravi Mistry01b48e72017-05-17 14:28:06 -04001059 // UpdateMetaConfig bot.
1060 if strings.Contains(name, "UpdateMetaConfig") {
Eric Boren9d78afd2017-12-07 14:54:05 +00001061 deps = append(deps, updateMetaConfig(b, name))
Ravi Mistry01b48e72017-05-17 14:28:06 -04001062 }
1063
borenetdb182c72016-09-30 12:53:12 -07001064 // CT bots.
1065 if strings.Contains(name, "-CT_") {
Eric Boren9d78afd2017-12-07 14:54:05 +00001066 deps = append(deps, ctSKPs(b, name))
borenetdb182c72016-09-30 12:53:12 -07001067 }
1068
borenet2dbbfa52016-10-14 06:32:09 -07001069 // Infra tests.
1070 if name == "Housekeeper-PerCommit-InfraTests" {
Eric Boren9d78afd2017-12-07 14:54:05 +00001071 deps = append(deps, infra(b, name))
borenet2dbbfa52016-10-14 06:32:09 -07001072 }
1073
borenetdb182c72016-09-30 12:53:12 -07001074 // Compile bots.
1075 if parts["role"] == "Build" {
boreneted20a702016-10-20 11:04:31 -07001076 deps = append(deps, compile(b, name, parts))
borenetdb182c72016-09-30 12:53:12 -07001077 }
1078
Yuqian Lic81aaaa2017-10-16 12:24:43 -04001079 // Calmbench bots.
1080 if parts["role"] == "Calmbench" {
Kevin Lubickd2b8af12017-10-30 10:05:52 -04001081 deps = append(deps, calmbench(b, name, parts))
Yuqian Lic81aaaa2017-10-16 12:24:43 -04001082 }
1083
Eric Borenf5a90e82016-11-15 15:18:20 -05001084 // Most remaining bots need a compile task.
borenetdb182c72016-09-30 12:53:12 -07001085 compileTaskName := deriveCompileTaskName(name, parts)
borenet52383432016-10-17 10:17:53 -07001086 compileTaskParts, err := jobNameSchema.ParseJobName(compileTaskName)
1087 if err != nil {
1088 glog.Fatal(err)
1089 }
Eric Boren628e78b2016-11-17 11:33:27 -05001090 // These bots do not need a compile task.
Yuqian Lic81aaaa2017-10-16 12:24:43 -04001091 if parts["role"] != "Build" && parts["role"] != "Calmbench" &&
Eric Borenb8ab7f72017-04-10 11:00:09 -04001092 name != "Housekeeper-PerCommit-BundleRecipes" &&
Eric Borenf5a90e82016-11-15 15:18:20 -05001093 name != "Housekeeper-PerCommit-InfraTests" &&
Eric Borenf7928b42017-07-28 07:35:28 -04001094 name != "Housekeeper-PerCommit-CheckGeneratedFiles" &&
Eric Boren71b762f2016-11-30 14:05:16 -05001095 !strings.Contains(name, "RecreateSKPs") &&
Ravi Mistry01b48e72017-05-17 14:28:06 -04001096 !strings.Contains(name, "UpdateMetaConfig") &&
Ben Wagner50b84682017-06-12 13:03:29 -04001097 !strings.Contains(name, "-CT_") &&
1098 !strings.Contains(name, "Housekeeper-PerCommit-Isolate") {
boreneted20a702016-10-20 11:04:31 -07001099 compile(b, compileTaskName, compileTaskParts)
borenet52383432016-10-17 10:17:53 -07001100 }
borenetdb182c72016-09-30 12:53:12 -07001101
Eric Borenf7928b42017-07-28 07:35:28 -04001102 // Housekeepers.
Eric Boren22f5ef72016-12-02 11:01:33 -05001103 if name == "Housekeeper-PerCommit" {
Eric Boren9d78afd2017-12-07 14:54:05 +00001104 deps = append(deps, housekeeper(b, name, compileTaskName))
borenetdb182c72016-09-30 12:53:12 -07001105 }
Eric Borenf7928b42017-07-28 07:35:28 -04001106 if name == "Housekeeper-PerCommit-CheckGeneratedFiles" {
Eric Boren9d78afd2017-12-07 14:54:05 +00001107 deps = append(deps, checkGeneratedFiles(b, name))
Eric Borenf7928b42017-07-28 07:35:28 -04001108 }
borenetdb182c72016-09-30 12:53:12 -07001109
1110 // Common assets needed by the remaining bots.
Kevin Lubick07072942017-05-11 13:35:23 -04001111
1112 pkgs := []*specs.CipdPackage{}
1113
Kevin Lubick90189522017-05-15 08:30:27 -04001114 if deps := getIsolatedCIPDDeps(parts); len(deps) == 0 {
Kevin Lubick07072942017-05-11 13:35:23 -04001115 pkgs = []*specs.CipdPackage{
1116 b.MustGetCipdPackageFromAsset("skimage"),
1117 b.MustGetCipdPackageFromAsset("skp"),
1118 b.MustGetCipdPackageFromAsset("svg"),
1119 }
borenetdb182c72016-09-30 12:53:12 -07001120 }
Kevin Lubick90189522017-05-15 08:30:27 -04001121
Ben Wagner5655ba42017-10-02 10:48:32 -04001122 if strings.Contains(name, "Ubuntu") || strings.Contains(name, "Debian") {
1123 if strings.Contains(name, "SAN") {
1124 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("clang_linux"))
1125 }
Kevin Lubick35115eb2017-02-17 10:25:34 -05001126 if strings.Contains(name, "Vulkan") {
1127 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("linux_vulkan_sdk"))
1128 }
Ben Wagner5655ba42017-10-02 10:48:32 -04001129 if strings.Contains(name, "Intel") && strings.Contains(name, "GPU") {
1130 if strings.Contains(name, "Release") {
1131 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("linux_vulkan_intel_driver_release"))
1132 } else {
1133 pkgs = append(pkgs, b.MustGetCipdPackageFromAsset("linux_vulkan_intel_driver_debug"))
1134 }
Kevin Lubick0a51b482017-02-06 12:45:29 -05001135 }
1136 }
borenetdb182c72016-09-30 12:53:12 -07001137
1138 // Test bots.
Kevin Lubick32f318b2017-10-17 13:40:52 -04001139
1140 if parts["role"] == "Test" {
1141 if strings.Contains(parts["extra_config"], "Coverage") {
1142 deps = append(deps, coverage(b, name, parts, compileTaskName, pkgs))
1143 } else if !strings.Contains(name, "-CT_") {
1144 deps = append(deps, test(b, name, parts, compileTaskName, pkgs))
1145 }
1146
borenetdb182c72016-09-30 12:53:12 -07001147 }
1148
1149 // Perf bots.
Eric Boren71b762f2016-11-30 14:05:16 -05001150 if parts["role"] == "Perf" && !strings.Contains(name, "-CT_") {
boreneted20a702016-10-20 11:04:31 -07001151 deps = append(deps, perf(b, name, parts, compileTaskName, pkgs))
borenetdb182c72016-09-30 12:53:12 -07001152 }
1153
1154 // Add the Job spec.
Eric Borenf5a90e82016-11-15 15:18:20 -05001155 j := &specs.JobSpec{
borenetdb182c72016-09-30 12:53:12 -07001156 Priority: 0.8,
1157 TaskSpecs: deps,
Eric Borenba937a42017-07-31 10:41:15 -04001158 Trigger: specs.TRIGGER_ANY_BRANCH,
Eric Borenf5a90e82016-11-15 15:18:20 -05001159 }
Eric Borenba937a42017-07-31 10:41:15 -04001160 if strings.Contains(name, "-Nightly-") {
1161 j.Trigger = specs.TRIGGER_NIGHTLY
Ravi Mistryf06dae82017-10-16 10:31:41 -04001162 } else if strings.Contains(name, "-Weekly-") || strings.Contains(name, "CT_DM_1m_SKPs") {
Eric Borenba937a42017-07-31 10:41:15 -04001163 j.Trigger = specs.TRIGGER_WEEKLY
1164 } else if strings.Contains(name, "Flutter") || strings.Contains(name, "PDFium") || strings.Contains(name, "CommandBuffer") {
1165 j.Trigger = specs.TRIGGER_MASTER_ONLY
Eric Boren71b762f2016-11-30 14:05:16 -05001166 }
Eric Boren8615fe52016-12-12 14:30:12 -05001167 b.MustAddJob(name, j)
borenetdb182c72016-09-30 12:53:12 -07001168}
1169
Eric Boren27225492017-02-01 15:56:55 -05001170func loadJson(flag *string, defaultFlag string, val interface{}) {
1171 if *flag == "" {
1172 *flag = defaultFlag
1173 }
1174 b, err := ioutil.ReadFile(*flag)
1175 if err != nil {
1176 glog.Fatal(err)
1177 }
1178 if err := json.Unmarshal(b, val); err != nil {
1179 glog.Fatal(err)
1180 }
1181}
1182
borenetdb182c72016-09-30 12:53:12 -07001183// Regenerate the tasks.json file.
1184func main() {
boreneted20a702016-10-20 11:04:31 -07001185 b := specs.MustNewTasksCfgBuilder()
Eric Boren27225492017-02-01 15:56:55 -05001186 b.SetAssetsDir(*assetsDir)
1187 infraBots := path.Join(b.CheckoutRoot(), "infra", "bots")
1188
1189 // Load the jobs from a JSON file.
1190 loadJson(jobsFile, path.Join(infraBots, "jobs.json"), &JOBS)
1191
Eric Boren27225492017-02-01 15:56:55 -05001192 // Load general config information from a JSON file.
1193 loadJson(cfgFile, path.Join(infraBots, "cfg.json"), &CONFIG)
1194
borenetdb182c72016-09-30 12:53:12 -07001195 // Create the JobNameSchema.
Eric Boren1f8be682017-02-07 09:16:30 -05001196 if *builderNameSchemaFile == "" {
1197 *builderNameSchemaFile = path.Join(b.CheckoutRoot(), "infra", "bots", "recipe_modules", "builder_name_schema", "builder_name_schema.json")
1198 }
1199 schema, err := NewJobNameSchema(*builderNameSchemaFile)
borenetdb182c72016-09-30 12:53:12 -07001200 if err != nil {
1201 glog.Fatal(err)
1202 }
1203 jobNameSchema = schema
1204
borenetdb182c72016-09-30 12:53:12 -07001205 // Create Tasks and Jobs.
boreneted20a702016-10-20 11:04:31 -07001206 for _, name := range JOBS {
1207 process(b, name)
borenetdb182c72016-09-30 12:53:12 -07001208 }
1209
boreneted20a702016-10-20 11:04:31 -07001210 b.MustFinish()
borenetdb182c72016-09-30 12:53:12 -07001211}
1212
1213// TODO(borenet): The below really belongs in its own file, probably next to the
1214// builder_name_schema.json file.
1215
1216// JobNameSchema is a struct used for (de)constructing Job names in a
1217// predictable format.
1218type JobNameSchema struct {
1219 Schema map[string][]string `json:"builder_name_schema"`
1220 Sep string `json:"builder_name_sep"`
1221}
1222
1223// NewJobNameSchema returns a JobNameSchema instance based on the given JSON
1224// file.
1225func NewJobNameSchema(jsonFile string) (*JobNameSchema, error) {
1226 var rv JobNameSchema
1227 f, err := os.Open(jsonFile)
1228 if err != nil {
1229 return nil, err
1230 }
1231 defer util.Close(f)
1232 if err := json.NewDecoder(f).Decode(&rv); err != nil {
1233 return nil, err
1234 }
1235 return &rv, nil
1236}
1237
1238// ParseJobName splits the given Job name into its component parts, according
1239// to the schema.
1240func (s *JobNameSchema) ParseJobName(n string) (map[string]string, error) {
1241 split := strings.Split(n, s.Sep)
1242 if len(split) < 2 {
1243 return nil, fmt.Errorf("Invalid job name: %q", n)
1244 }
1245 role := split[0]
1246 split = split[1:]
1247 keys, ok := s.Schema[role]
1248 if !ok {
1249 return nil, fmt.Errorf("Invalid job name; %q is not a valid role.", role)
1250 }
1251 extraConfig := ""
1252 if len(split) == len(keys)+1 {
1253 extraConfig = split[len(split)-1]
1254 split = split[:len(split)-1]
1255 }
1256 if len(split) != len(keys) {
1257 return nil, fmt.Errorf("Invalid job name; %q has incorrect number of parts.", n)
1258 }
1259 rv := make(map[string]string, len(keys)+2)
1260 rv["role"] = role
1261 if extraConfig != "" {
1262 rv["extra_config"] = extraConfig
1263 }
1264 for i, k := range keys {
1265 rv[k] = split[i]
1266 }
1267 return rv, nil
1268}
1269
1270// MakeJobName assembles the given parts of a Job name, according to the schema.
1271func (s *JobNameSchema) MakeJobName(parts map[string]string) (string, error) {
1272 role, ok := parts["role"]
1273 if !ok {
1274 return "", fmt.Errorf("Invalid job parts; jobs must have a role.")
1275 }
1276 keys, ok := s.Schema[role]
1277 if !ok {
1278 return "", fmt.Errorf("Invalid job parts; unknown role %q", role)
1279 }
1280 rvParts := make([]string, 0, len(parts))
1281 rvParts = append(rvParts, role)
1282 for _, k := range keys {
1283 v, ok := parts[k]
1284 if !ok {
1285 return "", fmt.Errorf("Invalid job parts; missing %q", k)
1286 }
1287 rvParts = append(rvParts, v)
1288 }
1289 if _, ok := parts["extra_config"]; ok {
1290 rvParts = append(rvParts, parts["extra_config"])
1291 }
1292 return strings.Join(rvParts, s.Sep), nil
1293}