blob: 0a7a89b7931757d1572de011853337a83921c0b6 [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
19Limitations:
20 This script can only handle builds on the "master" branch.
21"""
22
23from __future__ import print_function
24
25import sys
26
27from chromite.lib import commandline
28from chromite.lib import config_lib
29
30
31_CONFIG_HEADER = """# Defines buckets on luci-scheduler.appspot.com.
32#
33# For schema of this file and documentation see ProjectConfig message in
34# https://github.com/luci/luci-go/blob/master/scheduler/appengine/messages/config.proto
35
36# Generated with chromite/scripts/gen_luci_scheduler
37
38acl_sets {
39 name: "default"
40 acls {
41 role: READER
42 granted_to: "group:googlers"
43 }
44 acls {
45 role: OWNER
46 granted_to: "group:project-chromeos-admins"
47 }
48}
49"""
50
51
52def genSchedulerJob(build_config):
53 """Generate the luci scheduler job for a given build config.
54
55 Args:
56 build_config: config_lib.BuildConfig.
57
58 Returns:
59 Multiline string to include in the luci scheduler configuration.
60 """
61 # TODO: Move --buildbot arg into recipe, and remove from here.
62 template = """
63job {
64 id: "%(name)s"
65 acl_sets: "default"
66 schedule: "%(schedule)s"
67 buildbucket: {
68 server: "cr-buildbucket.appspot.com"
69 bucket: "luci.chromeos.general"
70 builder: "%(builder)s"
71 tags: "cbb_branch:%(branch)s"
72 tags: "cbb_display_label:%(display_label)s"
73 tags: "cbb_config:%(name)s"
74 properties: "cbb_branch:%(branch)s"
75 properties: "cbb_display_label:%(display_label)s"
76 properties: "cbb_config:%(name)s"
77 properties: "cbb_extra_args:[\\"--buildbot\\"]"
78 }
79}
80"""
81 return template % {
82 'name': build_config.name,
83 'builder': build_config.luci_builder,
84 'branch': 'master',
85 'display_label': build_config.display_label,
86 'schedule': build_config.schedule,
87 }
88
89
90def genSchedulerTrigger(trigger_name, repo, refs, builds):
91 """Generate the luci scheduler job for a given build config.
92
93 Args:
94 trigger_name: Name of the trigger as a string.
95 repo: Gitiles URL git git repository.
96 refs: Iterable of git refs to check. May use regular expressions.
97 builds: Iterable of build config names to trigger.
98
99 Returns:
100 Multiline string to include in the luci scheduler configuration.
101 """
102 template = """
103trigger {
104 id: "%(trigger_name)s"
105 acl_sets: "default"
106 schedule: "with 5m interval"
107 gitiles: {
108 repo: "%(repo)s"
109%(refs)s
110 }
111%(triggers)s
112}
113"""
114
115 return template % {
116 'trigger_name': trigger_name,
117 'repo': repo,
118 'refs': '\n'.join(' refs: "%s"' % r for r in refs),
119 'triggers': '\n'.join(' triggers: "%s"' % b for b in builds),
120 }
121
122
123def genLuciSchedulerConfig(site_config):
124 """Generate a luciSchedulerConfig as a string.
125
126 Args:
127 site_config: A config_lib.SiteConfig instance.
128
129 Returns:
130 The complete scheduler configuration contents as a string.
131 """
132 # Trigger collection is used to collect together trigger information, so
133 # we can reuse the same trigger for multiple builds as needed.
134 # It maps gitiles_key to a set of build_names.
135 # A gitiles_key = (gitiles_url, tuple(ref_list))
136 trigger_collection = {}
137
138 jobs = []
139 for name in sorted(site_config):
140 config = site_config[name]
141
142 # Populate jobs.
143 if config.schedule:
144 jobs.append(genSchedulerJob(config))
145
146 # Populate trigger_collection.
147 if config.triggered_gitiles:
148 for gitiles_url, ref_list in config.triggered_gitiles:
149 gitiles_key = (gitiles_url, tuple(ref_list))
150 trigger_collection.setdefault(gitiles_key, set())
151 trigger_collection[gitiles_key].add(config.name)
152
153 # Populate triggers.
154 triggers = []
155 trigger_counter = 0
156 for gitiles_key in sorted(trigger_collection):
157 builds = sorted(trigger_collection[gitiles_key])
158
159 trigger_name = 'trigger_%s' % trigger_counter
160 gitiles_url, refs = gitiles_key
161 triggers.append(genSchedulerTrigger(
162 trigger_name, gitiles_url, refs, builds))
163 trigger_counter += 1
164
165 return ''.join([_CONFIG_HEADER] + triggers + jobs)
166
167
168def GetParser():
169 """Creates the argparse parser."""
170 parser = commandline.ArgumentParser(description=__doc__)
171
172 parser.add_argument('-o', '--file_out', type='path',
173 help='Write output to specified file.')
174
175 return parser
176
177
178def main(argv):
179 parser = GetParser()
180 options = parser.parse_args(argv)
181 options.Freeze()
182
183 site_config = config_lib.GetConfig()
184
185 with (open(options.file_out, 'w') if options.file_out else sys.stdout) as fh:
186 fh.write(genLuciSchedulerConfig(site_config))