blob: b3e98767c2b806c916225e61152caee42e711957 [file] [log] [blame]
Don Garrettbe3608b2018-06-05 17:10:09 -07001# -*- coding: utf-8 -*-
2# Copyright 2018 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Generate LUCI Scheduler config file.
7
8This generates the LUCI Scheduler configuration file for ChromeOS builds based
9on the chromeos_config contents.
10
11To update the production config:
12 cd $REPO/manifest-internal
13 git checkout infra/config
14 $REPO/chromite/scripts/gen_luci_scheduler > luci-scheduler.cfg
15 git commit -a
16 git cl upload (yes, really) (Say Yes to removing commit-msg hook)
17 repo abandon infra/config
18
Don Garrettc8323dc2018-08-22 15:58:26 -070019Notes:
20 Normal builds are scheduled based on the builder values for
21 'schedule' and 'triggered_gitiles' in config/chromeos_config.py.
22
23 Branched builds are scheduled based on the function
24 chromeos_config.BranchScheduleConfig()
Don Garrettbe3608b2018-06-05 17:10:09 -070025"""
26
27from __future__ import print_function
28
29import sys
30
Don Garrett8dace272018-07-19 14:07:42 -070031from chromite.config import chromeos_config
Don Garrettbe3608b2018-06-05 17:10:09 -070032from chromite.lib import commandline
33from chromite.lib import config_lib
34
35
36_CONFIG_HEADER = """# Defines buckets on luci-scheduler.appspot.com.
37#
38# For schema of this file and documentation see ProjectConfig message in
39# https://github.com/luci/luci-go/blob/master/scheduler/appengine/messages/config.proto
40
41# Generated with chromite/scripts/gen_luci_scheduler
42
43acl_sets {
44 name: "default"
45 acls {
46 role: READER
47 granted_to: "group:googlers"
48 }
49 acls {
50 role: OWNER
51 granted_to: "group:project-chromeos-admins"
52 }
53}
54"""
55
56
57def genSchedulerJob(build_config):
58 """Generate the luci scheduler job for a given build config.
59
60 Args:
61 build_config: config_lib.BuildConfig.
62
63 Returns:
64 Multiline string to include in the luci scheduler configuration.
65 """
66 # TODO: Move --buildbot arg into recipe, and remove from here.
67 template = """
68job {
Don Garrett8dace272018-07-19 14:07:42 -070069 id: "%(job_name)s"
Don Garrettbe3608b2018-06-05 17:10:09 -070070 acl_sets: "default"
71 schedule: "%(schedule)s"
72 buildbucket: {
73 server: "cr-buildbucket.appspot.com"
74 bucket: "luci.chromeos.general"
75 builder: "%(builder)s"
76 tags: "cbb_branch:%(branch)s"
77 tags: "cbb_display_label:%(display_label)s"
78 tags: "cbb_config:%(name)s"
79 properties: "cbb_branch:%(branch)s"
80 properties: "cbb_display_label:%(display_label)s"
81 properties: "cbb_config:%(name)s"
82 properties: "cbb_extra_args:[\\"--buildbot\\"]"
83 }
84}
85"""
Don Garrett8dace272018-07-19 14:07:42 -070086 if 'schedule_branch' in build_config:
87 branch = build_config.schedule_branch
88 job_name = '%s-%s' % (branch, build_config.name)
89 else:
90 branch = 'master'
91 job_name = build_config.name
92
Don Garrettbe3608b2018-06-05 17:10:09 -070093 return template % {
Don Garrett8dace272018-07-19 14:07:42 -070094 'job_name': job_name,
Don Garrettbe3608b2018-06-05 17:10:09 -070095 'name': build_config.name,
96 'builder': build_config.luci_builder,
Don Garrett8dace272018-07-19 14:07:42 -070097 'branch': branch,
Don Garrettbe3608b2018-06-05 17:10:09 -070098 'display_label': build_config.display_label,
99 'schedule': build_config.schedule,
100 }
101
102
103def genSchedulerTrigger(trigger_name, repo, refs, builds):
104 """Generate the luci scheduler job for a given build config.
105
106 Args:
107 trigger_name: Name of the trigger as a string.
108 repo: Gitiles URL git git repository.
109 refs: Iterable of git refs to check. May use regular expressions.
110 builds: Iterable of build config names to trigger.
111
112 Returns:
113 Multiline string to include in the luci scheduler configuration.
114 """
115 template = """
116trigger {
117 id: "%(trigger_name)s"
118 acl_sets: "default"
119 schedule: "with 5m interval"
120 gitiles: {
121 repo: "%(repo)s"
122%(refs)s
123 }
124%(triggers)s
125}
126"""
127
128 return template % {
129 'trigger_name': trigger_name,
130 'repo': repo,
131 'refs': '\n'.join(' refs: "%s"' % r for r in refs),
132 'triggers': '\n'.join(' triggers: "%s"' % b for b in builds),
133 }
134
135
Don Garrett8dace272018-07-19 14:07:42 -0700136def genLuciSchedulerConfig(site_config, branch_config):
Don Garrettbe3608b2018-06-05 17:10:09 -0700137 """Generate a luciSchedulerConfig as a string.
138
139 Args:
140 site_config: A config_lib.SiteConfig instance.
Don Garrett8dace272018-07-19 14:07:42 -0700141 branch_config: A list of BuildConfig instances to schedule.
Don Garrettbe3608b2018-06-05 17:10:09 -0700142
143 Returns:
144 The complete scheduler configuration contents as a string.
145 """
146 # Trigger collection is used to collect together trigger information, so
147 # we can reuse the same trigger for multiple builds as needed.
148 # It maps gitiles_key to a set of build_names.
149 # A gitiles_key = (gitiles_url, tuple(ref_list))
150 trigger_collection = {}
151
152 jobs = []
Don Garrettbe3608b2018-06-05 17:10:09 -0700153
Don Garrett8dace272018-07-19 14:07:42 -0700154 # Order the configs consistently.
155 configs = [site_config[name] for name in sorted(site_config)] + branch_config
156
157 for config in configs:
Don Garrettbe3608b2018-06-05 17:10:09 -0700158 # Populate jobs.
159 if config.schedule:
160 jobs.append(genSchedulerJob(config))
161
162 # Populate trigger_collection.
163 if config.triggered_gitiles:
164 for gitiles_url, ref_list in config.triggered_gitiles:
165 gitiles_key = (gitiles_url, tuple(ref_list))
166 trigger_collection.setdefault(gitiles_key, set())
167 trigger_collection[gitiles_key].add(config.name)
168
169 # Populate triggers.
170 triggers = []
171 trigger_counter = 0
172 for gitiles_key in sorted(trigger_collection):
173 builds = sorted(trigger_collection[gitiles_key])
174
175 trigger_name = 'trigger_%s' % trigger_counter
176 gitiles_url, refs = gitiles_key
177 triggers.append(genSchedulerTrigger(
178 trigger_name, gitiles_url, refs, builds))
179 trigger_counter += 1
180
181 return ''.join([_CONFIG_HEADER] + triggers + jobs)
182
183
184def GetParser():
185 """Creates the argparse parser."""
186 parser = commandline.ArgumentParser(description=__doc__)
187
188 parser.add_argument('-o', '--file_out', type='path',
189 help='Write output to specified file.')
190
191 return parser
192
193
194def main(argv):
195 parser = GetParser()
196 options = parser.parse_args(argv)
197 options.Freeze()
198
199 site_config = config_lib.GetConfig()
Don Garrett8dace272018-07-19 14:07:42 -0700200 branch_config = chromeos_config.BranchScheduleConfig()
Don Garrettbe3608b2018-06-05 17:10:09 -0700201
202 with (open(options.file_out, 'w') if options.file_out else sys.stdout) as fh:
Don Garrett8dace272018-07-19 14:07:42 -0700203 fh.write(genLuciSchedulerConfig(site_config, branch_config))