bot_update: Show failed patch in "Patch Failure".

Have "bot_update.py" export the failing patch body in its JSON. Have the
recipe actually emit the patch body in the "Patch Failure" step instead
of the "bot_update" step, and remove the "Patch Failure" step's
indirection to the "bot_update" step for patch failure.

This will provide a more straightforward user interface: the red step
that says "Patch Failure" now includes the details of the patch failure!

BUG=chromium:710477
TEST=expectations

Change-Id: I6ad305f0b972de89e4f0b5eb70edf41980447abd
Reviewed-on: https://chromium-review.googlesource.com/475950
Commit-Queue: Daniel Jacques <dnj@chromium.org>
Reviewed-by: Ryan Tseng <hinoka@chromium.org>
changes/50/475950/6
Dan Jacques 8 years ago committed by Commit Bot
parent 3978290b21
commit 8dd4edae99

@ -269,6 +269,7 @@ class BotUpdateApi(recipe_api.RecipeApi):
raise
finally:
if step_result:
result = step_result.json.output
self._last_returned_properties = step_result.json.output.get(
'properties', {})
@ -278,44 +279,38 @@ class BotUpdateApi(recipe_api.RecipeApi):
self.last_returned_properties.iteritems()):
step_result.presentation.properties[prop_name] = prop_value
# Add helpful step description in the step UI.
if 'step_text' in step_result.json.output:
step_text = step_result.json.output['step_text']
if 'step_text' in result:
step_text = result['step_text']
step_result.presentation.step_text = step_text
# Add log line output.
if 'log_lines' in step_result.json.output:
for log_name, log_lines in step_result.json.output['log_lines']:
step_result.presentation.logs[log_name] = log_lines.splitlines()
# Set the "checkout" path for the main solution.
# This is used by the Chromium module to figure out where to look for
# the checkout.
# If there is a patch failure, emit another step that said things
# failed.
if step_result.json.output.get('patch_failure'):
return_code = step_result.json.output.get('patch_apply_return_code')
if result.get('patch_failure'):
return_code = result.get('patch_apply_return_code')
patch_body = result.get('failed_patch_body')
try:
if return_code == 3:
# This is download failure, hence an infra failure.
# Sadly, python.failing_step doesn't support kwargs.
self.m.python.inline(
'Patch failure - Try Rebasing',
('import sys;'
'print "Patch download failed. See bot_update step for'
' details";sys.exit(1)'),
infra_step=True,
step_test_data=lambda: self.m.raw_io.test_api.output(
'Patch download failed. See bot_update step for details',
retcode=1)
)
with self.m.step.context({'infra_step': True}):
self.m.python.failing_step(
'Patch failure', 'Git reported a download failure')
else:
# This is actual patch failure.
self.m.tryserver.set_patch_failure_tryjob_result()
self.m.python.failing_step(
'Patch failure', 'Check the bot_update step for details')
'Patch failure', 'See attached log. Try rebasing?')
except self.m.step.StepFailure as e:
if patch_body:
e.result.presentation.logs['patch error'] = (
patch_body.splitlines())
# bot_update actually just sets root to be the folder name of the
# first solution.
if step_result.json.output['did_run']:
co_root = step_result.json.output['root']
if result['did_run']:
co_root = result['root']
cwd = self.m.step.get_from_context('cwd', self.m.path['start_dir'])
if 'checkout' not in self.m.path:
self.m.path['checkout'] = cwd.join(*co_root.split(self.m.path.sep))

