go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/lucicfg/testdata/full_example.star (about)

     1  lucicfg.config(config_dir = ".output")
     2  lucicfg.config(tracked_files = ["*.cfg"])
     3  lucicfg.config(fail_on_warnings = True)
     4  
     5  luci.project(
     6      name = "infra",
     7      buildbucket = "cr-buildbucket.appspot.com",
     8      logdog = "luci-logdog.appspot.com",
     9      milo = "luci-milo.appspot.com",
    10      notify = "luci-notify.appspot.com",
    11      scheduler = "luci-scheduler.appspot.com",
    12      swarming = "chromium-swarm.appspot.com",
    13      tricium = "tricium-prod.appspot.com",
    14      acls = [
    15          acl.entry(
    16              roles = [
    17                  acl.PROJECT_CONFIGS_READER,
    18                  acl.LOGDOG_READER,
    19                  acl.BUILDBUCKET_READER,
    20                  acl.SCHEDULER_READER,
    21              ],
    22              groups = ["all"],
    23          ),
    24          acl.entry(
    25              roles = [
    26                  acl.BUILDBUCKET_OWNER,
    27                  acl.SCHEDULER_OWNER,
    28                  acl.CQ_COMMITTER,
    29              ],
    30              groups = ["admins"],
    31          ),
    32      ],
    33  )
    34  
    35  luci.logdog(
    36      gs_bucket = "chromium-luci-logdog",
    37      cloud_logging_project = "chromium-build-logs",
    38  )
    39  
    40  luci.milo(
    41      logo = "https://storage.googleapis.com/chrome-infra-public/logo/chrome-infra-logo-200x200.png",
    42      favicon = "https://storage.googleapis.com/chrome-infra-public/logo/favicon.ico",
    43      bug_url_template = "https://bugs.chromium.org/p/tutu%%2C%%20all%%20aboard/issues/entry?summary=Bug%%20summary&description=Everything%%20is%%20broken&components=Stuff%%3EHard",
    44  )
    45  
    46  luci.buildbucket_notification_topic(
    47      name = "projects/my-cloud-project1/topics/my-topic1",
    48  )
    49  luci.buildbucket_notification_topic(
    50      name = "projects/my-cloud-project2/topics/my-topic2",
    51      compression = "ZSTD",
    52  )
    53  
    54  # Recipes.
    55  
    56  luci.recipe(
    57      name = "main/recipe",
    58      cipd_package = "recipe/bundles/main",
    59      use_python3 = True,
    60      wrapper = ["path/to/wrapper"],
    61  )
    62  
    63  # Executables.
    64  
    65  luci.executable(
    66      name = "main/executable",
    67      cipd_package = "executable/bundles/main",
    68      cmd = ["cmd"],
    69  )
    70  
    71  # Task Backend
    72  luci.task_backend(
    73      name = "my_test_backend",
    74      target = "swarming://chromium",
    75      config = {"key": "value"},
    76  )
    77  
    78  # CI bucket.
    79  
    80  luci.bucket(
    81      name = "ci",
    82  
    83      # Allow developers to force-launch CI builds through Scheduler, but not
    84      # directly through Buildbucket. The direct access to Buildbucket allows to
    85      # override almost all aspects of the builds (e.g. what recipe is used),
    86      # and Buildbucket totally ignores any concurrency limitations set in the
    87      # LUCI Scheduler configs. This makes direct Buildbucket access to CI buckets
    88      # dangerous. They usually have very small pool of machines, and these
    89      # machines are assumed to be running only "approved" code (being post-submit
    90      # builders).
    91      acls = [
    92          acl.entry(
    93              acl.SCHEDULER_TRIGGERER,
    94              groups = ["devs"],
    95              projects = ["some-project"],
    96          ),
    97      ],
    98  )
    99  
   100  luci.gitiles_poller(
   101      name = "main-poller",
   102      bucket = "ci",
   103      repo = "https://noop.com",
   104      refs = [
   105          "refs/heads/main",
   106          "refs/tags/blah",
   107          r"refs/branch-heads/\d+\.\d+",
   108      ],
   109      path_regexps = [".*"],
   110      path_regexps_exclude = ["excluded"],
   111      schedule = "with 10s interval",
   112  )
   113  
   114  luci.builder(
   115      name = "linux ci builder",
   116      bucket = "ci",
   117      description_html = "this is a linux ci builder",
   118      executable = "main/recipe",
   119      triggered_by = ["main-poller"],
   120      triggers = [
   121          "ci/generically named builder",
   122          "ci/generically named executable builder",
   123      ],
   124      properties = {
   125          "prop2": ["val2", 123],
   126          "prop1": "val1",
   127      },
   128      allowed_property_overrides = ["prop1"],
   129      service_account = "builder@example.com",
   130      caches = [
   131          swarming.cache("path1"),
   132          swarming.cache("path2", name = "name2"),
   133          swarming.cache("path3", name = "name3", wait_for_warm_cache = 10 * time.minute),
   134      ],
   135      execution_timeout = 3 * time.hour,
   136      grace_period = 2 * time.minute,
   137      heartbeat_timeout = 10 * time.minute,
   138      dimensions = {
   139          "os": "Linux",
   140          "builder": "linux ci builder",  # no auto_builder_dimension
   141          "prefer_if_available": [
   142              swarming.dimension("first-choice", expiration = 5 * time.minute),
   143              swarming.dimension("fallback"),
   144          ],
   145      },
   146      priority = 80,
   147      swarming_tags = ["tag1:val1", "tag2:val2"],
   148      expiration_timeout = time.hour,
   149      build_numbers = True,
   150      triggering_policy = scheduler.greedy_batching(
   151          max_concurrent_invocations = 5,
   152          max_batch_size = 10,
   153      ),
   154      resultdb_settings = resultdb.settings(
   155          enable = True,
   156          bq_exports = [
   157              resultdb.export_test_results(
   158                  bq_table = ("luci-resultdb", "my-awesome-project", "all_test_results"),
   159                  predicate = resultdb.test_result_predicate(
   160                      test_id_regexp = "ninja:.*",
   161                      unexpected_only = True,
   162                      variant_contains = True,
   163                      variant = {"test_suite": "super_interesting_suite"},
   164                  ),
   165              ),
   166              resultdb.export_text_artifacts(
   167                  bq_table = "luci-resultdb.my-awesome-project.all_text_artifacts",
   168                  predicate = resultdb.artifact_predicate(
   169                      test_result_predicate = resultdb.test_result_predicate(
   170                          test_id_regexp = "ninja:.*",
   171                          unexpected_only = True,
   172                          variant_contains = True,
   173                          variant = {"test_suite": "super_interesting_suite"},
   174                      ),
   175                      included_invocations = False,
   176                      test_results = True,
   177                      content_type_regexp = "text.*",
   178                  ),
   179              ),
   180          ],
   181          history_options = resultdb.history_options(
   182              by_timestamp = True,
   183          ),
   184      ),
   185      test_presentation = resultdb.test_presentation(
   186          column_keys = ["v.gpu"],
   187          grouping_keys = ["status", "v.test_suite"],
   188      ),
   189  )
   190  
   191  luci.builder(
   192      name = "generically named builder",
   193      bucket = "ci",
   194      executable = "main/recipe",
   195      triggered_by = ["main-poller"],
   196  )
   197  
   198  luci.builder(
   199      name = "generically named executable builder",
   200      bucket = "ci",
   201      executable = "main/executable",
   202      properties = {
   203          "prop2": ["val2", 123],
   204          "prop1": "val1",
   205      },
   206      allowed_property_overrides = ["*"],
   207      triggered_by = ["main-poller"],
   208  )
   209  
   210  luci.builder(
   211      name = "cron builder",
   212      bucket = "ci",
   213      executable = "main/recipe",
   214      schedule = "0 6 * * *",
   215      repo = "https://cron.repo.example.com",
   216  )
   217  
   218  luci.builder(
   219      name = "newest first schedule builder",
   220      bucket = "ci",
   221      executable = "main/recipe",
   222      triggering_policy = scheduler.newest_first(
   223          max_concurrent_invocations = 2,
   224          pending_timeout = 3 * 24 * time.hour,
   225      ),
   226      repo = "https://newest-first.repo.example.com",
   227  )
   228  
   229  luci.builder(
   230      name = "builder with custom swarming host",
   231      bucket = "ci",
   232      executable = "main/recipe",
   233      swarming_host = "another-swarming.appspot.com",
   234  )
   235  
   236  luci.builder(
   237      name = "builder with the default test presentation config",
   238      bucket = "ci",
   239      executable = "main/recipe",
   240      test_presentation = resultdb.test_presentation(
   241          column_keys = [],
   242          grouping_keys = ["status"],
   243      ),
   244  )
   245  
   246  # Try bucket.
   247  
   248  luci.bucket(
   249      name = "try",
   250  
   251      # Allow developers to launch try jobs directly with whatever parameters
   252      # they want. Try bucket is basically a free build farm for all developers.
   253      acls = [
   254          acl.entry(acl.BUILDBUCKET_TRIGGERER, groups = "devs"),
   255      ],
   256  )
   257  
   258  luci.builder(
   259      name = "linux try builder",
   260      bucket = "try",
   261      executable = "main/recipe",
   262  )
   263  
   264  luci.builder(
   265      name = "linux try builder 2",
   266      bucket = "try",
   267      executable = "main/recipe",
   268  )
   269  
   270  luci.builder(
   271      name = "generically named builder",
   272      bucket = "try",
   273      executable = "main/recipe",
   274  )
   275  
   276  luci.builder(
   277      name = "builder with executable",
   278      bucket = "try",
   279      executable = "main/executable",
   280  )
   281  
   282  luci.builder(
   283      name = "builder with experiment map",
   284      bucket = "try",
   285      executable = "main/executable",
   286      experiments = {
   287          "luci.enable_new_beta_feature": 32,
   288      },
   289  )
   290  luci.builder(
   291      name = "website-preview",
   292      bucket = "try",
   293      executable = "main/recipe",
   294  )
   295  
   296  luci.builder(
   297      name = "spell-checker",
   298      bucket = "try",
   299      executable = "main/recipe",
   300  )
   301  
   302  # Inline definitions.
   303  
   304  def inline_poller():
   305      return luci.gitiles_poller(
   306          name = "inline poller",
   307          bucket = "inline",
   308          repo = "https://noop.com",
   309          refs = [
   310              "refs/heads/main",
   311              "refs/tags/blah",
   312              r"refs/branch-heads/\d+\.\d+",
   313          ],
   314          schedule = "with 10s interval",
   315      )
   316  
   317  luci.builder(
   318      name = "triggerer builder",
   319      bucket = luci.bucket(name = "inline"),
   320      executable = luci.recipe(
   321          name = "inline/recipe",
   322          cipd_package = "recipe/bundles/inline",
   323          use_bbagent = True,
   324      ),
   325      service_account = "builder@example.com",
   326      triggers = [
   327          luci.builder(
   328              name = "triggered builder",
   329              bucket = "inline",
   330              executable = "inline/recipe",
   331          ),
   332      ],
   333      triggered_by = [inline_poller()],
   334  )
   335  
   336  luci.builder(
   337      name = "another builder",
   338      bucket = "inline",
   339      executable = luci.recipe(
   340          name = "inline/recipe",
   341          cipd_package = "recipe/bundles/inline",
   342          use_bbagent = True,
   343      ),
   344      service_account = "builder@example.com",
   345      triggered_by = [inline_poller()],
   346  )
   347  
   348  luci.builder(
   349      name = "another executable builder",
   350      bucket = "inline",
   351      executable = luci.executable(
   352          name = "inline/executable",
   353          cipd_package = "executable/bundles/inline",
   354      ),
   355      service_account = "builder@example.com",
   356      triggered_by = [inline_poller()],
   357  )
   358  
   359  luci.builder(
   360      name = "executable builder wrapper",
   361      bucket = "inline",
   362      executable = luci.executable(
   363          name = "wrapped executable",
   364          cipd_package = "executable/bundles/inline",
   365          wrapper = ["/path/to/wrapper"],
   366      ),
   367      service_account = "builder@example.com",
   368  )
   369  
   370  # List views.
   371  
   372  luci.list_view(
   373      name = "List view",
   374      entries = [
   375          "cron builder",
   376          "ci/generically named builder",
   377          luci.list_view_entry(
   378              builder = "linux ci builder",
   379          ),
   380      ],
   381  )
   382  
   383  luci.list_view_entry(
   384      list_view = "List view",
   385      builder = "inline/triggered builder",
   386  )
   387  
   388  # Console views.
   389  
   390  luci.console_view(
   391      name = "Console view",
   392      title = "CI Builders",
   393      header = {
   394          "links": [
   395              {"name": "a", "links": [{"text": "a"}]},
   396              {"name": "b", "links": [{"text": "b"}]},
   397          ],
   398      },
   399      repo = "https://noop.com",
   400      refs = ["refs/tags/blah", r"refs/branch-heads/\d+\.\d+"],
   401      exclude_ref = "refs/heads/main",
   402      include_experimental_builds = True,
   403      entries = [
   404          luci.console_view_entry(
   405              builder = "linux ci builder",
   406              category = "a|b",
   407              short_name = "lnx",
   408          ),
   409          # An alias for luci.console_view_entry(**{...}).
   410          {"builder": "cron builder", "category": "cron"},
   411      ],
   412      default_commit_limit = 3,
   413      default_expand = True,
   414  )
   415  
   416  luci.console_view_entry(
   417      console_view = "Console view",
   418      builder = "inline/triggered builder",
   419  )
   420  
   421  luci.external_console_view(
   422      name = "external-console",
   423      title = "External console",
   424      source = "chromium:main",
   425  )
   426  
   427  # Notifier.
   428  
   429  luci.notifier(
   430      name = "main notifier",
   431      on_new_status = ["FAILURE"],
   432      notify_emails = ["someone@example,com"],
   433      notify_blamelist = True,
   434      template = "notifier_template",
   435      notified_by = [
   436          "linux ci builder",
   437          "cron builder",
   438      ],
   439  )
   440  
   441  luci.notifier_template(
   442      name = "notifier_template",
   443      body = "Hello\n\nHi\n",
   444  )
   445  
   446  luci.notifier_template(
   447      name = "another_template",
   448      body = "Boo!\n",
   449  )
   450  
   451  luci.builder(
   452      name = "watched builder",
   453      bucket = "ci",
   454      executable = "main/recipe",
   455      repo = "https://custom.example.com/repo",
   456      notifies = ["main notifier"],
   457  )
   458  
   459  # CQ.
   460  
   461  luci.cq(
   462      submit_max_burst = 10,
   463      submit_burst_delay = 10 * time.minute,
   464      draining_start_time = "2017-12-23T15:47:58Z",
   465      status_host = "chromium-cq-status.appspot.com",
   466  )
   467  
   468  luci.cq_group(
   469      name = "main-cq",
   470      watch = [
   471          cq.refset("https://example.googlesource.com/repo"),
   472          cq.refset(
   473              "https://example.googlesource.com/another/repo",
   474              refs_exclude = ["refs/heads/infra/config"],
   475          ),
   476      ],
   477      acls = [
   478          acl.entry(acl.CQ_COMMITTER, groups = ["committers"]),
   479          acl.entry(acl.CQ_DRY_RUNNER, groups = ["dry-runners"]),
   480          acl.entry(acl.CQ_NEW_PATCHSET_RUN_TRIGGERER, groups = ["new-patchset-runners"]),
   481      ],
   482      allow_submit_with_open_deps = True,
   483      allow_owner_if_submittable = cq.ACTION_COMMIT,
   484      trust_dry_runner_deps = True,
   485      allow_non_owner_dry_runner = True,
   486      tree_status_host = "tree-status.example.com",
   487      verifiers = [
   488          luci.cq_tryjob_verifier(
   489              builder = "linux try builder",
   490              cancel_stale = False,
   491              result_visibility = cq.COMMENT_LEVEL_RESTRICTED,
   492              location_filters = [
   493                  cq.location_filter(
   494                      gerrit_host_regexp = "example.com",
   495                      gerrit_project_regexp = "repo",
   496                      path_regexp = "all/one.txt",
   497                      exclude = True,
   498                  ),
   499              ],
   500              mode_allowlist = [cq.MODE_DRY_RUN, cq.MODE_FULL_RUN],
   501          ),
   502          # An experimental verifier with a location filter.
   503          luci.cq_tryjob_verifier(
   504              builder = "linux try builder 2",
   505              location_filters = [
   506                  cq.location_filter(
   507                      gerrit_host_regexp = "example.com",
   508                      gerrit_project_regexp = "repo",
   509                      path_regexp = "all/two.txt",
   510                      exclude = True,
   511                  ),
   512              ],
   513              experiment_percentage = 50,
   514          ),
   515          # An alias for luci.cq_tryjob_verifier(**{...}).
   516          {"builder": "try/generically named builder", "disable_reuse": True},
   517          # An alias for luci.cq_tryjob_verifier(<builder>).
   518          "another-project:try/yyy",
   519          luci.cq_tryjob_verifier(
   520              builder = "another-project:try/zzz",
   521              includable_only = True,
   522              owner_whitelist = ["another-project-committers"],
   523          ),
   524          luci.cq_tryjob_verifier(
   525              builder = "website-preview",
   526              owner_whitelist = ["project-contributor"],
   527              mode_allowlist = [cq.MODE_NEW_PATCHSET_RUN],
   528          ),
   529          luci.cq_tryjob_verifier(
   530              builder = "spell-checker",
   531              owner_whitelist = ["project-contributor"],
   532              mode_allowlist = [cq.MODE_ANALYZER_RUN],
   533              disable_reuse = True,
   534          ),
   535      ],
   536      additional_modes = cq.run_mode(
   537          name = "TEST_RUN",
   538          cq_label_value = 1,
   539          triggering_label = "TEST_RUN_LABEL",
   540          triggering_value = 1,
   541      ),
   542      user_limits = [
   543          cq.user_limit(
   544              name = "comitters",
   545              groups = ["comitters"],
   546              run = cq.run_limits(max_active = 3),
   547          ),
   548      ],
   549      user_limit_default = cq.user_limit(
   550          name = "user_limit_default",
   551          run = cq.run_limits(max_active = 1),
   552      ),
   553      tryjob_experiments = [
   554          cq.tryjob_experiment(
   555              name = "infra.experiment.internal",
   556              owner_group_allowlist = ["googler", "bot-accounts"],
   557          ),
   558          cq.tryjob_experiment(
   559              name = "infra.experiment.public",
   560          ),
   561      ],
   562  )
   563  
   564  luci.cq_tryjob_verifier(
   565      builder = "triggerer builder",
   566      cq_group = "main-cq",
   567      experiment_percentage = 50.0,
   568  )
   569  
   570  luci.cq_tryjob_verifier(
   571      builder = luci.builder(
   572          name = "main cq builder",
   573          bucket = "try",
   574          executable = "main/recipe",
   575      ),
   576      equivalent_builder = luci.builder(
   577          name = "equivalent cq builder",
   578          bucket = "try",
   579          executable = "main/recipe",
   580      ),
   581      equivalent_builder_percentage = 60,
   582      equivalent_builder_whitelist = "owners",
   583      cq_group = "main-cq",
   584  )
   585  
   586  luci.cq_tryjob_verifier(
   587      builder = "another-project:analyzer/format checker",
   588      cq_group = "main-cq",
   589      location_filters = [
   590          cq.location_filter(path_regexp = ".+\\.py"),
   591          cq.location_filter(path_regexp = ".+\\.go"),
   592          cq.location_filter(path_regexp = ".+\\.X4"),
   593      ],
   594      owner_whitelist = ["project-contributor"],
   595      mode_allowlist = [cq.MODE_ANALYZER_RUN, cq.MODE_FULL_RUN],
   596  )
   597  
   598  # Emitting arbitrary configs,
   599  
   600  lucicfg.emit(
   601      dest = "dir/custom.cfg",
   602      data = "hello!\n",
   603  )
   604  
   605  # Expect configs:
   606  #
   607  # === commit-queue.cfg
   608  # draining_start_time: "2017-12-23T15:47:58Z"
   609  # cq_status_host: "chromium-cq-status.appspot.com"
   610  # submit_options {
   611  #   max_burst: 10
   612  #   burst_delay {
   613  #     seconds: 600
   614  #   }
   615  # }
   616  # config_groups {
   617  #   name: "main-cq"
   618  #   gerrit {
   619  #     url: "https://example-review.googlesource.com"
   620  #     projects {
   621  #       name: "repo"
   622  #       ref_regexp: "refs/heads/main"
   623  #     }
   624  #     projects {
   625  #       name: "another/repo"
   626  #       ref_regexp: "refs/heads/main"
   627  #       ref_regexp_exclude: "refs/heads/infra/config"
   628  #     }
   629  #   }
   630  #   verifiers {
   631  #     gerrit_cq_ability {
   632  #       committer_list: "admins"
   633  #       committer_list: "committers"
   634  #       dry_run_access_list: "dry-runners"
   635  #       new_patchset_run_access_list: "new-patchset-runners"
   636  #       allow_submit_with_open_deps: true
   637  #       allow_owner_if_submittable: COMMIT
   638  #       trust_dry_runner_deps: true
   639  #       allow_non_owner_dry_runner: true
   640  #     }
   641  #     tree_status {
   642  #       url: "https://tree-status.example.com"
   643  #     }
   644  #     tryjob {
   645  #       builders {
   646  #         name: "another-project/analyzer/format checker"
   647  #         location_filters {
   648  #           gerrit_host_regexp: ".*"
   649  #           gerrit_project_regexp: ".*"
   650  #           path_regexp: ".+\\.py"
   651  #         }
   652  #         location_filters {
   653  #           gerrit_host_regexp: ".*"
   654  #           gerrit_project_regexp: ".*"
   655  #           path_regexp: ".+\\.go"
   656  #         }
   657  #         location_filters {
   658  #           gerrit_host_regexp: ".*"
   659  #           gerrit_project_regexp: ".*"
   660  #           path_regexp: ".+\\.X4"
   661  #         }
   662  #         owner_whitelist_group: "project-contributor"
   663  #         mode_allowlist: "ANALYZER_RUN"
   664  #         mode_allowlist: "FULL_RUN"
   665  #       }
   666  #       builders {
   667  #         name: "another-project/try/yyy"
   668  #       }
   669  #       builders {
   670  #         name: "another-project/try/zzz"
   671  #         includable_only: true
   672  #         owner_whitelist_group: "another-project-committers"
   673  #       }
   674  #       builders {
   675  #         name: "infra/inline/triggerer builder"
   676  #         experiment_percentage: 50
   677  #       }
   678  #       builders {
   679  #         name: "infra/try/generically named builder"
   680  #         disable_reuse: true
   681  #       }
   682  #       builders {
   683  #         name: "infra/try/linux try builder"
   684  #         result_visibility: COMMENT_LEVEL_RESTRICTED
   685  #         cancel_stale: NO
   686  #         location_filters {
   687  #           gerrit_host_regexp: "example.com"
   688  #           gerrit_project_regexp: "repo"
   689  #           path_regexp: "all/one.txt"
   690  #           exclude: true
   691  #         }
   692  #         mode_allowlist: "DRY_RUN"
   693  #         mode_allowlist: "FULL_RUN"
   694  #       }
   695  #       builders {
   696  #         name: "infra/try/linux try builder 2"
   697  #         experiment_percentage: 50
   698  #         location_filters {
   699  #           gerrit_host_regexp: "example.com"
   700  #           gerrit_project_regexp: "repo"
   701  #           path_regexp: "all/two.txt"
   702  #           exclude: true
   703  #         }
   704  #       }
   705  #       builders {
   706  #         name: "infra/try/main cq builder"
   707  #         equivalent_to {
   708  #           name: "infra/try/equivalent cq builder"
   709  #           percentage: 60
   710  #           owner_whitelist_group: "owners"
   711  #         }
   712  #       }
   713  #       builders {
   714  #         name: "infra/try/spell-checker"
   715  #         disable_reuse: true
   716  #         owner_whitelist_group: "project-contributor"
   717  #         mode_allowlist: "ANALYZER_RUN"
   718  #       }
   719  #       builders {
   720  #         name: "infra/try/website-preview"
   721  #         owner_whitelist_group: "project-contributor"
   722  #         mode_allowlist: "NEW_PATCHSET_RUN"
   723  #       }
   724  #       retry_config {
   725  #         single_quota: 1
   726  #         global_quota: 2
   727  #         failure_weight: 100
   728  #         transient_failure_weight: 1
   729  #         timeout_weight: 100
   730  #       }
   731  #     }
   732  #   }
   733  #   additional_modes {
   734  #     name: "TEST_RUN"
   735  #     cq_label_value: 1
   736  #     triggering_label: "TEST_RUN_LABEL"
   737  #     triggering_value: 1
   738  #   }
   739  #   user_limits {
   740  #     name: "comitters"
   741  #     principals: "group:comitters"
   742  #     run {
   743  #       max_active {
   744  #         value: 3
   745  #       }
   746  #     }
   747  #   }
   748  #   user_limit_default {
   749  #     name: "user_limit_default"
   750  #     run {
   751  #       max_active {
   752  #         value: 1
   753  #       }
   754  #     }
   755  #   }
   756  #   tryjob_experiments {
   757  #     name: "infra.experiment.internal"
   758  #     condition {
   759  #       owner_group_allowlist: "googler"
   760  #       owner_group_allowlist: "bot-accounts"
   761  #     }
   762  #   }
   763  #   tryjob_experiments {
   764  #     name: "infra.experiment.public"
   765  #   }
   766  # }
   767  # ===
   768  #
   769  # === cr-buildbucket.cfg
   770  # buckets {
   771  #   name: "ci"
   772  #   acls {
   773  #     role: WRITER
   774  #     group: "admins"
   775  #   }
   776  #   acls {
   777  #     group: "all"
   778  #   }
   779  #   swarming {
   780  #     builders {
   781  #       name: "builder with custom swarming host"
   782  #       swarming_host: "another-swarming.appspot.com"
   783  #       exe {
   784  #         cipd_package: "recipe/bundles/main"
   785  #         cipd_version: "refs/heads/main"
   786  #         cmd: "luciexe"
   787  #         wrapper: "path/to/wrapper"
   788  #       }
   789  #       properties:
   790  #         '{'
   791  #         '  "recipe": "main/recipe"'
   792  #         '}'
   793  #       experiments {
   794  #         key: "luci.recipes.use_python3"
   795  #         value: 100
   796  #       }
   797  #     }
   798  #     builders {
   799  #       name: "builder with the default test presentation config"
   800  #       swarming_host: "chromium-swarm.appspot.com"
   801  #       exe {
   802  #         cipd_package: "recipe/bundles/main"
   803  #         cipd_version: "refs/heads/main"
   804  #         cmd: "luciexe"
   805  #         wrapper: "path/to/wrapper"
   806  #       }
   807  #       properties:
   808  #         '{'
   809  #         '  "recipe": "main/recipe"'
   810  #         '}'
   811  #       experiments {
   812  #         key: "luci.recipes.use_python3"
   813  #         value: 100
   814  #       }
   815  #     }
   816  #     builders {
   817  #       name: "cron builder"
   818  #       swarming_host: "chromium-swarm.appspot.com"
   819  #       exe {
   820  #         cipd_package: "recipe/bundles/main"
   821  #         cipd_version: "refs/heads/main"
   822  #         cmd: "luciexe"
   823  #         wrapper: "path/to/wrapper"
   824  #       }
   825  #       properties:
   826  #         '{'
   827  #         '  "recipe": "main/recipe"'
   828  #         '}'
   829  #       experiments {
   830  #         key: "luci.recipes.use_python3"
   831  #         value: 100
   832  #       }
   833  #     }
   834  #     builders {
   835  #       name: "generically named builder"
   836  #       swarming_host: "chromium-swarm.appspot.com"
   837  #       exe {
   838  #         cipd_package: "recipe/bundles/main"
   839  #         cipd_version: "refs/heads/main"
   840  #         cmd: "luciexe"
   841  #         wrapper: "path/to/wrapper"
   842  #       }
   843  #       properties:
   844  #         '{'
   845  #         '  "recipe": "main/recipe"'
   846  #         '}'
   847  #       experiments {
   848  #         key: "luci.recipes.use_python3"
   849  #         value: 100
   850  #       }
   851  #     }
   852  #     builders {
   853  #       name: "generically named executable builder"
   854  #       swarming_host: "chromium-swarm.appspot.com"
   855  #       exe {
   856  #         cipd_package: "executable/bundles/main"
   857  #         cipd_version: "refs/heads/main"
   858  #         cmd: "cmd"
   859  #       }
   860  #       properties:
   861  #         '{'
   862  #         '  "prop1": "val1",'
   863  #         '  "prop2": ['
   864  #         '    "val2",'
   865  #         '    123'
   866  #         '  ]'
   867  #         '}'
   868  #       allowed_property_overrides: "*"
   869  #     }
   870  #     builders {
   871  #       name: "linux ci builder"
   872  #       swarming_host: "chromium-swarm.appspot.com"
   873  #       swarming_tags: "tag1:val1"
   874  #       swarming_tags: "tag2:val2"
   875  #       dimensions: "builder:linux ci builder"
   876  #       dimensions: "os:Linux"
   877  #       dimensions: "300:prefer_if_available:first-choice"
   878  #       dimensions: "prefer_if_available:fallback"
   879  #       exe {
   880  #         cipd_package: "recipe/bundles/main"
   881  #         cipd_version: "refs/heads/main"
   882  #         cmd: "luciexe"
   883  #         wrapper: "path/to/wrapper"
   884  #       }
   885  #       properties:
   886  #         '{'
   887  #         '  "$recipe_engine/resultdb/test_presentation": {'
   888  #         '    "column_keys": ['
   889  #         '      "v.gpu"'
   890  #         '    ],'
   891  #         '    "grouping_keys": ['
   892  #         '      "status",'
   893  #         '      "v.test_suite"'
   894  #         '    ]'
   895  #         '  },'
   896  #         '  "prop1": "val1",'
   897  #         '  "prop2": ['
   898  #         '    "val2",'
   899  #         '    123'
   900  #         '  ],'
   901  #         '  "recipe": "main/recipe"'
   902  #         '}'
   903  #       allowed_property_overrides: "prop1"
   904  #       priority: 80
   905  #       execution_timeout_secs: 10800
   906  #       heartbeat_timeout_secs: 600
   907  #       expiration_secs: 3600
   908  #       grace_period {
   909  #         seconds: 120
   910  #       }
   911  #       caches {
   912  #         name: "name2"
   913  #         path: "path2"
   914  #       }
   915  #       caches {
   916  #         name: "name3"
   917  #         path: "path3"
   918  #         wait_for_warm_cache_secs: 600
   919  #       }
   920  #       caches {
   921  #         name: "path1"
   922  #         path: "path1"
   923  #       }
   924  #       build_numbers: YES
   925  #       service_account: "builder@example.com"
   926  #       experiments {
   927  #         key: "luci.recipes.use_python3"
   928  #         value: 100
   929  #       }
   930  #       resultdb {
   931  #         enable: true
   932  #         bq_exports {
   933  #           project: "luci-resultdb"
   934  #           dataset: "my-awesome-project"
   935  #           table: "all_test_results"
   936  #           test_results {
   937  #             predicate {
   938  #               test_id_regexp: "ninja:.*"
   939  #               variant {
   940  #                 contains {
   941  #                   def {
   942  #                     key: "test_suite"
   943  #                     value: "super_interesting_suite"
   944  #                   }
   945  #                 }
   946  #               }
   947  #               expectancy: VARIANTS_WITH_UNEXPECTED_RESULTS
   948  #             }
   949  #           }
   950  #         }
   951  #         bq_exports {
   952  #           project: "luci-resultdb"
   953  #           dataset: "my-awesome-project"
   954  #           table: "all_text_artifacts"
   955  #           text_artifacts {
   956  #             predicate {
   957  #               follow_edges {
   958  #                 test_results: true
   959  #               }
   960  #               test_result_predicate {
   961  #                 test_id_regexp: "ninja:.*"
   962  #                 variant {
   963  #                   contains {
   964  #                     def {
   965  #                       key: "test_suite"
   966  #                       value: "super_interesting_suite"
   967  #                     }
   968  #                   }
   969  #                 }
   970  #                 expectancy: VARIANTS_WITH_UNEXPECTED_RESULTS
   971  #               }
   972  #               content_type_regexp: "text.*"
   973  #             }
   974  #           }
   975  #         }
   976  #         history_options {
   977  #           use_invocation_timestamp: true
   978  #         }
   979  #       }
   980  #       description_html: "this is a linux ci builder"
   981  #     }
   982  #     builders {
   983  #       name: "newest first schedule builder"
   984  #       swarming_host: "chromium-swarm.appspot.com"
   985  #       exe {
   986  #         cipd_package: "recipe/bundles/main"
   987  #         cipd_version: "refs/heads/main"
   988  #         cmd: "luciexe"
   989  #         wrapper: "path/to/wrapper"
   990  #       }
   991  #       properties:
   992  #         '{'
   993  #         '  "recipe": "main/recipe"'
   994  #         '}'
   995  #       experiments {
   996  #         key: "luci.recipes.use_python3"
   997  #         value: 100
   998  #       }
   999  #     }
  1000  #     builders {
  1001  #       name: "watched builder"
  1002  #       swarming_host: "chromium-swarm.appspot.com"
  1003  #       exe {
  1004  #         cipd_package: "recipe/bundles/main"
  1005  #         cipd_version: "refs/heads/main"
  1006  #         cmd: "luciexe"
  1007  #         wrapper: "path/to/wrapper"
  1008  #       }
  1009  #       properties:
  1010  #         '{'
  1011  #         '  "recipe": "main/recipe"'
  1012  #         '}'
  1013  #       experiments {
  1014  #         key: "luci.recipes.use_python3"
  1015  #         value: 100
  1016  #       }
  1017  #     }
  1018  #   }
  1019  # }
  1020  # buckets {
  1021  #   name: "inline"
  1022  #   acls {
  1023  #     role: WRITER
  1024  #     group: "admins"
  1025  #   }
  1026  #   acls {
  1027  #     group: "all"
  1028  #   }
  1029  #   swarming {
  1030  #     builders {
  1031  #       name: "another builder"
  1032  #       swarming_host: "chromium-swarm.appspot.com"
  1033  #       exe {
  1034  #         cipd_package: "recipe/bundles/inline"
  1035  #         cipd_version: "refs/heads/main"
  1036  #         cmd: "luciexe"
  1037  #       }
  1038  #       properties:
  1039  #         '{'
  1040  #         '  "recipe": "inline/recipe"'
  1041  #         '}'
  1042  #       service_account: "builder@example.com"
  1043  #     }
  1044  #     builders {
  1045  #       name: "another executable builder"
  1046  #       swarming_host: "chromium-swarm.appspot.com"
  1047  #       exe {
  1048  #         cipd_package: "executable/bundles/inline"
  1049  #         cipd_version: "refs/heads/main"
  1050  #       }
  1051  #       properties: '{}'
  1052  #       service_account: "builder@example.com"
  1053  #     }
  1054  #     builders {
  1055  #       name: "executable builder wrapper"
  1056  #       swarming_host: "chromium-swarm.appspot.com"
  1057  #       exe {
  1058  #         cipd_package: "executable/bundles/inline"
  1059  #         cipd_version: "refs/heads/main"
  1060  #         wrapper: "/path/to/wrapper"
  1061  #       }
  1062  #       properties: '{}'
  1063  #       service_account: "builder@example.com"
  1064  #     }
  1065  #     builders {
  1066  #       name: "triggered builder"
  1067  #       swarming_host: "chromium-swarm.appspot.com"
  1068  #       exe {
  1069  #         cipd_package: "recipe/bundles/inline"
  1070  #         cipd_version: "refs/heads/main"
  1071  #         cmd: "luciexe"
  1072  #       }
  1073  #       properties:
  1074  #         '{'
  1075  #         '  "recipe": "inline/recipe"'
  1076  #         '}'
  1077  #     }
  1078  #     builders {
  1079  #       name: "triggerer builder"
  1080  #       swarming_host: "chromium-swarm.appspot.com"
  1081  #       exe {
  1082  #         cipd_package: "recipe/bundles/inline"
  1083  #         cipd_version: "refs/heads/main"
  1084  #         cmd: "luciexe"
  1085  #       }
  1086  #       properties:
  1087  #         '{'
  1088  #         '  "recipe": "inline/recipe"'
  1089  #         '}'
  1090  #       service_account: "builder@example.com"
  1091  #     }
  1092  #   }
  1093  # }
  1094  # buckets {
  1095  #   name: "try"
  1096  #   acls {
  1097  #     role: WRITER
  1098  #     group: "admins"
  1099  #   }
  1100  #   acls {
  1101  #     group: "all"
  1102  #   }
  1103  #   acls {
  1104  #     role: SCHEDULER
  1105  #     group: "devs"
  1106  #   }
  1107  #   swarming {
  1108  #     builders {
  1109  #       name: "builder with executable"
  1110  #       swarming_host: "chromium-swarm.appspot.com"
  1111  #       exe {
  1112  #         cipd_package: "executable/bundles/main"
  1113  #         cipd_version: "refs/heads/main"
  1114  #         cmd: "cmd"
  1115  #       }
  1116  #       properties: '{}'
  1117  #     }
  1118  #     builders {
  1119  #       name: "builder with experiment map"
  1120  #       swarming_host: "chromium-swarm.appspot.com"
  1121  #       exe {
  1122  #         cipd_package: "executable/bundles/main"
  1123  #         cipd_version: "refs/heads/main"
  1124  #         cmd: "cmd"
  1125  #       }
  1126  #       properties: '{}'
  1127  #       experiments {
  1128  #         key: "luci.enable_new_beta_feature"
  1129  #         value: 32
  1130  #       }
  1131  #     }
  1132  #     builders {
  1133  #       name: "equivalent cq builder"
  1134  #       swarming_host: "chromium-swarm.appspot.com"
  1135  #       exe {
  1136  #         cipd_package: "recipe/bundles/main"
  1137  #         cipd_version: "refs/heads/main"
  1138  #         cmd: "luciexe"
  1139  #         wrapper: "path/to/wrapper"
  1140  #       }
  1141  #       properties:
  1142  #         '{'
  1143  #         '  "recipe": "main/recipe"'
  1144  #         '}'
  1145  #       experiments {
  1146  #         key: "luci.recipes.use_python3"
  1147  #         value: 100
  1148  #       }
  1149  #     }
  1150  #     builders {
  1151  #       name: "generically named builder"
  1152  #       swarming_host: "chromium-swarm.appspot.com"
  1153  #       exe {
  1154  #         cipd_package: "recipe/bundles/main"
  1155  #         cipd_version: "refs/heads/main"
  1156  #         cmd: "luciexe"
  1157  #         wrapper: "path/to/wrapper"
  1158  #       }
  1159  #       properties:
  1160  #         '{'
  1161  #         '  "recipe": "main/recipe"'
  1162  #         '}'
  1163  #       experiments {
  1164  #         key: "luci.recipes.use_python3"
  1165  #         value: 100
  1166  #       }
  1167  #     }
  1168  #     builders {
  1169  #       name: "linux try builder"
  1170  #       swarming_host: "chromium-swarm.appspot.com"
  1171  #       exe {
  1172  #         cipd_package: "recipe/bundles/main"
  1173  #         cipd_version: "refs/heads/main"
  1174  #         cmd: "luciexe"
  1175  #         wrapper: "path/to/wrapper"
  1176  #       }
  1177  #       properties:
  1178  #         '{'
  1179  #         '  "recipe": "main/recipe"'
  1180  #         '}'
  1181  #       experiments {
  1182  #         key: "luci.recipes.use_python3"
  1183  #         value: 100
  1184  #       }
  1185  #     }
  1186  #     builders {
  1187  #       name: "linux try builder 2"
  1188  #       swarming_host: "chromium-swarm.appspot.com"
  1189  #       exe {
  1190  #         cipd_package: "recipe/bundles/main"
  1191  #         cipd_version: "refs/heads/main"
  1192  #         cmd: "luciexe"
  1193  #         wrapper: "path/to/wrapper"
  1194  #       }
  1195  #       properties:
  1196  #         '{'
  1197  #         '  "recipe": "main/recipe"'
  1198  #         '}'
  1199  #       experiments {
  1200  #         key: "luci.recipes.use_python3"
  1201  #         value: 100
  1202  #       }
  1203  #     }
  1204  #     builders {
  1205  #       name: "main cq builder"
  1206  #       swarming_host: "chromium-swarm.appspot.com"
  1207  #       exe {
  1208  #         cipd_package: "recipe/bundles/main"
  1209  #         cipd_version: "refs/heads/main"
  1210  #         cmd: "luciexe"
  1211  #         wrapper: "path/to/wrapper"
  1212  #       }
  1213  #       properties:
  1214  #         '{'
  1215  #         '  "recipe": "main/recipe"'
  1216  #         '}'
  1217  #       experiments {
  1218  #         key: "luci.recipes.use_python3"
  1219  #         value: 100
  1220  #       }
  1221  #     }
  1222  #     builders {
  1223  #       name: "spell-checker"
  1224  #       swarming_host: "chromium-swarm.appspot.com"
  1225  #       exe {
  1226  #         cipd_package: "recipe/bundles/main"
  1227  #         cipd_version: "refs/heads/main"
  1228  #         cmd: "luciexe"
  1229  #         wrapper: "path/to/wrapper"
  1230  #       }
  1231  #       properties:
  1232  #         '{'
  1233  #         '  "recipe": "main/recipe"'
  1234  #         '}'
  1235  #       experiments {
  1236  #         key: "luci.recipes.use_python3"
  1237  #         value: 100
  1238  #       }
  1239  #     }
  1240  #     builders {
  1241  #       name: "website-preview"
  1242  #       swarming_host: "chromium-swarm.appspot.com"
  1243  #       exe {
  1244  #         cipd_package: "recipe/bundles/main"
  1245  #         cipd_version: "refs/heads/main"
  1246  #         cmd: "luciexe"
  1247  #         wrapper: "path/to/wrapper"
  1248  #       }
  1249  #       properties:
  1250  #         '{'
  1251  #         '  "recipe": "main/recipe"'
  1252  #         '}'
  1253  #       experiments {
  1254  #         key: "luci.recipes.use_python3"
  1255  #         value: 100
  1256  #       }
  1257  #     }
  1258  #   }
  1259  # }
  1260  # common_config {
  1261  #   builds_notification_topics {
  1262  #     name: "projects/my-cloud-project1/topics/my-topic1"
  1263  #   }
  1264  #   builds_notification_topics {
  1265  #     name: "projects/my-cloud-project2/topics/my-topic2"
  1266  #     compression: ZSTD
  1267  #   }
  1268  # }
  1269  # ===
  1270  #
  1271  # === dir/custom.cfg
  1272  # hello!
  1273  # ===
  1274  #
  1275  # === luci-logdog.cfg
  1276  # reader_auth_groups: "all"
  1277  # archive_gs_bucket: "chromium-luci-logdog"
  1278  # cloud_logging_config {
  1279  #   destination: "chromium-build-logs"
  1280  # }
  1281  # ===
  1282  #
  1283  # === luci-milo.cfg
  1284  # consoles {
  1285  #   id: "List view"
  1286  #   name: "List view"
  1287  #   builders {
  1288  #     name: "buildbucket/luci.infra.ci/cron builder"
  1289  #   }
  1290  #   builders {
  1291  #     name: "buildbucket/luci.infra.ci/generically named builder"
  1292  #   }
  1293  #   builders {
  1294  #     name: "buildbucket/luci.infra.ci/linux ci builder"
  1295  #   }
  1296  #   builders {
  1297  #     name: "buildbucket/luci.infra.inline/triggered builder"
  1298  #   }
  1299  #   favicon_url: "https://storage.googleapis.com/chrome-infra-public/logo/favicon.ico"
  1300  #   builder_view_only: true
  1301  # }
  1302  # consoles {
  1303  #   id: "Console view"
  1304  #   name: "CI Builders"
  1305  #   repo_url: "https://noop.com"
  1306  #   refs: "regexp:refs/tags/blah"
  1307  #   refs: "regexp:refs/branch-heads/\\d+\\.\\d+"
  1308  #   exclude_ref: "refs/heads/main"
  1309  #   manifest_name: "REVISION"
  1310  #   builders {
  1311  #     name: "buildbucket/luci.infra.ci/linux ci builder"
  1312  #     category: "a|b"
  1313  #     short_name: "lnx"
  1314  #   }
  1315  #   builders {
  1316  #     name: "buildbucket/luci.infra.ci/cron builder"
  1317  #     category: "cron"
  1318  #   }
  1319  #   builders {
  1320  #     name: "buildbucket/luci.infra.inline/triggered builder"
  1321  #   }
  1322  #   favicon_url: "https://storage.googleapis.com/chrome-infra-public/logo/favicon.ico"
  1323  #   header {
  1324  #     links {
  1325  #       name: "a"
  1326  #       links {
  1327  #         text: "a"
  1328  #       }
  1329  #     }
  1330  #     links {
  1331  #       name: "b"
  1332  #       links {
  1333  #         text: "b"
  1334  #       }
  1335  #     }
  1336  #   }
  1337  #   include_experimental_builds: true
  1338  #   default_commit_limit: 3
  1339  #   default_expand: true
  1340  # }
  1341  # consoles {
  1342  #   id: "external-console"
  1343  #   name: "External console"
  1344  #   external_project: "chromium"
  1345  #   external_id: "main"
  1346  # }
  1347  # logo_url: "https://storage.googleapis.com/chrome-infra-public/logo/chrome-infra-logo-200x200.png"
  1348  # bug_url_template: "https://bugs.chromium.org/p/tutu%2C%20all%20aboard/issues/entry?summary=Bug%20summary&description=Everything%20is%20broken&components=Stuff%3EHard"
  1349  # ===
  1350  #
  1351  # === luci-notify.cfg
  1352  # notifiers {
  1353  #   notifications {
  1354  #     on_new_status: FAILURE
  1355  #     email {
  1356  #       recipients: "someone@example,com"
  1357  #     }
  1358  #     template: "notifier_template"
  1359  #     notify_blamelist {}
  1360  #   }
  1361  #   builders {
  1362  #     bucket: "ci"
  1363  #     name: "cron builder"
  1364  #     repository: "https://cron.repo.example.com"
  1365  #   }
  1366  # }
  1367  # notifiers {
  1368  #   notifications {
  1369  #     on_new_status: FAILURE
  1370  #     email {
  1371  #       recipients: "someone@example,com"
  1372  #     }
  1373  #     template: "notifier_template"
  1374  #     notify_blamelist {}
  1375  #   }
  1376  #   builders {
  1377  #     bucket: "ci"
  1378  #     name: "linux ci builder"
  1379  #     repository: "https://noop.com"
  1380  #   }
  1381  # }
  1382  # notifiers {
  1383  #   notifications {
  1384  #     on_new_status: FAILURE
  1385  #     email {
  1386  #       recipients: "someone@example,com"
  1387  #     }
  1388  #     template: "notifier_template"
  1389  #     notify_blamelist {}
  1390  #   }
  1391  #   builders {
  1392  #     bucket: "ci"
  1393  #     name: "watched builder"
  1394  #     repository: "https://custom.example.com/repo"
  1395  #   }
  1396  # }
  1397  # ===
  1398  #
  1399  # === luci-notify/email-templates/another_template.template
  1400  # Boo!
  1401  # ===
  1402  #
  1403  # === luci-notify/email-templates/notifier_template.template
  1404  # Hello
  1405  #
  1406  # Hi
  1407  # ===
  1408  #
  1409  # === luci-scheduler.cfg
  1410  # job {
  1411  #   id: "another builder"
  1412  #   realm: "inline"
  1413  #   acl_sets: "inline"
  1414  #   buildbucket {
  1415  #     server: "cr-buildbucket.appspot.com"
  1416  #     bucket: "luci.infra.inline"
  1417  #     builder: "another builder"
  1418  #   }
  1419  # }
  1420  # job {
  1421  #   id: "another executable builder"
  1422  #   realm: "inline"
  1423  #   acl_sets: "inline"
  1424  #   buildbucket {
  1425  #     server: "cr-buildbucket.appspot.com"
  1426  #     bucket: "luci.infra.inline"
  1427  #     builder: "another executable builder"
  1428  #   }
  1429  # }
  1430  # job {
  1431  #   id: "cron builder"
  1432  #   realm: "ci"
  1433  #   schedule: "0 6 * * *"
  1434  #   acl_sets: "ci"
  1435  #   buildbucket {
  1436  #     server: "cr-buildbucket.appspot.com"
  1437  #     bucket: "luci.infra.ci"
  1438  #     builder: "cron builder"
  1439  #   }
  1440  # }
  1441  # job {
  1442  #   id: "generically named builder"
  1443  #   realm: "ci"
  1444  #   acls {
  1445  #     role: TRIGGERER
  1446  #     granted_to: "builder@example.com"
  1447  #   }
  1448  #   acl_sets: "ci"
  1449  #   buildbucket {
  1450  #     server: "cr-buildbucket.appspot.com"
  1451  #     bucket: "luci.infra.ci"
  1452  #     builder: "generically named builder"
  1453  #   }
  1454  # }
  1455  # job {
  1456  #   id: "generically named executable builder"
  1457  #   realm: "ci"
  1458  #   acls {
  1459  #     role: TRIGGERER
  1460  #     granted_to: "builder@example.com"
  1461  #   }
  1462  #   acl_sets: "ci"
  1463  #   buildbucket {
  1464  #     server: "cr-buildbucket.appspot.com"
  1465  #     bucket: "luci.infra.ci"
  1466  #     builder: "generically named executable builder"
  1467  #   }
  1468  # }
  1469  # job {
  1470  #   id: "linux ci builder"
  1471  #   realm: "ci"
  1472  #   acl_sets: "ci"
  1473  #   triggering_policy {
  1474  #     kind: GREEDY_BATCHING
  1475  #     max_concurrent_invocations: 5
  1476  #     max_batch_size: 10
  1477  #   }
  1478  #   buildbucket {
  1479  #     server: "cr-buildbucket.appspot.com"
  1480  #     bucket: "luci.infra.ci"
  1481  #     builder: "linux ci builder"
  1482  #   }
  1483  # }
  1484  # job {
  1485  #   id: "newest first schedule builder"
  1486  #   realm: "ci"
  1487  #   acl_sets: "ci"
  1488  #   triggering_policy {
  1489  #     kind: NEWEST_FIRST
  1490  #     max_concurrent_invocations: 2
  1491  #     pending_timeout {
  1492  #       seconds: 259200
  1493  #     }
  1494  #   }
  1495  #   buildbucket {
  1496  #     server: "cr-buildbucket.appspot.com"
  1497  #     bucket: "luci.infra.ci"
  1498  #     builder: "newest first schedule builder"
  1499  #   }
  1500  # }
  1501  # job {
  1502  #   id: "triggered builder"
  1503  #   realm: "inline"
  1504  #   acls {
  1505  #     role: TRIGGERER
  1506  #     granted_to: "builder@example.com"
  1507  #   }
  1508  #   acl_sets: "inline"
  1509  #   buildbucket {
  1510  #     server: "cr-buildbucket.appspot.com"
  1511  #     bucket: "luci.infra.inline"
  1512  #     builder: "triggered builder"
  1513  #   }
  1514  # }
  1515  # job {
  1516  #   id: "triggerer builder"
  1517  #   realm: "inline"
  1518  #   acl_sets: "inline"
  1519  #   buildbucket {
  1520  #     server: "cr-buildbucket.appspot.com"
  1521  #     bucket: "luci.infra.inline"
  1522  #     builder: "triggerer builder"
  1523  #   }
  1524  # }
  1525  # trigger {
  1526  #   id: "inline poller"
  1527  #   realm: "inline"
  1528  #   schedule: "with 10s interval"
  1529  #   acl_sets: "inline"
  1530  #   triggers: "another builder"
  1531  #   triggers: "another executable builder"
  1532  #   triggers: "triggerer builder"
  1533  #   gitiles {
  1534  #     repo: "https://noop.com"
  1535  #     refs: "regexp:refs/heads/main"
  1536  #     refs: "regexp:refs/tags/blah"
  1537  #     refs: "regexp:refs/branch-heads/\\d+\\.\\d+"
  1538  #   }
  1539  # }
  1540  # trigger {
  1541  #   id: "main-poller"
  1542  #   realm: "ci"
  1543  #   schedule: "with 10s interval"
  1544  #   acl_sets: "ci"
  1545  #   triggers: "generically named builder"
  1546  #   triggers: "generically named executable builder"
  1547  #   triggers: "linux ci builder"
  1548  #   gitiles {
  1549  #     repo: "https://noop.com"
  1550  #     refs: "regexp:refs/heads/main"
  1551  #     refs: "regexp:refs/tags/blah"
  1552  #     refs: "regexp:refs/branch-heads/\\d+\\.\\d+"
  1553  #     path_regexps: ".*"
  1554  #     path_regexps_exclude: "excluded"
  1555  #   }
  1556  # }
  1557  # acl_sets {
  1558  #   name: "ci"
  1559  #   acls {
  1560  #     role: OWNER
  1561  #     granted_to: "group:admins"
  1562  #   }
  1563  #   acls {
  1564  #     granted_to: "group:all"
  1565  #   }
  1566  #   acls {
  1567  #     role: TRIGGERER
  1568  #     granted_to: "group:devs"
  1569  #   }
  1570  #   acls {
  1571  #     role: TRIGGERER
  1572  #     granted_to: "project:some-project"
  1573  #   }
  1574  # }
  1575  # acl_sets {
  1576  #   name: "inline"
  1577  #   acls {
  1578  #     role: OWNER
  1579  #     granted_to: "group:admins"
  1580  #   }
  1581  #   acls {
  1582  #     granted_to: "group:all"
  1583  #   }
  1584  # }
  1585  # ===
  1586  #
  1587  # === project.cfg
  1588  # name: "infra"
  1589  # access: "group:all"
  1590  # ===
  1591  #
  1592  # === realms.cfg
  1593  # realms {
  1594  #   name: "@root"
  1595  #   bindings {
  1596  #     role: "role/buildbucket.owner"
  1597  #     principals: "group:admins"
  1598  #   }
  1599  #   bindings {
  1600  #     role: "role/buildbucket.reader"
  1601  #     principals: "group:all"
  1602  #   }
  1603  #   bindings {
  1604  #     role: "role/configs.reader"
  1605  #     principals: "group:all"
  1606  #   }
  1607  #   bindings {
  1608  #     role: "role/cq.committer"
  1609  #     principals: "group:admins"
  1610  #   }
  1611  #   bindings {
  1612  #     role: "role/logdog.reader"
  1613  #     principals: "group:all"
  1614  #   }
  1615  #   bindings {
  1616  #     role: "role/scheduler.owner"
  1617  #     principals: "group:admins"
  1618  #   }
  1619  #   bindings {
  1620  #     role: "role/scheduler.reader"
  1621  #     principals: "group:all"
  1622  #   }
  1623  # }
  1624  # realms {
  1625  #   name: "ci"
  1626  #   bindings {
  1627  #     role: "role/buildbucket.builderServiceAccount"
  1628  #     principals: "user:builder@example.com"
  1629  #   }
  1630  #   bindings {
  1631  #     role: "role/scheduler.triggerer"
  1632  #     principals: "group:devs"
  1633  #     principals: "project:some-project"
  1634  #   }
  1635  # }
  1636  # realms {
  1637  #   name: "inline"
  1638  #   bindings {
  1639  #     role: "role/buildbucket.builderServiceAccount"
  1640  #     principals: "user:builder@example.com"
  1641  #   }
  1642  # }
  1643  # realms {
  1644  #   name: "try"
  1645  #   bindings {
  1646  #     role: "role/buildbucket.triggerer"
  1647  #     principals: "group:devs"
  1648  #   }
  1649  # }
  1650  # ===
  1651  #
  1652  # === tricium-prod.cfg
  1653  # functions {
  1654  #   type: ANALYZER
  1655  #   name: "AnotherProjectAnalyzerFormatChecker"
  1656  #   needs: GIT_FILE_DETAILS
  1657  #   provides: RESULTS
  1658  #   path_filters: "*.X4"
  1659  #   path_filters: "*.go"
  1660  #   path_filters: "*.py"
  1661  #   impls {
  1662  #     provides_for_platform: LINUX
  1663  #     runtime_platform: LINUX
  1664  #     recipe {
  1665  #       project: "another-project"
  1666  #       bucket: "analyzer"
  1667  #       builder: "format checker"
  1668  #     }
  1669  #   }
  1670  # }
  1671  # functions {
  1672  #   type: ANALYZER
  1673  #   name: "InfraTrySpellChecker"
  1674  #   needs: GIT_FILE_DETAILS
  1675  #   provides: RESULTS
  1676  #   impls {
  1677  #     provides_for_platform: LINUX
  1678  #     runtime_platform: LINUX
  1679  #     recipe {
  1680  #       project: "infra"
  1681  #       bucket: "try"
  1682  #       builder: "spell-checker"
  1683  #     }
  1684  #   }
  1685  # }
  1686  # selections {
  1687  #   function: "AnotherProjectAnalyzerFormatChecker"
  1688  #   platform: LINUX
  1689  # }
  1690  # selections {
  1691  #   function: "InfraTrySpellChecker"
  1692  #   platform: LINUX
  1693  # }
  1694  # repos {
  1695  #   gerrit_project {
  1696  #     host: "example-review.googlesource.com"
  1697  #     project: "another/repo"
  1698  #     git_url: "https://example.googlesource.com/another/repo"
  1699  #   }
  1700  #   whitelisted_group: "project-contributor"
  1701  #   check_all_revision_kinds: true
  1702  # }
  1703  # repos {
  1704  #   gerrit_project {
  1705  #     host: "example-review.googlesource.com"
  1706  #     project: "repo"
  1707  #     git_url: "https://example.googlesource.com/repo"
  1708  #   }
  1709  #   whitelisted_group: "project-contributor"
  1710  #   check_all_revision_kinds: true
  1711  # }
  1712  # service_account: "tricium-prod@appspot.gserviceaccount.com"
  1713  # ===