1#!/usr/bin/env lucicfg 2# 3# Copyright (C) 2021 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18"""LUCI project configuration for the production instance of LUCI. 19 20After modifying this file execute it ('./main.star') to regenerate the configs. 21""" 22 23lucicfg.check_version("1.30.9", "Please update depot_tools") 24 25luci.builder.defaults.experiments.set({ 26 "luci.recipes.use_python3": 100, 27}) 28 29# Use LUCI Scheduler BBv2 names and add Scheduler realms configs. 30lucicfg.enable_experiment("crbug.com/1182002") 31 32# Tell lucicfg what files it is allowed to touch. 33lucicfg.config( 34 config_dir = "generated", 35 fail_on_warnings = True, 36 lint_checks = ["default"], 37) 38 39# TODO: Switch to project-scoped service account. 40 41luci.project( 42 name = "art", 43 buildbucket = "cr-buildbucket.appspot.com", 44 logdog = "luci-logdog.appspot.com", 45 milo = "luci-milo.appspot.com", 46 notify = "luci-notify.appspot.com", 47 scheduler = "luci-scheduler.appspot.com", 48 swarming = "chromium-swarm.appspot.com", 49 acls = [ 50 # Publicly readable. 51 acl.entry( 52 roles = [ 53 acl.BUILDBUCKET_READER, 54 acl.LOGDOG_READER, 55 acl.PROJECT_CONFIGS_READER, 56 acl.SCHEDULER_READER, 57 ], 58 groups = "all", 59 ), 60 acl.entry( 61 roles = [ 62 acl.BUILDBUCKET_OWNER, 63 acl.SCHEDULER_OWNER, 64 ], 65 groups = "project-art-admins", 66 ), 67 acl.entry( 68 roles = acl.LOGDOG_WRITER, 69 groups = "luci-logdog-chromium-writers", 70 ), 71 ], 72 bindings = [ 73 luci.binding( 74 roles = "role/swarming.poolOwner", 75 groups = "project-art-admins", 76 ), 77 luci.binding( 78 roles = "role/swarming.poolViewer", 79 groups = "all", 80 ), 81 ], 82) 83 84# Per-service tweaks. 85luci.logdog(gs_bucket = "chromium-luci-logdog") 86luci.milo(logo = "https://storage.googleapis.com/chrome-infra-public/logo/art-logo.png") 87 88# Allow admins to use LED and "Debug" button on every builder and bot. 89luci.binding( 90 realm = "@root", 91 roles = "role/swarming.poolUser", 92 groups = "project-art-admins", 93) 94luci.binding( 95 realm = "@root", 96 roles = "role/swarming.taskTriggerer", 97 groups = "project-art-admins", 98) 99 100# Resources shared by all subprojects. 101 102luci.realm(name = "pools/ci") 103luci.bucket(name = "ci") 104 105# Shadow bucket is needed for LED. 106luci.bucket( 107 name = "ci.shadow", 108 shadows = "ci", 109 bindings = [ 110 luci.binding( 111 roles = "role/buildbucket.creator", 112 users = ["[email protected]"], 113 ), 114 luci.binding( 115 roles = "role/buildbucket.triggerer", 116 users = ["[email protected]"], 117 ), 118 ], 119 constraints = luci.bucket_constraints( 120 pools = ["luci.art.ci"], 121 service_accounts = ["[email protected]"], 122 ), 123 dynamic = True, 124) 125 126luci.notifier_template( 127 name = "default", 128 body = io.read_file("luci-notify.template"), 129) 130 131luci.console_view( 132 name = "luci", 133 repo = "https://android.googlesource.com/platform/art", 134 title = "ART LUCI Console", 135 refs = ["refs/heads/master"], 136 include_experimental_builds = True, 137) 138 139luci.notifier( 140 name = "art-team+chromium-buildbot", 141 on_new_status = [ 142 "FAILURE", 143 "INFRA_FAILURE", 144 ], 145 notify_emails = [ 146 "[email protected]", 147 ], 148) 149 150luci.gitiles_poller( 151 name = "art", 152 bucket = "ci", 153 repo = "https://android.googlesource.com/platform/art", 154 refs = ["refs/heads/master"], 155) 156 157luci.gitiles_poller( 158 name = "libcore", 159 bucket = "ci", 160 repo = "https://android.googlesource.com/platform/libcore", 161 refs = ["refs/heads/master"], 162) 163 164luci.gitiles_poller( 165 name = "vogar", 166 bucket = "ci", 167 repo = "https://android.googlesource.com/platform/external/vogar", 168 refs = ["refs/heads/master"], 169) 170 171luci.gitiles_poller( 172 name = "manifest", 173 bucket = "ci", 174 repo = "https://android.googlesource.com/platform/manifest", 175 refs = ["refs/heads/master-art"], 176) 177 178def ci_builder(name, category, short_name, dimensions, properties={}, 179 experiments={}, hidden=False): 180 luci.builder( 181 name = name, 182 bucket = "ci", 183 executable = luci.recipe( 184 cipd_package = "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build", 185 cipd_version = "refs/heads/main", 186 name = "art", 187 ), 188 dimensions = dimensions | { 189 "pool": "luci.art.ci", 190 }, 191 service_account = "[email protected]", 192 193 # Maximum delay between scheduling a build and the build actually starting. 194 # In a healthy state (enough free/idle devices), the delay is fairly small, 195 # but if enough devices are offline, this timeout will cause INFRA_FAILURE. 196 # Set the value reasonably high to prefer delayed builds over failing ones. 197 # NB: LUCI also enforces (expiration_timeout + execution_timeout <= 47). 198 expiration_timeout = 17 * time.hour, 199 execution_timeout = 30 * time.hour, 200 build_numbers = True, 201 properties = properties, 202 caches = [ 203 # Directory called "art" that persists from build to build (one per bot). 204 # We can checkout and build in this directory to get fast incremental builds. 205 swarming.cache("art", name = "art"), 206 ], 207 notifies = ["art-team+chromium-buildbot"] if not hidden else [], 208 triggered_by = [ 209 "art", 210 "libcore", 211 "manifest", 212 "vogar", 213 ], 214 experiments = experiments, 215 ) 216 if not hidden: 217 luci.console_view_entry( 218 console_view = "luci", 219 builder = name, 220 category = category, 221 short_name = short_name, 222 ) 223 224def add_builder(mode, 225 arch, 226 bitness, 227 ndebug=False, 228 ngen=False, 229 cmc=False, 230 gcstress=False, 231 poison=False, 232 hidden=False): 233 def check_arg(value, valid_values): 234 if value not in valid_values: 235 fail("Argument '{}' was expected to be on of {}".format(value, valid_values)) 236 check_arg(mode, ["target", "host", "qemu"]) 237 check_arg(arch, ["arm", "x86", "riscv"]) 238 check_arg(bitness, [32, 64]) 239 240 # Create builder name based on the configuaration parameters. 241 name = mode + '.' + arch 242 name += '.gsctress' if gcstress else '' 243 name += '.poison' if poison else '' 244 name += '.ngen' if ngen else '' 245 name += '.cmc' if cmc else '' 246 name += '.ndebug' if ndebug else '' 247 name += '.' + str(bitness) 248 name = name.replace("ngen.cmc", "ngen-cmc") 249 250 # Define the LUCI console category (the tree layout). 251 # The "|" splits the tree node into sub-categories. 252 # Merge some name parts to reduce the tree depth. 253 category = name.replace(".", "|") 254 category = category.replace("host|", "host.") 255 category = category.replace("target|", "target.") 256 257 product = None 258 if arch == "arm": 259 product = "armv8" if bitness == 64 else "arm_krait" 260 if arch == "riscv": 261 product = "riscv64" 262 263 dimensions = {"os": "Android" if mode == "target" else "Ubuntu"} 264 if mode == "target": 265 if cmc: 266 # Request devices running Android 24Q3 (`AP1A` builds) for 267 # (`userfaultfd`-based) Concurrent Mark-Compact GC configurations. 268 # Currently (as of 2024-08-22), the only devices within the device pool 269 # allocated to ART that are running `AP1A` builds are Pixel 6 devices 270 # (all other device types are running older Android versions), which are 271 # also the only device model supporting `userfaultfd` among that pool. 272 dimensions |= {"device_os": "A"} 273 else: 274 # Run all other configurations on Android S since it is the oldest we support. 275 # Other than the `AP1A` builds above, all other devices are flashed to `SP2A`. 276 # This avoids allocating `userfaultfd` devices for tests that don't need it. 277 dimensions |= {"device_os": "S"} 278 elif mode == "host": 279 dimensions |= {"cores": "8"} 280 elif mode == "qemu": 281 dimensions |= {"cores": "16"} 282 283 testrunner_args = ['--verbose', '--host'] if mode == 'host' else ['--target', '--verbose'] 284 testrunner_args += ['--ndebug'] if ndebug else ['--debug'] 285 testrunner_args += ['--gcstress'] if gcstress else [] 286 287 properties = { 288 "builder_group": "client.art", 289 "bitness": bitness, 290 "build_only": ("build_only" in name), 291 "debug": not ndebug, 292 "device": None if mode == "host" else "-".join(name.split("-")[:2]), 293 "on_virtual_machine": mode == "qemu", 294 "product": product, 295 "concurrent_collector": not cmc, 296 "generational_cc": not ngen, 297 "gcstress": gcstress, 298 "heap_poisoning": poison, 299 "testrunner_args": testrunner_args, 300 } 301 302 experiments = {"art.superproject": 100} if mode == "qemu" else {} 303 304 ci_builder(name=name, 305 category="|".join(category.split("|")[:-1]), 306 short_name=category.split("|")[-1], 307 dimensions=dimensions, 308 properties={k:v for k, v in properties.items() if v}, 309 experiments=experiments, 310 hidden=hidden) 311 312def add_builders(): 313 for mode, arch in [("target", "arm"), ("host", "x86")]: 314 for bitness in [32, 64]: 315 # Add first to keep these builders together and left-aligned in the console. 316 add_builder(mode, arch, bitness) 317 for bitness in [32, 64]: 318 add_builder(mode, arch, bitness, ndebug=True) 319 if mode == "host": 320 add_builder(mode, arch, bitness, ngen=True, cmc=True) 321 add_builder(mode, arch, bitness, cmc=True) 322 add_builder(mode, arch, bitness, poison=True) 323 add_builder(mode, arch, bitness, gcstress=True) 324 add_builder('qemu', 'arm', bitness=64) 325 add_builder('qemu', 'riscv', bitness=64) 326 327add_builders()