blob: 471450f2886ef2d22fb8db5a4ae2d7d097f33575 [file] [log] [blame]
Don Garrettbe3608b2018-06-05 17:10:09 -07001# Copyright 2018 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Don Garrettff45f4b2018-10-04 09:08:01 -07005# pylint: disable=line-too-long
Don Garrettbe3608b2018-06-05 17:10:09 -07006"""Generate LUCI Scheduler config file.
7
8This generates the LUCI Scheduler configuration file for ChromeOS builds based
9on the chromeos_config contents.
10
Don Garrettff45f4b2018-10-04 09:08:01 -070011Changes to chromite/config/luci-scheduler.cfg will be autodeployed:
Mike Nicholsb575c612021-04-09 10:04:43 -060012 https://data.corp.google.com/sites/chromeos_ci_cros_ci_builds/utility/?f=board_name:in:luci-scheduler-updater
Don Garrettbe3608b2018-06-05 17:10:09 -070013
Don Garrettc8323dc2018-08-22 15:58:26 -070014Notes:
15 Normal builds are scheduled based on the builder values for
16 'schedule' and 'triggered_gitiles' in config/chromeos_config.py.
17
18 Branched builds are scheduled based on the function
19 chromeos_config.BranchScheduleConfig()
Don Garrettbe3608b2018-06-05 17:10:09 -070020"""
Don Garrettff45f4b2018-10-04 09:08:01 -070021# pylint: enable=line-too-long
Don Garrettbe3608b2018-06-05 17:10:09 -070022
Don Garrettbe3608b2018-06-05 17:10:09 -070023import sys
24
Don Garrett8dace272018-07-19 14:07:42 -070025from chromite.config import chromeos_config
Don Garrettbe3608b2018-06-05 17:10:09 -070026from chromite.lib import commandline
27from chromite.lib import config_lib
28
29
30_CONFIG_HEADER = """# Defines buckets on luci-scheduler.appspot.com.
31#
32# For schema of this file and documentation see ProjectConfig message in
Mike Frysinger92dc6492021-02-17 16:01:09 -050033# https://github.com/luci/luci-go/blob/HEAD/scheduler/appengine/messages/config.proto
Don Garrettbe3608b2018-06-05 17:10:09 -070034
35# Generated with chromite/scripts/gen_luci_scheduler
36
Don Garrettff45f4b2018-10-04 09:08:01 -070037# Autodeployed with:
Mike Nicholsb575c612021-04-09 10:04:43 -060038# https://data.corp.google.com/sites/chromeos_ci_cros_ci_builds/utility/?f=board_name:in:luci-scheduler-updater
Don Garrettff45f4b2018-10-04 09:08:01 -070039
Don Garrettbe3608b2018-06-05 17:10:09 -070040acl_sets {
41 name: "default"
42 acls {
43 role: READER
44 granted_to: "group:googlers"
45 }
46 acls {
47 role: OWNER
48 granted_to: "group:project-chromeos-admins"
49 }
Jason D. Clintona9e374a2018-10-18 18:41:00 -060050 acls {
51 role: TRIGGERER
52 granted_to: "group:mdb/chromeos-build-access"
LaMont Jones48ddfd92020-09-16 13:46:41 -060053 }
54 acls {
55 role: TRIGGERER
LaMont Jonesd1bb0002020-09-16 09:35:10 -060056 granted_to: "group:project-chromeos-buildbucket-schedulers"
Jason D. Clintona9e374a2018-10-18 18:41:00 -060057 }
Don Garrettbe3608b2018-06-05 17:10:09 -070058}
59"""
60
Alex Klein1699fab2022-09-08 08:46:06 -060061
Don Garrett9a0d90c2018-10-30 12:47:14 -070062def buildJobName(build_config):
Alex Klein1699fab2022-09-08 08:46:06 -060063 if "schedule_branch" in build_config:
64 return "%s-%s" % (build_config.schedule_branch, build_config.name)
65 else:
66 return build_config.name
Don Garrett9a0d90c2018-10-30 12:47:14 -070067
Don Garrettbe3608b2018-06-05 17:10:09 -070068
69def genSchedulerJob(build_config):
Alex Klein1699fab2022-09-08 08:46:06 -060070 """Generate the luci scheduler job for a given build config.
Don Garrettbe3608b2018-06-05 17:10:09 -070071
Alex Klein1699fab2022-09-08 08:46:06 -060072 Args:
73 build_config: config_lib.BuildConfig.
Don Garrettbe3608b2018-06-05 17:10:09 -070074
Alex Klein1699fab2022-09-08 08:46:06 -060075 Returns:
76 Multiline string to include in the luci scheduler configuration.
77 """
78 job_name = buildJobName(build_config)
79 if "schedule_branch" in build_config:
80 branch = build_config.schedule_branch
81 else:
82 branch = "main"
Don Garrett73148e52018-08-17 16:54:46 -070083
Alex Klein1699fab2022-09-08 08:46:06 -060084 tags = {
85 "cbb_branch": branch,
86 "cbb_config": build_config.name,
87 "cbb_display_label": build_config.display_label,
88 "cbb_workspace_branch": build_config.workspace_branch,
89 "cbb_goma_client_type": build_config.goma_client_type,
90 }
Don Garrett73148e52018-08-17 16:54:46 -070091
Alex Klein1699fab2022-09-08 08:46:06 -060092 # Filter out tags with no value set.
93 tags = {k: v for k, v in tags.items() if v}
Don Garrett73148e52018-08-17 16:54:46 -070094
Alex Klein1699fab2022-09-08 08:46:06 -060095 tag_lines = [
96 ' tags: "%s:%s"' % (k, tags[k]) for k in sorted(tags.keys())
97 ]
98 prop_lines = [
99 ' properties: "%s:%s"' % (k, tags[k]) for k in sorted(tags.keys())
100 ]
Don Garrett73148e52018-08-17 16:54:46 -0700101
Alex Klein1699fab2022-09-08 08:46:06 -0600102 # TODO: Move --buildbot arg into recipe, and remove from here.
103 template = """
Don Garrettbe3608b2018-06-05 17:10:09 -0700104job {
Don Garrett8dace272018-07-19 14:07:42 -0700105 id: "%(job_name)s"
Vadim Shtayura6398e002021-01-11 12:02:11 -0800106 realm: "cbb-jobs"
Don Garrettbe3608b2018-06-05 17:10:09 -0700107 acl_sets: "default"
108 schedule: "%(schedule)s"
109 buildbucket: {
110 server: "cr-buildbucket.appspot.com"
Vadim Shtayura959cb0f2022-02-03 12:45:58 -0800111 bucket: "general"
Don Garrettbe3608b2018-06-05 17:10:09 -0700112 builder: "%(builder)s"
Don Garrett73148e52018-08-17 16:54:46 -0700113%(tag_lines)s
114%(prop_lines)s
Don Garrettbe3608b2018-06-05 17:10:09 -0700115 properties: "cbb_extra_args:[\\"--buildbot\\"]"
116 }
117}
118"""
Don Garrett8dace272018-07-19 14:07:42 -0700119
Alex Klein1699fab2022-09-08 08:46:06 -0600120 return template % {
121 "job_name": job_name,
122 "builder": build_config.luci_builder,
123 "schedule": build_config.schedule,
124 "tag_lines": "\n".join(tag_lines),
125 "prop_lines": "\n".join(prop_lines),
126 }
Don Garrettbe3608b2018-06-05 17:10:09 -0700127
128
David Burgercba0d272020-06-24 16:21:26 -0600129def genSchedulerTrigger(trigger_name, repo, refs, path_regexps, builds):
Alex Klein1699fab2022-09-08 08:46:06 -0600130 """Generate the luci scheduler job for a given build config.
Don Garrettbe3608b2018-06-05 17:10:09 -0700131
Alex Klein1699fab2022-09-08 08:46:06 -0600132 Args:
133 trigger_name: Name of the trigger as a string.
134 repo: Gitiles URL git git repository.
135 refs: Iterable of git refs to check. May use regular expressions.
136 path_regexps: Iterable of path regular expressions of files to trigger on
137 or falsy to trigger on everything.
138 builds: Iterable of build config names to trigger.
Don Garrettbe3608b2018-06-05 17:10:09 -0700139
Alex Klein1699fab2022-09-08 08:46:06 -0600140 Returns:
141 Multiline string to include in the luci scheduler configuration.
142 """
143 template = """
Don Garrettbe3608b2018-06-05 17:10:09 -0700144trigger {
145 id: "%(trigger_name)s"
Vadim Shtayura6398e002021-01-11 12:02:11 -0800146 realm: "cbb-jobs"
Don Garrettbe3608b2018-06-05 17:10:09 -0700147 acl_sets: "default"
148 schedule: "with 5m interval"
149 gitiles: {
150 repo: "%(repo)s"
David Burgercba0d272020-06-24 16:21:26 -0600151%(refs)s%(path_regexps)s
Don Garrettbe3608b2018-06-05 17:10:09 -0700152 }
153%(triggers)s
154}
155"""
Alex Klein1699fab2022-09-08 08:46:06 -0600156 if path_regexps:
157 path_regexps = "\n" + "\n".join(
158 ' path_regexps: "%s"' % r for r in path_regexps
159 )
160 else:
161 path_regexps = ""
162 return template % {
163 "trigger_name": trigger_name,
164 "repo": repo,
165 "refs": "\n".join(' refs: "%s"' % r for r in refs),
166 "path_regexps": path_regexps,
167 "triggers": "\n".join(' triggers: "%s"' % b for b in builds),
168 }
Don Garrettbe3608b2018-06-05 17:10:09 -0700169
170
Don Garrett8dace272018-07-19 14:07:42 -0700171def genLuciSchedulerConfig(site_config, branch_config):
Alex Klein1699fab2022-09-08 08:46:06 -0600172 """Generate a luciSchedulerConfig as a string.
Don Garrettbe3608b2018-06-05 17:10:09 -0700173
Alex Klein1699fab2022-09-08 08:46:06 -0600174 Args:
175 site_config: A config_lib.SiteConfig instance.
176 branch_config: A list of BuildConfig instances to schedule.
Don Garrettbe3608b2018-06-05 17:10:09 -0700177
Alex Klein1699fab2022-09-08 08:46:06 -0600178 Returns:
179 The complete scheduler configuration contents as a string.
180 """
181 # Trigger collection is used to collect together trigger information, so
182 # we can reuse the same trigger for multiple builds as needed.
183 # It maps gitiles_key to a set of build_names.
184 # A gitiles_key = (gitiles_url, tuple(ref_list))
185 trigger_collection = {}
Don Garrettbe3608b2018-06-05 17:10:09 -0700186
Alex Klein1699fab2022-09-08 08:46:06 -0600187 jobs = []
Don Garrettbe3608b2018-06-05 17:10:09 -0700188
Alex Klein1699fab2022-09-08 08:46:06 -0600189 # Order the configs consistently.
190 configs = [
191 site_config[name] for name in sorted(site_config)
192 ] + branch_config
Don Garrett8dace272018-07-19 14:07:42 -0700193
Alex Klein1699fab2022-09-08 08:46:06 -0600194 for config in configs:
195 # Populate jobs.
196 if config.schedule:
197 jobs.append(genSchedulerJob(config))
Don Garrettbe3608b2018-06-05 17:10:09 -0700198
Alex Klein1699fab2022-09-08 08:46:06 -0600199 # Populate trigger_collection.
200 if config.triggered_gitiles:
201 for trigger in config.triggered_gitiles:
202 try:
203 gitiles_url, ref_list, path_regexps = trigger
204 except ValueError:
205 gitiles_url, ref_list = trigger
206 path_regexps = []
207 gitiles_key = (
208 gitiles_url,
209 tuple(ref_list),
210 tuple(path_regexps),
211 )
212 trigger_collection.setdefault(gitiles_key, set())
213 trigger_collection[gitiles_key].add(buildJobName(config))
Don Garrettbe3608b2018-06-05 17:10:09 -0700214
Alex Klein1699fab2022-09-08 08:46:06 -0600215 # Populate triggers.
216 triggers = []
217 trigger_counter = 0
218 for gitiles_key in sorted(trigger_collection):
219 builds = sorted(trigger_collection[gitiles_key])
Don Garrettbe3608b2018-06-05 17:10:09 -0700220
Alex Klein1699fab2022-09-08 08:46:06 -0600221 trigger_name = "trigger_%s" % trigger_counter
222 gitiles_url, refs, path_regexps = gitiles_key
223 triggers.append(
224 genSchedulerTrigger(
225 trigger_name, gitiles_url, refs, path_regexps, builds
226 )
227 )
228 trigger_counter += 1
Don Garrettbe3608b2018-06-05 17:10:09 -0700229
Alex Klein1699fab2022-09-08 08:46:06 -0600230 return "".join([_CONFIG_HEADER] + triggers + jobs)
Don Garrettbe3608b2018-06-05 17:10:09 -0700231
232
233def GetParser():
Alex Klein1699fab2022-09-08 08:46:06 -0600234 """Creates the argparse parser."""
235 parser = commandline.ArgumentParser(description=__doc__)
Don Garrettbe3608b2018-06-05 17:10:09 -0700236
Alex Klein1699fab2022-09-08 08:46:06 -0600237 parser.add_argument(
238 "-o", "--file_out", type="path", help="Write output to specified file."
239 )
Don Garrettbe3608b2018-06-05 17:10:09 -0700240
Alex Klein1699fab2022-09-08 08:46:06 -0600241 return parser
Don Garrettbe3608b2018-06-05 17:10:09 -0700242
243
244def main(argv):
Alex Klein1699fab2022-09-08 08:46:06 -0600245 parser = GetParser()
246 options = parser.parse_args(argv)
247 options.Freeze()
Don Garrettbe3608b2018-06-05 17:10:09 -0700248
Alex Klein1699fab2022-09-08 08:46:06 -0600249 site_config = config_lib.GetConfig()
250 branch_config = chromeos_config.BranchScheduleConfig()
Don Garrettbe3608b2018-06-05 17:10:09 -0700251
Alex Klein1699fab2022-09-08 08:46:06 -0600252 with (
253 open(options.file_out, "w") if options.file_out else sys.stdout
254 ) as fh:
255 fh.write(genLuciSchedulerConfig(site_config, branch_config))