xref: /aosp_15_r20/external/angle/infra/config/main.star (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1#!/usr/bin/env lucicfg
2#
3# Copyright 2021 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6#
7# main.star: lucicfg configuration for ANGLE's standalone builders.
8
9lucicfg.check_version(min = "1.31.3", message = "Update depot_tools")
10
11# Use LUCI Scheduler BBv2 names and add Scheduler realms configs.
12lucicfg.enable_experiment("crbug.com/1182002")
13
14# Fail build when merge script fails.
15build_experiments = {"chromium_swarming.expose_merge_script_failures": 100}
16
17lucicfg.config(
18    fail_on_warnings = True,
19    lint_checks = [
20        "default",
21        "-module-docstring",
22        "-function-docstring",
23    ],
24)
25
26luci.project(
27    name = "angle",
28    buildbucket = "cr-buildbucket.appspot.com",
29    logdog = "luci-logdog.appspot.com",
30    milo = "luci-milo.appspot.com",
31    notify = "luci-notify.appspot.com",
32    scheduler = "luci-scheduler.appspot.com",
33    swarming = "chromium-swarm.appspot.com",
34    acls = [
35        acl.entry(
36            roles = [
37                acl.PROJECT_CONFIGS_READER,
38                acl.LOGDOG_READER,
39                acl.BUILDBUCKET_READER,
40                acl.SCHEDULER_READER,
41            ],
42            groups = "all",
43        ),
44        acl.entry(
45            roles = [
46                acl.SCHEDULER_OWNER,
47            ],
48            groups = "project-angle-admins",
49        ),
50        acl.entry(
51            roles = [
52                acl.LOGDOG_WRITER,
53            ],
54            groups = "luci-logdog-angle-writers",
55        ),
56    ],
57    bindings = [
58        luci.binding(
59            roles = "role/configs.validator",
60            users = "[email protected]",
61        ),
62        luci.binding(
63            roles = "role/swarming.poolOwner",
64            groups = ["project-angle-owners", "mdb/chrome-troopers"],
65        ),
66        luci.binding(
67            roles = "role/swarming.poolViewer",
68            groups = "all",
69        ),
70        # Allow any Angle build to trigger a test ran under testing accounts
71        # used on shared chromium tester pools.
72        luci.binding(
73            roles = "role/swarming.taskServiceAccount",
74            users = [
75                "[email protected]",
76                "[email protected]",
77            ],
78        ),
79    ],
80)
81
82# Swarming permissions
83luci.realm(name = "pools/ci")
84luci.realm(name = "pools/try")
85
86# Allow Angle owners and Chrome troopers to run tasks directly for testing and
87# development on all Angle bots. E.g. via `led` tool or "Debug" button in Swarming Web UI.
88luci.binding(
89    realm = "@root",
90    roles = "role/swarming.poolUser",
91    groups = ["project-angle-owners", "mdb/chrome-troopers"],
92)
93luci.binding(
94    realm = "@root",
95    roles = "role/swarming.taskTriggerer",
96    groups = ["project-angle-owners", "mdb/chrome-troopers"],
97)
98
99def _generate_project_pyl(ctx):
100    ctx.output["project.pyl"] = "\n".join([
101        "# This is a non-LUCI generated file",
102        "# This is consumed by presubmit checks that need to validate the config",
103        repr(dict(
104            # We don't validate matching source-side configs for simplicity.
105            validate_source_side_specs_have_builder = False,
106        )),
107        "",
108    ])
109
110lucicfg.generator(_generate_project_pyl)
111
112luci.milo(
113    logo = "https://storage.googleapis.com/chrome-infra/OpenGL%20ES_RGB_June16.svg",
114    bug_url_template = "https://bugs.chromium.org/p/angleproject/issues/entry?components=Infra",
115)
116
117luci.logdog(gs_bucket = "chromium-luci-logdog")
118
119# The category for an os: a more generic grouping than specific OS versions that
120# can be used for computing defaults
121os_category = struct(
122    ANDROID = "Android",
123    LINUX = "Linux",
124    MAC = "Mac",
125    WINDOWS = "Windows",
126)
127
128def os_enum(dimension, category, console_name):
129    return struct(dimension = dimension, category = category, console_name = console_name)
130
131os = struct(
132    ANDROID = os_enum("Ubuntu", os_category.ANDROID, "android"),
133    LINUX = os_enum("Ubuntu", os_category.LINUX, "linux"),
134    MAC = os_enum("Mac", os_category.MAC, "mac"),
135    WINDOWS = os_enum("Windows", os_category.WINDOWS, "win"),
136)
137
138# Recipes
139
140_RECIPE_NAME_PREFIX = "recipe:"
141_DEFAULT_BUILDERLESS_OS_CATEGORIES = [os_category.LINUX, os_category.WINDOWS]
142
143def _recipe_for_package(cipd_package):
144    def recipe(*, name, cipd_version = None, recipe = None, use_python3 = False):
145        # Force the caller to put the recipe prefix rather than adding it
146        # programatically to make the string greppable
147        if not name.startswith(_RECIPE_NAME_PREFIX):
148            fail("Recipe name {!r} does not start with {!r}"
149                .format(name, _RECIPE_NAME_PREFIX))
150        if recipe == None:
151            recipe = name[len(_RECIPE_NAME_PREFIX):]
152        return luci.recipe(
153            name = name,
154            cipd_package = cipd_package,
155            cipd_version = cipd_version,
156            recipe = recipe,
157            use_bbagent = True,
158            use_python3 = use_python3,
159        )
160
161    return recipe
162
163build_recipe = _recipe_for_package(
164    "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",
165)
166
167build_recipe(
168    name = "recipe:angle",
169    use_python3 = True,
170)
171
172build_recipe(
173    name = "recipe:run_presubmit",
174    use_python3 = True,
175)
176
177def get_os_from_name(name):
178    if name.startswith("android"):
179        return os.ANDROID
180    if name.startswith("linux"):
181        return os.LINUX
182    if name.startswith("win"):
183        return os.WINDOWS
184    if name.startswith("mac"):
185        return os.MAC
186    return os.MAC
187
188def get_gpu_type_from_builder_name(name):
189    return name.split("-")[1]
190
191# Adds both the CI and Try standalone builders.
192def angle_builder(name, cpu):
193    config_os = get_os_from_name(name)
194    dimensions = {}
195    dimensions["os"] = config_os.dimension
196
197    if config_os.category in _DEFAULT_BUILDERLESS_OS_CATEGORIES:
198        dimensions["builderless"] = "1"
199
200    is_asan = "-asan" in name
201    is_tsan = "-tsan" in name
202    is_debug = "-dbg" in name
203    is_exp = "-exp" in name
204    is_perf = name.endswith("-perf")
205    is_s22 = "s22" in name
206    is_trace = name.endswith("-trace")
207    is_uwp = "winuwp" in name
208    is_msvc = is_uwp or "-msvc" in name
209
210    location_filters = None
211
212    if name.endswith("-compile"):
213        test_mode = "compile_only"
214        category = "compile"
215    elif name.endswith("-test"):
216        test_mode = "compile_and_test"
217        category = "test"
218    elif is_trace:
219        test_mode = "trace_tests"
220        category = "trace"
221
222        # Trace tests are only run on CQ if files in the capture folders change.
223        location_filters = [
224            cq.location_filter(path_regexp = "DEPS"),
225            cq.location_filter(path_regexp = "src/libANGLE/capture/.+"),
226            cq.location_filter(path_regexp = "src/tests/angle_end2end_tests_expectations.txt"),
227            cq.location_filter(path_regexp = "src/tests/capture.+"),
228            cq.location_filter(path_regexp = "src/tests/egl_tests/.+"),
229            cq.location_filter(path_regexp = "src/tests/gl_tests/.+"),
230        ]
231    elif is_perf:
232        test_mode = "compile_and_test"
233        category = "perf"
234    else:
235        print("Test mode unknown for %s" % name)
236
237    if is_msvc:
238        toolchain = "msvc"
239    else:
240        toolchain = "clang"
241
242    if is_uwp:
243        os_toolchain_name = "win-uwp"
244    elif is_msvc:
245        os_toolchain_name = "win-msvc"
246    else:
247        os_toolchain_name = config_os.console_name
248
249    if is_perf:
250        short_name = get_gpu_type_from_builder_name(name)
251    elif is_asan:
252        short_name = "asan"
253        if is_exp:
254            short_name = "asan-exp"
255    elif is_tsan:
256        short_name = "tsan"
257        if is_exp:
258            short_name = "tsan-exp"
259    elif is_debug:
260        short_name = "dbg"
261    elif is_exp:
262        short_name = "exp"
263        if is_s22:
264            # This is a little clunky, but we'd like this to be cleanly "s22" rather than "s22-exp"
265            short_name = "s22"
266    else:
267        short_name = "rel"
268
269    properties = {
270        "builder_group": "angle",
271        "$build/reclient": {
272            "instance": "rbe-chromium-untrusted",
273            "metrics_project": "chromium-reclient-metrics",
274            "scandeps_server": True,
275        },
276        "platform": config_os.console_name,
277        "toolchain": toolchain,
278        "test_mode": test_mode,
279    }
280
281    ci_properties = {
282        "builder_group": "angle",
283        "$build/reclient": {
284            "instance": "rbe-chromium-trusted",
285            "metrics_project": "chromium-reclient-metrics",
286            "scandeps_server": True,
287        },
288        "platform": config_os.console_name,
289        "toolchain": toolchain,
290        "test_mode": test_mode,
291    }
292
293    # TODO(343503161): Remove sheriff_rotations after SoM is updated.
294    ci_properties["gardener_rotations"] = ["angle"]
295    ci_properties["sheriff_rotations"] = ["angle"]
296
297    if is_perf:
298        timeout_hours = 5
299    else:
300        timeout_hours = 3
301
302    luci.builder(
303        name = name,
304        bucket = "ci",
305        triggered_by = ["main-poller"],
306        executable = "recipe:angle",
307        experiments = build_experiments,
308        service_account = "[email protected]",
309        shadow_service_account = "[email protected]",
310        properties = ci_properties,
311        dimensions = dimensions,
312        build_numbers = True,
313        resultdb_settings = resultdb.settings(enable = True),
314        test_presentation = resultdb.test_presentation(
315            column_keys = ["v.gpu"],
316            grouping_keys = ["status", "v.test_suite"],
317        ),
318        triggering_policy = scheduler.policy(
319            kind = scheduler.LOGARITHMIC_BATCHING_KIND,
320            log_base = 2,
321        ),
322        execution_timeout = timeout_hours * time.hour,
323    )
324
325    active_experimental_builders = [
326        "android-arm64-exp-test",
327        "android-arm64-exp-s22-test",
328        "linux-exp-test",
329        "mac-exp-test",
330        "win-exp-test",
331    ]
332
333    if (not is_exp) or (name in active_experimental_builders):
334        luci.console_view_entry(
335            console_view = "ci",
336            builder = "ci/" + name,
337            category = category + "|" + os_toolchain_name + "|" + cpu,
338            short_name = short_name,
339        )
340    else:
341        luci.list_view_entry(
342            list_view = "exp",
343            builder = "ci/" + name,
344        )
345
346    # Do not include perf tests in "try".
347    if not is_perf:
348        luci.list_view_entry(
349            list_view = "try",
350            builder = "try/" + name,
351        )
352
353        luci.builder(
354            name = name,
355            bucket = "try",
356            executable = "recipe:angle",
357            experiments = build_experiments,
358            service_account = "[email protected]",
359            properties = properties,
360            dimensions = dimensions,
361            build_numbers = True,
362            resultdb_settings = resultdb.settings(enable = True),
363            test_presentation = resultdb.test_presentation(
364                column_keys = ["v.gpu"],
365                grouping_keys = ["status", "v.test_suite"],
366            ),
367        )
368
369        # Don't add experimental bots to CQ.
370        if not is_exp:
371            luci.cq_tryjob_verifier(
372                cq_group = "main",
373                builder = "angle:try/" + name,
374                location_filters = location_filters,
375            )
376
377luci.bucket(
378    name = "ci",
379    acls = [
380        acl.entry(
381            acl.BUILDBUCKET_TRIGGERER,
382            users = [
383                "[email protected]",
384            ],
385        ),
386    ],
387)
388
389luci.bucket(
390    name = "try",
391    acls = [
392        acl.entry(
393            acl.BUILDBUCKET_TRIGGERER,
394            groups = [
395                "project-angle-tryjob-access",
396                "service-account-cq",
397            ],
398        ),
399    ],
400)
401
402# Shadow buckets for LED jobs.
403luci.bucket(
404    name = "ci.shadow",
405    shadows = "ci",
406    constraints = luci.bucket_constraints(
407        pools = ["luci.angle.ci"],
408    ),
409    bindings = [
410        luci.binding(
411            roles = "role/buildbucket.creator",
412            groups = [
413                "mdb/chrome-build-access-sphinx",
414                "mdb/chrome-troopers",
415                "chromium-led-users",
416            ],
417            users = [
418                "[email protected]",
419            ],
420        ),
421        luci.binding(
422            roles = "role/buildbucket.triggerer",
423            users = [
424                "[email protected]",
425            ],
426        ),
427        # Allow ci builders to create invocations in their own builds.
428        luci.binding(
429            roles = "role/resultdb.invocationCreator",
430            users = [
431                "[email protected]",
432            ],
433        ),
434    ],
435    dynamic = True,
436)
437
438luci.bucket(
439    name = "try.shadow",
440    shadows = "try",
441    constraints = luci.bucket_constraints(
442        pools = ["luci.angle.try"],
443        service_accounts = [
444            "[email protected]",
445        ],
446    ),
447    bindings = [
448        luci.binding(
449            roles = "role/buildbucket.creator",
450            groups = [
451                "mdb/chrome-build-access-sphinx",
452                "mdb/chrome-troopers",
453                "chromium-led-users",
454            ],
455            users = [
456                "[email protected]",
457            ],
458        ),
459        luci.binding(
460            roles = "role/buildbucket.triggerer",
461            users = [
462                "[email protected]",
463            ],
464        ),
465        # Allow try builders to create invocations in their own builds.
466        luci.binding(
467            roles = "role/resultdb.invocationCreator",
468            groups = [
469                "project-angle-try-task-accounts",
470                "project-angle-tryjob-access",
471            ],
472        ),
473    ],
474    dynamic = True,
475)
476
477luci.builder(
478    name = "presubmit",
479    bucket = "try",
480    executable = "recipe:run_presubmit",
481    experiments = build_experiments,
482    service_account = "[email protected]",
483    build_numbers = True,
484    dimensions = {
485        "os": os.LINUX.dimension,
486    },
487    properties = {
488        "repo_name": "angle",
489        "runhooks": True,
490    },
491    resultdb_settings = resultdb.settings(enable = True),
492    test_presentation = resultdb.test_presentation(
493        column_keys = ["v.gpu"],
494        grouping_keys = ["status", "v.test_suite"],
495    ),
496)
497
498luci.gitiles_poller(
499    name = "main-poller",
500    bucket = "ci",
501    repo = "https://chromium.googlesource.com/angle/angle",
502    refs = [
503        "refs/heads/main",
504    ],
505    schedule = "with 10s interval",
506)
507
508# name, clang, debug, cpu, uwp, trace_tests
509angle_builder("android-arm-compile", cpu = "arm")
510angle_builder("android-arm-dbg-compile", cpu = "arm")
511angle_builder("android-arm64-dbg-compile", cpu = "arm64")
512angle_builder("android-arm64-exp-s22-test", cpu = "arm64")
513angle_builder("android-arm64-exp-test", cpu = "arm64")
514angle_builder("android-arm64-test", cpu = "arm64")
515angle_builder("linux-asan-test", cpu = "x64")
516angle_builder("linux-exp-asan-test", cpu = "x64")
517angle_builder("linux-exp-test", cpu = "x64")
518angle_builder("linux-exp-tsan-test", cpu = "x64")
519angle_builder("linux-tsan-test", cpu = "x64")
520angle_builder("linux-dbg-compile", cpu = "x64")
521angle_builder("linux-test", cpu = "x64")
522angle_builder("mac-dbg-compile", cpu = "x64")
523angle_builder("mac-exp-test", cpu = "x64")
524angle_builder("mac-test", cpu = "x64")
525angle_builder("win-asan-test", cpu = "x64")
526angle_builder("win-dbg-compile", cpu = "x64")
527angle_builder("win-exp-test", cpu = "x64")
528angle_builder("win-msvc-compile", cpu = "x64")
529angle_builder("win-msvc-dbg-compile", cpu = "x64")
530angle_builder("win-msvc-x86-compile", cpu = "x86")
531angle_builder("win-msvc-x86-dbg-compile", cpu = "x86")
532angle_builder("win-test", cpu = "x64")
533angle_builder("win-x86-dbg-compile", cpu = "x86")
534angle_builder("win-x86-test", cpu = "x86")
535angle_builder("winuwp-compile", cpu = "x64")
536angle_builder("winuwp-dbg-compile", cpu = "x64")
537
538angle_builder("linux-trace", cpu = "x64")
539angle_builder("win-trace", cpu = "x64")
540
541angle_builder("android-pixel4-perf", cpu = "arm64")
542angle_builder("android-pixel6-perf", cpu = "arm64")
543angle_builder("linux-intel-uhd630-perf", cpu = "x64")
544angle_builder("linux-nvidia-gtx1660-perf", cpu = "x64")
545angle_builder("win10-intel-uhd630-perf", cpu = "x64")
546angle_builder("win10-nvidia-gtx1660-perf", cpu = "x64")
547
548# Views
549
550luci.console_view(
551    name = "ci",
552    title = "ANGLE CI Builders",
553    repo = "https://chromium.googlesource.com/angle/angle",
554)
555
556luci.list_view(
557    name = "exp",
558    title = "ANGLE Experimental CI Builders",
559)
560
561luci.list_view(
562    name = "try",
563    title = "ANGLE Try Builders",
564)
565
566luci.list_view_entry(
567    list_view = "try",
568    builder = "try/presubmit",
569)
570
571# CQ
572
573luci.cq(
574    status_host = "chromium-cq-status.appspot.com",
575    submit_max_burst = 4,
576    submit_burst_delay = 480 * time.second,
577)
578
579luci.cq_group(
580    name = "main",
581    watch = cq.refset(
582        "https://chromium.googlesource.com/angle/angle",
583        refs = [r"refs/heads/main"],
584    ),
585    acls = [
586        acl.entry(
587            acl.CQ_COMMITTER,
588            groups = "project-angle-committers",
589        ),
590        acl.entry(
591            acl.CQ_DRY_RUNNER,
592            groups = "project-angle-tryjob-access",
593        ),
594    ],
595    verifiers = [
596        luci.cq_tryjob_verifier(
597            builder = "angle:try/presubmit",
598            disable_reuse = True,
599        ),
600        luci.cq_tryjob_verifier(
601            builder = "chromium:try/android-angle-chromium-try",
602        ),
603        luci.cq_tryjob_verifier(
604            builder = "chromium:try/fuchsia-angle-try",
605        ),
606        luci.cq_tryjob_verifier(
607            builder = "chromium:try/linux-angle-chromium-try",
608        ),
609        luci.cq_tryjob_verifier(
610            builder = "chromium:try/mac-angle-chromium-try",
611        ),
612        luci.cq_tryjob_verifier(
613            builder = "chromium:try/win-angle-chromium-x64-try",
614        ),
615        luci.cq_tryjob_verifier(
616            builder = "chromium:try/win-angle-chromium-x86-try",
617        ),
618    ],
619)
620