OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import json | 6 import json |
7 import os | 7 import os |
8 import subprocess | 8 import subprocess |
9 import sys | 9 import sys |
10 import tempfile | 10 import tempfile |
11 | 11 |
12 | 12 |
13 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | 13 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
14 | 14 |
15 | 15 |
16 sys.path.insert(0, os.path.join(BASE_DIR, 'scripts')) | |
17 sys.path.insert(0, os.path.join(BASE_DIR, 'scripts', 'slave', 'recipes')) | |
18 sys.path.insert( | |
19 0, os.path.join(BASE_DIR, 'scripts', 'slave', 'recipe_modules')) | |
20 sys.path.insert(0, os.path.join(BASE_DIR, 'third_party')) | |
21 | |
22 import chromium_trybot | |
23 from chromium_tests.builders import BUILDERS | |
24 | |
25 | |
26 MAIN_WATERFALL_MASTERS = [ | 16 MAIN_WATERFALL_MASTERS = [ |
27 'master.chromium.chrome', | 17 'master.chromium.chrome', |
28 'master.chromium.chromiumos', | 18 'master.chromium.chromiumos', |
29 'master.chromium.gpu', | 19 'master.chromium.gpu', |
30 'master.chromium.linux', | 20 'master.chromium.linux', |
31 'master.chromium.mac', | 21 'master.chromium.mac', |
32 'master.chromium.memory', | 22 'master.chromium.memory', |
33 'master.chromium.win', | 23 'master.chromium.win', |
34 ] | 24 ] |
35 | 25 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 ], | 85 ], |
96 } | 86 } |
97 | 87 |
98 UNUSED_MAIN_WATERFALL_BUILDERS = { | 88 UNUSED_MAIN_WATERFALL_BUILDERS = { |
99 'master.chromium.linux': [ | 89 'master.chromium.linux': [ |
100 'Android x86 Builder (dbg)', | 90 'Android x86 Builder (dbg)', |
101 ], | 91 ], |
102 } | 92 } |
103 | 93 |
104 | 94 |
| 95 def getBuilders(recipe_name): |
| 96 """Asks the given recipe to dump its BUILDERS dictionary. |
| 97 |
| 98 This must be implemented by the recipe in question. |
| 99 """ |
| 100 (fh, builders_file) = tempfile.mkstemp('.json') |
| 101 os.close(fh) |
| 102 try: |
| 103 subprocess.check_call([ |
| 104 os.path.join(BASE_DIR, 'scripts', 'slave', 'recipes.py'), |
| 105 'run', recipe_name, 'dump_builders=%s' % builders_file]) |
| 106 with open(builders_file) as fh: |
| 107 return json.load(fh) |
| 108 finally: |
| 109 os.remove(builders_file) |
| 110 |
| 111 |
105 def getMasterConfig(master): | 112 def getMasterConfig(master): |
106 with tempfile.NamedTemporaryFile() as f: | 113 with tempfile.NamedTemporaryFile() as f: |
107 subprocess.check_call([ | 114 subprocess.check_call([ |
108 os.path.join(BASE_DIR, 'scripts', 'tools', 'runit.py'), | 115 os.path.join(BASE_DIR, 'scripts', 'tools', 'runit.py'), |
109 os.path.join(BASE_DIR, 'scripts', 'tools', 'dump_master_cfg.py'), | 116 os.path.join(BASE_DIR, 'scripts', 'tools', 'dump_master_cfg.py'), |
110 os.path.join(BASE_DIR, 'masters/%s' % master), | 117 os.path.join(BASE_DIR, 'masters/%s' % master), |
111 f.name]) | 118 f.name]) |
112 return json.load(f) | 119 return json.load(f) |
113 | 120 |
114 | 121 |
115 def getBuildersAndRecipes(master): | 122 def getBuildersAndRecipes(master): |
116 return { | 123 return { |
117 builder['name'] : builder['factory']['properties'].get( | 124 builder['name'] : builder['factory']['properties'].get( |
118 'recipe', [None])[0] | 125 'recipe', [None])[0] |
119 for builder in getMasterConfig(master)['builders'] | 126 for builder in getMasterConfig(master)['builders'] |
120 } | 127 } |
121 | 128 |
122 | 129 |
123 def mutualDifference(a, b): | 130 def mutualDifference(a, b): |
124 return a - b, b - a | 131 return a - b, b - a |
125 | 132 |
126 | 133 |
127 def main(argv): | 134 def main(argv): |
128 chromium_recipe_builders = {} | 135 chromium_recipe_builders = {} |
129 covered_builders = set() | 136 covered_builders = set() |
130 all_builders = set() | 137 all_builders = set() |
131 | 138 |
132 exit_code = 0 | 139 exit_code = 0 |
133 | 140 |
| 141 chromium_trybot_BUILDERS = getBuilders('chromium_trybot') |
| 142 chromium_BUILDERS = getBuilders('chromium') |
| 143 |
134 for master in MAIN_WATERFALL_MASTERS: | 144 for master in MAIN_WATERFALL_MASTERS: |
135 builders = getBuildersAndRecipes(master) | 145 builders = getBuildersAndRecipes(master) |
136 all_builders.update((master, b) for b in builders) | 146 all_builders.update((master, b) for b in builders) |
137 | 147 |
138 # We only have a standardized way to mirror builders using the chromium | 148 # We only have a standardized way to mirror builders using the chromium |
139 # recipe on the tryserver. | 149 # recipe on the tryserver. |
140 chromium_recipe_builders[master] = [b for b in builders | 150 chromium_recipe_builders[master] = [b for b in builders |
141 if builders[b] == 'chromium'] | 151 if builders[b] == 'chromium'] |
142 | 152 |
143 # TODO(phajdan.jr): Also consider it an error if configured builders | 153 # TODO(phajdan.jr): Also consider it an error if configured builders |
144 # are not using chromium recipe. This might make it harder to experiment | 154 # are not using chromium recipe. This might make it harder to experiment |
145 # with switching bots over to chromium recipe though, so it may be better | 155 # with switching bots over to chromium recipe though, so it may be better |
146 # to just wait until the switch is done. | 156 # to just wait until the switch is done. |
147 recipe_side_builders = BUILDERS.get( | 157 recipe_side_builders = chromium_BUILDERS.get( |
148 master.replace('master.', ''), {}).get('builders') | 158 master.replace('master.', ''), {}).get('builders') |
149 if recipe_side_builders is not None: | 159 if recipe_side_builders is not None: |
150 bogus_builders = set(recipe_side_builders.keys()).difference( | 160 bogus_builders = set(recipe_side_builders.keys()).difference( |
151 set(builders.keys())) | 161 set(builders.keys())) |
152 bogus_builders, unused = mutualDifference( | 162 bogus_builders, unused = mutualDifference( |
153 bogus_builders, | 163 bogus_builders, |
154 set(UNUSED_MAIN_WATERFALL_BUILDERS.get(master, []))) | 164 set(UNUSED_MAIN_WATERFALL_BUILDERS.get(master, []))) |
155 # TODO(phajdan.jr): Clean up bogus chromiumos builders. | 165 # TODO(phajdan.jr): Clean up bogus chromiumos builders. |
156 if bogus_builders and master != 'master.chromium.chromiumos': | 166 if bogus_builders and master != 'master.chromium.chromiumos': |
157 exit_code = 1 | 167 exit_code = 1 |
158 print 'The following builders from chromium recipe' | 168 print 'The following builders from chromium recipe' |
159 print 'do not exist in master config for %s:' % master | 169 print 'do not exist in master config for %s:' % master |
160 print '\n'.join('\t%s' % b for b in sorted(bogus_builders)) | 170 print '\n'.join('\t%s' % b for b in sorted(bogus_builders)) |
161 if unused: | 171 if unused: |
162 exit_code = 1 | 172 exit_code = 1 |
163 print 'The following unused declarations are superfluous ' | 173 print 'The following unused declarations are superfluous ' |
164 print 'on %s' % master | 174 print 'on %s' % master |
165 print '\n'.join('\t%s' % b for b in sorted(unused)) | 175 print '\n'.join('\t%s' % b for b in sorted(unused)) |
166 | 176 |
167 | 177 |
168 for master in TRYSERVER_MASTERS: | 178 for master in TRYSERVER_MASTERS: |
169 builders = getBuildersAndRecipes(master) | 179 builders = getBuildersAndRecipes(master) |
170 recipe_side_builders = chromium_trybot.BUILDERS[ | 180 recipe_side_builders = chromium_trybot_BUILDERS[ |
171 master.replace('master.', '')]['builders'] | 181 master.replace('master.', '')]['builders'] |
172 | 182 |
173 bogus_builders = set(recipe_side_builders.keys()).difference( | 183 bogus_builders = set(recipe_side_builders.keys()).difference( |
174 set(builders.keys())) | 184 set(builders.keys())) |
175 if bogus_builders: | 185 if bogus_builders: |
176 exit_code = 1 | 186 exit_code = 1 |
177 print 'The following builders from chromium_trybot recipe' | 187 print 'The following builders from chromium_trybot recipe' |
178 print 'do not exist in master config for %s:' % master | 188 print 'do not exist in master config for %s:' % master |
179 print '\n'.join('\t%s' % b for b in sorted(bogus_builders)) | 189 print '\n'.join('\t%s' % b for b in sorted(bogus_builders)) |
180 | 190 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 exit_code = 1 | 230 exit_code = 1 |
221 print 'Unused suppressions:' | 231 print 'Unused suppressions:' |
222 print '\n'.join(sorted( | 232 print '\n'.join(sorted( |
223 '\t%s:%s' % (b[0], b[1]) for b in unused_suppressions)) | 233 '\t%s:%s' % (b[0], b[1]) for b in unused_suppressions)) |
224 | 234 |
225 return exit_code | 235 return exit_code |
226 | 236 |
227 | 237 |
228 if __name__ == '__main__': | 238 if __name__ == '__main__': |
229 sys.exit(main(sys.argv[1:])) | 239 sys.exit(main(sys.argv[1:])) |
OLD | NEW |