| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2013 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 """Contains generating and parsing systems of the Chromium Buildbot Annotator. | 6 """Contains generating and parsing systems of the Chromium Buildbot Annotator. |
| 7 | 7 |
| 8 When executed as a script, this reads step name / command pairs from a file and | 8 When executed as a script, this reads step name / command pairs from a file and |
| 9 executes those lines while annotating the output. The input is json: | 9 executes those lines while annotating the output. The input is json: |
| 10 | 10 |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 cmd: command to run, list of one or more strings | 354 cmd: command to run, list of one or more strings |
| 355 cwd: absolute path to working directory for the command | 355 cwd: absolute path to working directory for the command |
| 356 env: dict with overrides for environment variables | 356 env: dict with overrides for environment variables |
| 357 skip: True to skip this step | 357 skip: True to skip this step |
| 358 always_run: True to run the step even if some previous step failed | 358 always_run: True to run the step even if some previous step failed |
| 359 ignore_annotations: if True will ignore annotations emitted by the step | 359 ignore_annotations: if True will ignore annotations emitted by the step |
| 360 | 360 |
| 361 Returns new value for build_failure. | 361 Returns new value for build_failure. |
| 362 """ | 362 """ |
| 363 if skip or (build_failure and not always_run): | 363 if skip or (build_failure and not always_run): |
| 364 return build_failure | 364 return build_failure, None |
| 365 | 365 |
| 366 # For error reporting. | 366 # For error reporting. |
| 367 step_dict = locals().copy() | 367 step_dict = locals().copy() |
| 368 step_dict.pop('stream') | 368 step_dict.pop('stream') |
| 369 step_dict.update(kwargs) | 369 step_dict.update(kwargs) |
| 370 | 370 |
| 371 filter_obj = None | 371 filter_obj = None |
| 372 if ignore_annotations: | 372 if ignore_annotations: |
| 373 class AnnotationFilter(chromium_utils.RunCommandFilter): | 373 class AnnotationFilter(chromium_utils.RunCommandFilter): |
| 374 def FilterLine(self, line): | 374 def FilterLine(self, line): |
| 375 return line.replace('@@@', '###') | 375 return line.replace('@@@', '###') |
| 376 filter_obj = AnnotationFilter() | 376 filter_obj = AnnotationFilter() |
| 377 | 377 |
| 378 ret = None |
| 378 try: | 379 try: |
| 379 with stream.step(name) as s: | 380 with stream.step(name) as s: |
| 380 ret = chromium_utils.RunCommand(command=map(str, cmd), | 381 ret = chromium_utils.RunCommand(command=map(str, cmd), |
| 381 cwd=cwd, | 382 cwd=cwd, |
| 382 env=_merge_envs(os.environ, env), | 383 env=_merge_envs(os.environ, env), |
| 383 filter_obj=filter_obj) | 384 filter_obj=filter_obj) |
| 384 if ret != 0: | 385 if ret != 0: |
| 385 print 'step returned non-zero exit code: %d' % ret | 386 print 'step returned non-zero exit code: %d' % ret |
| 386 print 'step was: %s' % json.dumps(step_dict) | 387 print 'step was: %s' % json.dumps(step_dict) |
| 387 s.step_failure() | 388 s.step_failure() |
| 388 build_failure = True | 389 build_failure = True |
| 389 except OSError: | 390 except OSError: |
| 390 # File wasn't found, error has been already reported to stream. | 391 # File wasn't found, error has been already reported to stream. |
| 391 build_failure = True | 392 build_failure = True |
| 392 | 393 |
| 393 return build_failure | 394 return build_failure, ret |
| 395 |
| 396 |
| 397 def run_steps(steps, build_failure): |
| 398 for step in steps: |
| 399 error = _validate_step(step) |
| 400 if error: |
| 401 print 'Invalid step - %s\n%s' % (error, json.dumps(step, indent=2)) |
| 402 sys.exit(1) |
| 403 |
| 404 seed_steps = [] |
| 405 for step in steps: |
| 406 seed_steps.append(step['name']) |
| 407 seed_steps.extend(step.get('seed_steps', [])) |
| 408 |
| 409 stream = StructuredAnnotationStream(seed_steps=seed_steps) |
| 410 ret_codes = [] |
| 411 for step in steps: |
| 412 build_failure, ret = _run_step(stream, build_failure, **step) |
| 413 ret_codes.append(ret) |
| 414 return build_failure, ret_codes |
| 394 | 415 |
| 395 | 416 |
| 396 def main(): | 417 def main(): |
| 397 usage = '%s <command list file or - for stdin>' % sys.argv[0] | 418 usage = '%s <command list file or - for stdin>' % sys.argv[0] |
| 398 parser = optparse.OptionParser(usage=usage) | 419 parser = optparse.OptionParser(usage=usage) |
| 399 _, args = parser.parse_args() | 420 _, args = parser.parse_args() |
| 400 if not args: | 421 if not args: |
| 401 parser.error('Must specify an input filename.') | 422 parser.error('Must specify an input filename.') |
| 402 if len(args) > 1: | 423 if len(args) > 1: |
| 403 parser.error('Too many arguments specified.') | 424 parser.error('Too many arguments specified.') |
| 404 | 425 |
| 405 steps = [] | 426 steps = [] |
| 406 | 427 |
| 407 if args[0] == '-': | 428 if args[0] == '-': |
| 408 steps.extend(json.load(sys.stdin)) | 429 steps.extend(json.load(sys.stdin)) |
| 409 else: | 430 else: |
| 410 with open(args[0], 'rb') as f: | 431 with open(args[0], 'rb') as f: |
| 411 steps.extend(json.load(f)) | 432 steps.extend(json.load(f)) |
| 412 | 433 |
| 413 for step in steps: | 434 return 1 if run_steps(steps, False)[0] else 0 |
| 414 error = _validate_step(step) | |
| 415 if error: | |
| 416 print 'Invalid step - %s\n%s' % (error, json.dumps(step, indent=2)) | |
| 417 return 1 | |
| 418 | |
| 419 stream = StructuredAnnotationStream(seed_steps=[s['name'] for s in steps]) | |
| 420 build_failure = False | |
| 421 for step in steps: | |
| 422 build_failure = _run_step(stream, build_failure, **step) | |
| 423 return 1 if build_failure else 0 | |
| 424 | 435 |
| 425 | 436 |
| 426 if __name__ == '__main__': | 437 if __name__ == '__main__': |
| 427 sys.exit(main()) | 438 sys.exit(main()) |
| OLD | NEW |