@ -34,15 +34,10 @@
"@@@STEP_TEXT@Some step text@@@",
"@@@STEP_LOG_LINE@json.output@{@@@",
"@@@STEP_LOG_LINE@json.output@ \"did_run\": true, @@@",
"@@@STEP_LOG_LINE@json.output@ \"failed_patch_body\": \"Downloading patch...\\nApplying the patch...\\nPatch: foo/bar.py\\nIndex: foo/bar.py\\ndiff --git a/foo/bar.py b/foo/bar.py\\nindex HASH..HASH MODE\\n--- a/foo/bar.py\\n+++ b/foo/bar.py\\ncontext\\n+something\\n-something\\nmore context\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"fixed_revisions\": {@@@",
"@@@STEP_LOG_LINE@json.output@ \"src\": \"HEAD\"@@@",
"@@@STEP_LOG_LINE@json.output@ }, @@@",
"@@@STEP_LOG_LINE@json.output@ \"log_lines\": [@@@",
"@@@STEP_LOG_LINE@json.output@ [@@@",
"@@@STEP_LOG_LINE@json.output@ \"patch error\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"Patch failed to apply\"@@@",
"@@@STEP_LOG_LINE@json.output@ ]@@@",
"@@@STEP_LOG_LINE@json.output@ ], @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_apply_return_code\": 1, @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_failure\": true, @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_root\": \"src\", @@@",
@ -54,8 +49,6 @@
"@@@STEP_LOG_LINE@json.output@ \"step_text\": \"Some step text\"@@@",
"@@@STEP_LOG_LINE@json.output@}@@@",
"@@@STEP_LOG_END@json.output@@@",
"@@@STEP_LOG_LINE@patch error@Patch failed to apply@@@",
"@@@STEP_LOG_END@patch error@@@",
"@@@SET_BUILD_PROPERTY@got_cr_revision@\"f27fede2220bcd326aee3e86ddfd4ebd0fe58cb9\"@@@",
"@@@SET_BUILD_PROPERTY@got_cr_revision_cp@\"refs/heads/master@{#170242}\"@@@",
"@@@SET_BUILD_PROPERTY@failure_type@\"PATCH_FAILURE\"@@@"
@ -70,14 +63,108 @@
"name": "Patch failure",
"~followup_annotations": [
"step returned non-zero exit code: 1",
"@@@STEP_TEXT@Check the bot_update step for details@@@",
"@@@STEP_TEXT@See attached log. Try rebasing?@@@",
"@@@STEP_LOG_LINE@patch error@Downloading patch...@@@",
"@@@STEP_LOG_LINE@patch error@Applying the patch...@@@",
"@@@STEP_LOG_LINE@patch error@Patch: foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@Index: foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@diff --git a/foo/bar.py b/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@index HASH..HASH MODE@@@",
"@@@STEP_LOG_LINE@patch error@--- a/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@+++ b/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@context@@@",
"@@@STEP_LOG_LINE@patch error@+something@@@",
"@@@STEP_LOG_LINE@patch error@-something@@@",
"@@@STEP_LOG_LINE@patch error@more context@@@",
"@@@STEP_LOG_END@patch error@@@",
"@@@STEP_FAILURE@@@"
]
},
{
"cmd": [
"python",
"-u",
"RECIPE_MODULE[depot_tools::bot_update]/resources/bot_update.py",
"--spec",
"cache_dir = '[GIT_CACHE]'\nsolutions = [{'deps_file': '.DEPS.git', 'managed': True, 'name': 'src', 'url': 'https://chromium.googlesource.com/chromium/src.git'}]",
"--patch_root",
"src",
"--revision_mapping_file",
"{\"src\": \"got_cr_revision\"}",
"--git-cache-dir",
"[GIT_CACHE]",
"--rietveld_server",
"https://rietveld.example.com/",
"--output_json",
"/path/to/tmp/json",
"--revision",
"src@f27fede2220bcd326aee3e86ddfd4ebd0fe58cb9",
"--output_manifest"
],
"env": {
"GIT_HTTP_LOW_SPEED_LIMIT": "1000",
"GIT_HTTP_LOW_SPEED_TIME": "300",
"PATH": "%(PATH)s:RECIPE_PACKAGE_REPO[depot_tools]"
},
"infra_step": true,
"name": "bot_update (without patch)",
"~followup_annotations": [
"@@@STEP_TEXT@Some step text@@@",
"@@@STEP_LOG_LINE@json.output@{@@@",
"@@@STEP_LOG_LINE@json.output@ \"did_run\": true, @@@",
"@@@STEP_LOG_LINE@json.output@ \"failed_patch_body\": \"Downloading patch...\\nApplying the patch...\\nPatch: foo/bar.py\\nIndex: foo/bar.py\\ndiff --git a/foo/bar.py b/foo/bar.py\\nindex HASH..HASH MODE\\n--- a/foo/bar.py\\n+++ b/foo/bar.py\\ncontext\\n+something\\n-something\\nmore context\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"fixed_revisions\": {@@@",
"@@@STEP_LOG_LINE@json.output@ \"src\": \"f27fede2220bcd326aee3e86ddfd4ebd0fe58cb9\"@@@",
"@@@STEP_LOG_LINE@json.output@ }, @@@",
"@@@STEP_LOG_LINE@json.output@ \"manifest\": {@@@",
"@@@STEP_LOG_LINE@json.output@ \"src\": {@@@",
"@@@STEP_LOG_LINE@json.output@ \"repository\": \"https://fake.org/src.git\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"revision\": \"f27fede2220bcd326aee3e86ddfd4ebd0fe58cb9\"@@@",
"@@@STEP_LOG_LINE@json.output@ }@@@",
"@@@STEP_LOG_LINE@json.output@ }, @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_apply_return_code\": 1, @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_failure\": true, @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_root\": \"src\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"properties\": {@@@",
"@@@STEP_LOG_LINE@json.output@ \"got_cr_revision\": \"f27fede2220bcd326aee3e86ddfd4ebd0fe58cb9\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"got_cr_revision_cp\": \"refs/heads/master@{#170242}\"@@@",
"@@@STEP_LOG_LINE@json.output@ }, @@@",
"@@@STEP_LOG_LINE@json.output@ \"root\": \"src\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"step_text\": \"Some step text\"@@@",
"@@@STEP_LOG_LINE@json.output@}@@@",
"@@@STEP_LOG_END@json.output@@@",
"@@@SET_BUILD_PROPERTY@failure_type@\"PATCH_FAILURE\"@@@"
]
},
{
"cmd": [
"python",
"-u",
"import sys; sys.exit(1)"
],
"name": "Patch failure (2)",
"~followup_annotations": [
"step returned non-zero exit code: 1",
"@@@STEP_TEXT@See attached log. Try rebasing?@@@",
"@@@STEP_LOG_LINE@patch error@Downloading patch...@@@",
"@@@STEP_LOG_LINE@patch error@Applying the patch...@@@",
"@@@STEP_LOG_LINE@patch error@Patch: foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@Index: foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@diff --git a/foo/bar.py b/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@index HASH..HASH MODE@@@",
"@@@STEP_LOG_LINE@patch error@--- a/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@+++ b/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@context@@@",
"@@@STEP_LOG_LINE@patch error@+something@@@",
"@@@STEP_LOG_LINE@patch error@-something@@@",
"@@@STEP_LOG_LINE@patch error@more context@@@",
"@@@STEP_LOG_END@patch error@@@",
"@@@STEP_FAILURE@@@"
]
},
{
"name": "$result",
"reason": "Step('Patch failure') failed with return_code 1",
"recipe_result": null,
"status_code": 1
"status_code": 0
}
]

