xref: /aosp_15_r20/art/tools/luci/config/main.star (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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()