Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2015 The Chromium 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 | |
| 5 import json | |
| 6 | |
| 7 from recipe_engine.config import List | |
| 8 from recipe_engine.recipe_api import Property | |
| 9 | |
| 10 | |
| 11 DEPS = [ | |
| 12 'chromium', | |
| 13 'chromium_tests', | |
| 14 'findit', | |
| 15 'gclient', | |
| 16 'json', | |
| 17 'path', | |
| 18 'properties', | |
| 19 'python', | |
| 20 'step', | |
| 21 ] | |
| 22 | |
| 23 | |
| 24 PROPERTIES = { | |
| 25 'target_mastername': Property( | |
| 26 kind=str, help='The target master to match compile config to.'), | |
| 27 'target_buildername': Property( | |
| 28 kind=str, help='The target builder to match compile config to.'), | |
| 29 'target_solution': Property( | |
|
Paweł Hajdan Jr.
2015/11/24 13:20:41
Why is this needed?
The mastername and buildernam
stgao
2015/11/24 23:19:20
This is very helpful, and it could save me one par
| |
| 30 kind=str, help='The gclient solution, eg: src for chromium.'), | |
| 31 'target_solution_revisions': Property( | |
| 32 kind=List(basestring), | |
| 33 help='The revisions to be tested for compile failure, ' | |
| 34 'ordered from older revisions to newer revisions.'), | |
| 35 'requested_compile_targets': Property( | |
| 36 kind=List(basestring), default=None, param_name='compile_targets', | |
| 37 help='The failed compile targets, eg: browser_tests'), | |
| 38 } | |
| 39 | |
| 40 | |
| 41 class CompileResult(object): | |
| 42 SKIPPED = 'skipped' # No compile is needed. | |
| 43 PASSED = 'passed' # Compile passed. | |
| 44 FAILED = 'failed' # Compile failed. | |
| 45 | |
| 46 | |
| 47 def _run_compile_at_revision(api, target_mastername, target_buildername, | |
| 48 target_solution, revision, | |
| 49 compile_targets): | |
| 50 with api.step.nest('test %s' % str(revision)): | |
| 51 # Configure the revision to recompile. | |
| 52 api.gclient.c.revisions[target_solution] = revision | |
| 53 | |
| 54 bot_update_step, master_dict, test_spec = \ | |
| 55 api.chromium_tests.prepare_checkout( | |
| 56 target_mastername, | |
| 57 target_buildername) | |
| 58 | |
| 59 # If no compile targets are provided, use analyze to filter out the | |
|
Paweł Hajdan Jr.
2015/11/24 13:20:41
Why do you want to support the case where no compi
stgao
2015/11/24 23:19:20
For compile failures on the waterfall, now there i
| |
| 60 # impacted compile targets by the given revision. | |
| 61 # TODO: if compile targets are provided, check if they exist and use analyze | |
| 62 # to filter out the impacted ones by the given revision. | |
| 63 compile_targets = sorted(set(compile_targets or [])) | |
| 64 if not compile_targets: | |
| 65 affected_files = api.findit.get_files_affected_by_revision( | |
| 66 revision, target_solution) | |
| 67 | |
| 68 test_targets, compile_targets, _ = \ | |
| 69 api.chromium_tests.get_test_targets_compile_targets_and_tests( | |
|
Dirk Pranke
2015/11/24 00:17:41
why are you splitting test_targets and compile_tar
stgao
2015/11/24 06:15:29
Yes, to match the changed API in chromium_tests.an
stgao
2015/11/24 23:19:19
Done.
| |
| 70 target_mastername, | |
| 71 target_buildername, | |
| 72 master_dict, | |
| 73 test_spec, | |
| 74 override_bot_type='builder_tester', | |
| 75 override_tests=[]) | |
| 76 additional_compile_targets = sorted( | |
| 77 set(compile_targets) - set(test_targets)) | |
| 78 | |
| 79 _, compile_targets = api.chromium_tests.analyze( | |
|
Paweł Hajdan Jr.
2015/11/24 13:20:41
Is analyze _really_ needed here? Why can't we rely
stgao
2015/11/24 23:19:20
We could do that, but it will be slow, because mor
Paweł Hajdan Jr.
2015/11/30 16:19:05
What's the reasoning behind this? I'm not convince
stgao
2015/12/01 16:30:00
In this smoke test, build in http://shortn/_d3dv1O
| |
| 80 affected_files, | |
| 81 test_targets, | |
| 82 additional_compile_targets, | |
| 83 'trybot_analyze_config.json') | |
| 84 | |
| 85 if not compile_targets: | |
| 86 # No compile target is impacted by the given revision. | |
| 87 return CompileResult.SKIPPED | |
| 88 | |
| 89 assert compile_targets, 'compile targets should not be empty!' | |
|
Dirk Pranke
2015/11/24 00:17:41
nit: I'm not convinced this assert is really usefu
stgao
2015/11/24 23:19:20
Done.
| |
| 90 | |
| 91 try: | |
| 92 api.chromium_tests.compile_specific_targets( | |
| 93 target_mastername, | |
| 94 target_buildername, | |
| 95 bot_update_step, | |
| 96 master_dict, | |
| 97 compile_targets, | |
| 98 [], # Not run any test. | |
|
Dirk Pranke
2015/11/24 00:17:41
nit: I'd just say tests_including_triggered=[] ins
stgao
2015/11/24 23:19:20
Done.
| |
| 99 override_bot_type='builder_tester') | |
|
Paweł Hajdan Jr.
2015/11/24 13:20:41
Why is this needed?
stgao
2015/11/24 23:19:20
Just want to make it explicit. I could remove it i
Paweł Hajdan Jr.
2015/11/30 16:19:05
That's actually a behavior change. chromium_trybot
stgao
2015/12/01 16:30:00
Oh, I see. I thought it was the same as a "builder
stgao
2015/12/01 17:15:02
As discussion in the meeting, I will add this bot-
| |
| 100 return CompileResult.PASSED | |
| 101 except api.step.InfraFailure: | |
| 102 raise | |
| 103 except api.step.StepFailure: | |
| 104 return CompileResult.FAILED | |
| 105 | |
| 106 | |
| 107 def RunSteps(api, target_mastername, target_buildername, | |
| 108 target_solution, target_solution_revisions, | |
| 109 requested_compile_targets): | |
| 110 api.chromium_tests.configure_build( | |
| 111 target_mastername, target_buildername, override_bot_type='builder_tester') | |
|
Paweł Hajdan Jr.
2015/11/24 13:20:41
Why is override_bot_type needed here?
stgao
2015/11/24 23:19:20
Just want to make it explicit. I could remove it i
| |
| 112 | |
| 113 results = [] | |
| 114 try: | |
| 115 for current_revision in target_solution_revisions: | |
| 116 try: | |
| 117 compile_result = _run_compile_at_revision( | |
| 118 api, target_mastername, target_buildername, target_solution, | |
| 119 current_revision, requested_compile_targets) | |
| 120 except api.step.InfraFailure: | |
| 121 # Retry once only on infra failure. | |
|
Paweł Hajdan Jr.
2015/11/24 13:20:41
Is this retry really needed/useful here?
stgao
2015/11/24 23:19:19
For compile failures on the waterfall, I saw a lot
Paweł Hajdan Jr.
2015/11/30 16:19:05
Can we start with a version of this recipe which d
stgao
2015/12/01 16:30:00
OK. Removed.
| |
| 122 compile_result = _run_compile_at_revision( | |
| 123 api, target_mastername, target_buildername, target_solution, | |
| 124 current_revision, requested_compile_targets) | |
| 125 | |
| 126 results.append([current_revision, compile_result]) | |
| 127 if compile_result == CompileResult.FAILED: | |
| 128 # TODO: if compile targets are specified, compile may fail because those | |
|
Paweł Hajdan Jr.
2015/11/24 13:20:41
Please follow the style guide's TODO(...) format.
stgao
2015/11/24 23:19:20
Done.
| |
| 129 # targets are added in a later revision. | |
| 130 break # Found the culprit, no need to check later revisions. | |
| 131 finally: | |
| 132 # Report the result. | |
| 133 step_result = api.python.inline( | |
|
Paweł Hajdan Jr.
2015/11/24 13:20:41
Why not use api.python.result_step (or succeeding/
stgao
2015/11/24 23:19:20
I'm afraid I can't do that.
Because they don't su
Paweł Hajdan Jr.
2015/11/30 16:19:05
Could you at the very least add a TODO, and eventu
stgao
2015/12/01 16:30:00
Done.
| |
| 134 'report', 'import sys; sys.exit(0)', add_python_log=False) | |
| 135 if (not requested_compile_targets and | |
| 136 results and results[-1][1] == CompileResult.FAILED): | |
| 137 step_result.presentation.step_text = '<br/>Culprit: %s' % results[-1][0] | |
| 138 step_result.presentation.logs.setdefault('result', []).append( | |
| 139 json.dumps(results, indent=2)) | |
| 140 | |
| 141 return results | |
| 142 | |
| 143 | |
| 144 def GenTests(api): | |
| 145 def props(compile_targets=None): | |
| 146 properties = { | |
| 147 'mastername': 'tryserver.chromium.linux', | |
| 148 'buildername': 'linux_variable', | |
| 149 'slavename': 'build1-a1', | |
| 150 'buildnumber': '1', | |
| 151 'target_mastername': 'chromium.linux', | |
| 152 'target_buildername': 'Linux Builder', | |
| 153 'target_solution': 'src', | |
| 154 'target_solution_revisions': ['r1'], | |
| 155 } | |
| 156 if compile_targets: | |
| 157 properties['compile_targets'] = compile_targets | |
| 158 return api.properties(**properties) | |
| 159 | |
| 160 yield ( | |
| 161 api.test('compile_skipped') + | |
| 162 props() + | |
| 163 api.override_step_data( | |
| 164 'test r1.analyze', | |
| 165 api.json.output({ | |
| 166 'status': 'No dependencies', | |
| 167 'compile_targets': [], | |
| 168 'test_targets': [], | |
| 169 }) | |
| 170 ) | |
| 171 ) | |
| 172 | |
| 173 yield ( | |
| 174 api.test('successful_compile_targets_returned_by_analyze') + | |
| 175 props() + | |
| 176 api.override_step_data( | |
| 177 'test r1.analyze', | |
| 178 api.json.output({ | |
| 179 'status': 'Found dependency', | |
| 180 'compile_targets': ['test_target', 'test_target_run'], | |
| 181 'test_targets': ['test_target', 'test_target_run'], | |
| 182 }) | |
| 183 ) | |
| 184 ) | |
| 185 | |
| 186 yield ( | |
| 187 api.test('failed_compile_targets_returned_by_analyze') + | |
| 188 props() + | |
| 189 api.override_step_data( | |
| 190 'test r1.analyze', | |
| 191 api.json.output({ | |
| 192 'status': 'Found dependency', | |
| 193 'compile_targets': ['test_target', 'test_target_run'], | |
| 194 'test_targets': ['test_target', 'test_target_run'], | |
| 195 }) | |
| 196 ) + | |
| 197 api.override_step_data('test r1.compile', retcode=1) | |
| 198 ) | |
| 199 | |
| 200 yield ( | |
| 201 api.test('compile_specified_targets') + | |
| 202 props(compile_targets=['target_name']) | |
| 203 ) | |
| 204 | |
| 205 yield ( | |
| 206 api.test('compile_failed') + | |
| 207 props(compile_targets=['target_name']) + | |
| 208 api.override_step_data('test r1.compile', retcode=1) | |
| 209 ) | |
| 210 | |
| 211 yield ( | |
| 212 api.test('successful_retry_compile_upon_infra_failure') + | |
| 213 props(compile_targets=['target_name']) + | |
| 214 api.override_step_data( | |
| 215 'test r1.compile', | |
| 216 api.json.output({ | |
| 217 'notice': [ | |
| 218 { | |
| 219 'infra_status': { | |
| 220 'ping_status_code': 408, | |
| 221 }, | |
| 222 }, | |
| 223 ], | |
| 224 }), | |
| 225 retcode=1) + | |
| 226 api.override_step_data( | |
| 227 'test r1.compile (2)', | |
| 228 api.json.output({ | |
| 229 'notice': [ | |
| 230 { | |
| 231 'infra_status': { | |
| 232 'ping_status_code': 200, | |
| 233 }, | |
| 234 }, | |
| 235 ], | |
| 236 }), | |
| 237 retcode=1) | |
| 238 ) | |
| 239 | |
| 240 yield ( | |
| 241 api.test('failed_retry_compile_upon_infra_failure') + | |
| 242 props(compile_targets=['target_name']) + | |
| 243 api.override_step_data( | |
| 244 'test r1.compile', | |
| 245 api.json.output({ | |
| 246 'notice': [ | |
| 247 { | |
| 248 'infra_status': { | |
| 249 'ping_status_code': 408, | |
| 250 }, | |
| 251 }, | |
| 252 ], | |
| 253 }), | |
| 254 retcode=1) + | |
| 255 api.override_step_data( | |
| 256 'test r1.compile (2)', | |
| 257 api.json.output({ | |
| 258 'notice': [ | |
| 259 { | |
| 260 'infra_status': { | |
| 261 'ping_status_code': 408, | |
| 262 }, | |
| 263 }, | |
| 264 ], | |
| 265 }), | |
| 266 retcode=1) | |
| 267 ) | |
| OLD | NEW |