@ -34,15 +34,10 @@
"@@@STEP_TEXT@Some step text@@@",
"@@@STEP_LOG_LINE@json.output@{@@@",
"@@@STEP_LOG_LINE@json.output@ \"did_run\": true, @@@",
"@@@STEP_LOG_LINE@json.output@ \"failed_patch_body\": \"Downloading patch...\\nApplying the patch...\\nPatch: foo/bar.py\\nIndex: foo/bar.py\\ndiff --git a/foo/bar.py b/foo/bar.py\\nindex HASH..HASH MODE\\n--- a/foo/bar.py\\n+++ b/foo/bar.py\\ncontext\\n+something\\n-something\\nmore context\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"fixed_revisions\": {@@@",
"@@@STEP_LOG_LINE@json.output@ \"src\": \"HEAD\"@@@",
"@@@STEP_LOG_LINE@json.output@ }, @@@",
"@@@STEP_LOG_LINE@json.output@ \"log_lines\": [@@@",
"@@@STEP_LOG_LINE@json.output@ [@@@",
"@@@STEP_LOG_LINE@json.output@ \"patch error\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"Patch failed to apply\"@@@",
"@@@STEP_LOG_LINE@json.output@ ]@@@",
"@@@STEP_LOG_LINE@json.output@ ], @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_apply_return_code\": 3, @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_failure\": true, @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_root\": \"src\", @@@",
@ -54,8 +49,6 @@
"@@@STEP_LOG_LINE@json.output@ \"step_text\": \"Some step text\"@@@",
"@@@STEP_LOG_LINE@json.output@}@@@",
"@@@STEP_LOG_END@json.output@@@",
"@@@STEP_LOG_LINE@patch error@Patch failed to apply@@@",
"@@@STEP_LOG_END@patch error@@@",
"@@@SET_BUILD_PROPERTY@got_cr_revision@\"f27fede2220bcd326aee3e86ddfd4ebd0fe58cb9\"@@@",
"@@@SET_BUILD_PROPERTY@got_cr_revision_cp@\"refs/heads/master@{#170242}\"@@@"
]
@ -64,21 +57,114 @@
"cmd": [
"python",
"-u",
"import sys;print \"Patch download failed. See bot_update step for details\";sys.exit(1)"
"import sys; sys.exit(1)"
],
"infra_step": true,
"name": "Patch failure - Try Rebasing",
"name": "Patch failure",
"~followup_annotations": [
"step returned non-zero exit code: 1",
"@@@STEP_LOG_LINE@python.inline@import sys;print \"Patch download failed. See bot_update step for details\";sys.exit(1)@@@",
"@@@STEP_LOG_END@python.inline@@@",
"@@@STEP_TEXT@Git reported a download failure@@@",
"@@@STEP_LOG_LINE@patch error@Downloading patch...@@@",
"@@@STEP_LOG_LINE@patch error@Applying the patch...@@@",
"@@@STEP_LOG_LINE@patch error@Patch: foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@Index: foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@diff --git a/foo/bar.py b/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@index HASH..HASH MODE@@@",
"@@@STEP_LOG_LINE@patch error@--- a/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@+++ b/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@context@@@",
"@@@STEP_LOG_LINE@patch error@+something@@@",
"@@@STEP_LOG_LINE@patch error@-something@@@",
"@@@STEP_LOG_LINE@patch error@more context@@@",
"@@@STEP_LOG_END@patch error@@@",
"@@@STEP_EXCEPTION@@@"
]
},
{
"cmd": [
"python",
"-u",
"RECIPE_MODULE[depot_tools::bot_update]/resources/bot_update.py",
"--spec",
"cache_dir = '[GIT_CACHE]'\nsolutions = [{'deps_file': '.DEPS.git', 'managed': True, 'name': 'src', 'url': 'https://chromium.googlesource.com/chromium/src.git'}]",
"--patch_root",
"src",
"--revision_mapping_file",
"{\"src\": \"got_cr_revision\"}",
"--git-cache-dir",
"[GIT_CACHE]",
"--rietveld_server",
"https://rietveld.example.com/",
"--output_json",
"/path/to/tmp/json",
"--revision",
"src@f27fede2220bcd326aee3e86ddfd4ebd0fe58cb9",
"--output_manifest"
],
"env": {
"GIT_HTTP_LOW_SPEED_LIMIT": "1000",
"GIT_HTTP_LOW_SPEED_TIME": "300",
"PATH": "%(PATH)s:RECIPE_PACKAGE_REPO[depot_tools]"
},
"infra_step": true,
"name": "bot_update (without patch)",
"~followup_annotations": [
"@@@STEP_TEXT@Some step text@@@",
"@@@STEP_LOG_LINE@json.output@{@@@",
"@@@STEP_LOG_LINE@json.output@ \"did_run\": true, @@@",
"@@@STEP_LOG_LINE@json.output@ \"failed_patch_body\": \"Downloading patch...\\nApplying the patch...\\nPatch: foo/bar.py\\nIndex: foo/bar.py\\ndiff --git a/foo/bar.py b/foo/bar.py\\nindex HASH..HASH MODE\\n--- a/foo/bar.py\\n+++ b/foo/bar.py\\ncontext\\n+something\\n-something\\nmore context\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"fixed_revisions\": {@@@",
"@@@STEP_LOG_LINE@json.output@ \"src\": \"f27fede2220bcd326aee3e86ddfd4ebd0fe58cb9\"@@@",
"@@@STEP_LOG_LINE@json.output@ }, @@@",
"@@@STEP_LOG_LINE@json.output@ \"manifest\": {@@@",
"@@@STEP_LOG_LINE@json.output@ \"src\": {@@@",
"@@@STEP_LOG_LINE@json.output@ \"repository\": \"https://fake.org/src.git\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"revision\": \"f27fede2220bcd326aee3e86ddfd4ebd0fe58cb9\"@@@",
"@@@STEP_LOG_LINE@json.output@ }@@@",
"@@@STEP_LOG_LINE@json.output@ }, @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_apply_return_code\": 3, @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_failure\": true, @@@",
"@@@STEP_LOG_LINE@json.output@ \"patch_root\": \"src\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"properties\": {@@@",
"@@@STEP_LOG_LINE@json.output@ \"got_cr_revision\": \"f27fede2220bcd326aee3e86ddfd4ebd0fe58cb9\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"got_cr_revision_cp\": \"refs/heads/master@{#170242}\"@@@",
"@@@STEP_LOG_LINE@json.output@ }, @@@",
"@@@STEP_LOG_LINE@json.output@ \"root\": \"src\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"step_text\": \"Some step text\"@@@",
"@@@STEP_LOG_LINE@json.output@}@@@",
"@@@STEP_LOG_END@json.output@@@"
]
},
{
"cmd": [
"python",
"-u",
"import sys; sys.exit(1)"
],
"infra_step": true,
"name": "Patch failure (2)",
"~followup_annotations": [
"step returned non-zero exit code: 1",
"@@@STEP_TEXT@Git reported a download failure@@@",
"@@@STEP_LOG_LINE@patch error@Downloading patch...@@@",
"@@@STEP_LOG_LINE@patch error@Applying the patch...@@@",
"@@@STEP_LOG_LINE@patch error@Patch: foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@Index: foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@diff --git a/foo/bar.py b/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@index HASH..HASH MODE@@@",
"@@@STEP_LOG_LINE@patch error@--- a/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@+++ b/foo/bar.py@@@",
"@@@STEP_LOG_LINE@patch error@context@@@",
"@@@STEP_LOG_LINE@patch error@+something@@@",
"@@@STEP_LOG_LINE@patch error@-something@@@",
"@@@STEP_LOG_LINE@patch error@more context@@@",
"@@@STEP_LOG_END@patch error@@@",
"@@@STEP_EXCEPTION@@@"
]
},
{
"name": "$result",
"reason": "Infra Failure: Step('Patch failure - Try Rebasing') returned 1",
"recipe_result": null,
"status_code": 1
"status_code": 0
}
]

@ -424,17 +424,6 @@ def get_commit_message_footer(message, key):
return get_commit_message_footer_map(message).get(key)
def emit_log_lines(name, lines):
for line in lines.splitlines():
print '@@@STEP_LOG_LINE@%s@%s@@@' % (name, line)
print '@@@STEP_LOG_END@%s@@@' % name
def emit_properties(properties):
for property_name, property_value in sorted(properties.items()):
print '@@@SET_BUILD_PROPERTY@%s@"%s"@@@' % (property_name, property_value)
# Derived from:
# http://code.activestate.com/recipes/577972-disk-usage/?in=user-4178764
def get_total_disk_space():
@ -1070,16 +1059,12 @@ def checkout(options, git_slns, specs, revisions, step_text, shallow):
emit_json(options.output_json,
did_run=True,
root=first_sln,
log_lines=[('patch error', e.output),],
patch_apply_return_code=e.code,
patch_root=options.patch_root,
patch_failure=True,
failed_patch_body=e.output,
step_text='%s PATCH FAILED' % step_text,
fixed_revisions=revisions)
else:
# If we're not on recipes, tell annotator about our got_revisions.
emit_log_lines('patch error', e.output)
print '@@@STEP_TEXT@%s PATCH FAILED@@@' % step_text
raise
# Take care of got_revisions outputs.
@ -1113,9 +1098,6 @@ def checkout(options, git_slns, specs, revisions, step_text, shallow):
fixed_revisions=revisions,
properties=got_revisions,
manifest=manifest)
else:
# If we're not on recipes, tell annotator about our got_revisions.
emit_properties(got_revisions)
def print_debug_info():

@ -50,8 +50,21 @@ class BotUpdateTestApi(recipe_test_api.RecipeTestApi):
output['fixed_revisions'] = fixed_revisions
if fail_patch:
output['log_lines'] = [('patch error', 'Patch failed to apply'),]
output['patch_failure'] = True
output['failed_patch_body'] = '\n'.join([
'Downloading patch...',
'Applying the patch...',
'Patch: foo/bar.py',
'Index: foo/bar.py',
'diff --git a/foo/bar.py b/foo/bar.py',
'index HASH..HASH MODE',
'--- a/foo/bar.py',
'+++ b/foo/bar.py',
'context',
'+something',
'-something',
'more context',
])
output['patch_apply_return_code'] = 1
if fail_patch == 'download':
output['patch_apply_return_code'] = 3

Loading…
Cancel
Save