| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Subclasses of various slave command classes.""" | 5 """Subclasses of various slave command classes.""" |
| 6 | 6 |
| 7 import copy | 7 import copy |
| 8 import errno | 8 import errno |
| 9 import json | 9 import json |
| 10 import logging | 10 import logging |
| 11 import os | 11 import os |
| 12 import re | 12 import re |
| 13 import time | 13 import time |
| 14 | 14 |
| 15 from twisted.python import log | 15 from twisted.python import log |
| 16 | 16 |
| 17 from buildbot import interfaces, util | 17 from buildbot import interfaces, util |
| 18 from buildbot.process import buildstep | 18 from buildbot.process import buildstep |
| 19 from buildbot.process.properties import WithProperties | 19 from buildbot.process.properties import WithProperties |
| 20 from buildbot.status import builder | 20 from buildbot.status import builder |
| 21 from buildbot.steps import shell | 21 from buildbot.steps import shell |
| 22 from buildbot.steps import source | 22 from buildbot.steps import source |
| 23 from buildbot.process.buildstep import LoggingBuildStep | 23 from buildbot.process.buildstep import LoggingBuildStep |
| 24 | 24 |
| 25 from common import annotator |
| 25 from common import chromium_utils | 26 from common import chromium_utils |
| 26 import config | 27 import config |
| 27 | 28 |
| 28 | 29 |
| 29 def change_to_revision(c): | 30 def change_to_revision(c): |
| 30 """Handle revision == None or any invalid value.""" | 31 """Handle revision == None or any invalid value.""" |
| 31 try: | 32 try: |
| 32 return int(str(c.revision).split('@')[-1]) | 33 return int(str(c.revision).split('@')[-1]) |
| 33 except (ValueError, TypeError): | 34 except (ValueError, TypeError): |
| 34 return 0 | 35 return 0 |
| (...skipping 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 # windows agents, but not others. | 850 # windows agents, but not others. |
| 850 if not line.endswith('\n'): | 851 if not line.endswith('\n'): |
| 851 line += '\n' | 852 line += '\n' |
| 852 # Handle initial setup here, as step_status might not exist yet at init. | 853 # Handle initial setup here, as step_status might not exist yet at init. |
| 853 self.initialSection() | 854 self.initialSection() |
| 854 | 855 |
| 855 | 856 |
| 856 # Support: @@@STEP_LOG_LINE@<label>@<line>@@@ (add log to step) | 857 # Support: @@@STEP_LOG_LINE@<label>@<line>@@@ (add log to step) |
| 857 # Appends a line to the log's array. When STEP_LOG_END is called, | 858 # Appends a line to the log's array. When STEP_LOG_END is called, |
| 858 # that will finalize the log and call addCompleteLog(). | 859 # that will finalize the log and call addCompleteLog(). |
| 859 m = re.match('^@@@STEP_LOG_LINE@(.*)@(.*)@@@', line) | 860 m = annotator.Match.log_line(line) |
| 860 if m: | 861 if m: |
| 861 log_label = m.group(1) | 862 log_label = m[0] |
| 862 log_line = m.group(2) | 863 log_line = m[1] |
| 863 current_logs = self.cursor['annotated_logs'] | 864 current_logs = self.cursor['annotated_logs'] |
| 864 current_logs[log_label] = current_logs.get(log_label, []) + [log_line] | 865 current_logs[log_label] = current_logs.get(log_label, []) + [log_line] |
| 865 | 866 |
| 866 # Support: @@@STEP_LOG_END@<label>@<line>@@@ (finalizes log to step) | 867 # Support: @@@STEP_LOG_END@<label>@<line>@@@ (finalizes log to step) |
| 867 m = re.match('^@@@STEP_LOG_END@(.*)@@@', line) | 868 m = annotator.Match.log_end(line) |
| 868 if m: | 869 if m: |
| 869 log_label = m.group(1) | 870 log_label = m[0] |
| 870 current_logs = self.cursor['annotated_logs'] | 871 current_logs = self.cursor['annotated_logs'] |
| 871 log_text = '\n'.join(current_logs.get(log_label, [])) | 872 log_text = '\n'.join(current_logs.get(log_label, [])) |
| 872 addLogToStep(self.cursor['step'], log_label, log_text) | 873 addLogToStep(self.cursor['step'], log_label, log_text) |
| 873 | 874 |
| 874 # Support: @@@STEP_LOG_END_PERF@<label>@<line>@@@ | 875 # Support: @@@STEP_LOG_END_PERF@<label>@<line>@@@ |
| 875 # (finalizes log to step, marks it as being a perf step | 876 # (finalizes log to step, marks it as being a perf step |
| 876 # requiring logs to be stored on the master) | 877 # requiring logs to be stored on the master) |
| 877 m = re.match('^@@@STEP_LOG_END_PERF@(.*)@(.*)@@@', line) | 878 m = annotator.Match.log_end_perf(line) |
| 878 if m: | 879 if m: |
| 879 log_label = m.group(1) | 880 log_label = m[0] |
| 880 perf_dashboard_name = m.group(2) | 881 perf_dashboard_name = m[1] |
| 881 current_logs = self.cursor['annotated_logs'] | 882 current_logs = self.cursor['annotated_logs'] |
| 882 log_text = '\n'.join(current_logs.get(log_label, [])) + '\n' | 883 log_text = '\n'.join(current_logs.get(log_label, [])) + '\n' |
| 883 | 884 |
| 884 report_link = None | 885 report_link = None |
| 885 output_dir = None | 886 output_dir = None |
| 886 if self.perf_id: | 887 if self.perf_id: |
| 887 report_link, output_dir, _ = self._PerfStepMappings( | 888 report_link, output_dir, _ = self._PerfStepMappings( |
| 888 self.show_perf, self.perf_id, perf_dashboard_name, | 889 self.show_perf, self.perf_id, perf_dashboard_name, |
| 889 self.perf_report_url_suffix) | 890 self.perf_report_url_suffix) |
| 890 if report_link: | 891 if report_link: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 903 | 904 |
| 904 if report_link and output_dir: | 905 if report_link and output_dir: |
| 905 MakeOutputDirectory(output_dir) | 906 MakeOutputDirectory(output_dir) |
| 906 if log_label == self.GRAPH_LIST: | 907 if log_label == self.GRAPH_LIST: |
| 907 self._SaveGraphInfo(log_text, output_dir) | 908 self._SaveGraphInfo(log_text, output_dir) |
| 908 else: | 909 else: |
| 909 Prepend(log_label, log_text, output_dir, perf_output_dir) | 910 Prepend(log_label, log_text, output_dir, perf_output_dir) |
| 910 | 911 |
| 911 # Support: @@@STEP_LINK@<name>@<url>@@@ (emit link) | 912 # Support: @@@STEP_LINK@<name>@<url>@@@ (emit link) |
| 912 # Also support depreceated @@@link@<name>@<url>@@@ | 913 # Also support depreceated @@@link@<name>@<url>@@@ |
| 913 m = re.match('^@@@STEP_LINK@(.*)@(.*)@@@', line) | 914 m = annotator.Match.step_link(line) |
| 914 if not m: | |
| 915 m = re.match('^@@@link@(.*)@(.*)@@@', line) | |
| 916 if m: | 915 if m: |
| 917 link_label = m.group(1) | 916 link_label = m[0] |
| 918 link_url = m.group(2) | 917 link_url = m[1] |
| 919 self.addLinkToCursor(link_label, link_url) | 918 self.addLinkToCursor(link_label, link_url) |
| 920 # Support: @@@STEP_STARTED@@@ (start a step at cursor) | 919 # Support: @@@STEP_STARTED@@@ (start a step at cursor) |
| 921 if line.startswith('@@@STEP_STARTED@@@'): | 920 if annotator.Match.step_started(line): |
| 922 self.startStep(self.cursor) | 921 self.startStep(self.cursor) |
| 923 # Support: @@@STEP_CLOSED@@@ | 922 # Support: @@@STEP_CLOSED@@@ |
| 924 if line.startswith('@@@STEP_CLOSED@@@'): | 923 if annotator.Match.step_closed(line): |
| 925 self.finishCursor() | 924 self.finishCursor() |
| 926 self.cursor = self.sections[0] | 925 self.cursor = self.sections[0] |
| 927 # Support: @@@STEP_WARNINGS@@@ (warn on a stage) | 926 # Support: @@@STEP_WARNINGS@@@ (warn on a stage) |
| 928 # Also support deprecated @@@BUILD_WARNINGS@@@ | 927 # Also support deprecated @@@BUILD_WARNINGS@@@ |
| 929 if (line.startswith('@@@STEP_WARNINGS@@@') or | 928 if annotator.Match.step_warnings(line): |
| 930 line.startswith('@@@BUILD_WARNINGS@@@')): | |
| 931 self.updateStepStatus(builder.WARNINGS) | 929 self.updateStepStatus(builder.WARNINGS) |
| 932 # Support: @@@STEP_FAILURE@@@ (fail a stage) | 930 # Support: @@@STEP_FAILURE@@@ (fail a stage) |
| 933 # Also support deprecated @@@BUILD_FAILED@@@ | 931 # Also support deprecated @@@BUILD_FAILED@@@ |
| 934 if (line.startswith('@@@STEP_FAILURE@@@') or | 932 if annotator.Match.step_failure(line): |
| 935 line.startswith('@@@BUILD_FAILED@@@')): | |
| 936 self.updateStepStatus(builder.FAILURE) | 933 self.updateStepStatus(builder.FAILURE) |
| 937 # Support: @@@STEP_EXCEPTION@@@ (exception on a stage) | 934 # Support: @@@STEP_EXCEPTION@@@ (exception on a stage) |
| 938 # Also support deprecated @@@BUILD_FAILED@@@ | 935 # Also support deprecated @@@BUILD_FAILED@@@ |
| 939 if (line.startswith('@@@STEP_EXCEPTION@@@') or | 936 if annotator.Match.step_exception(line): |
| 940 line.startswith('@@@BUILD_EXCEPTION@@@')): | |
| 941 self.updateStepStatus(builder.EXCEPTION) | 937 self.updateStepStatus(builder.EXCEPTION) |
| 942 # Support: @@@HALT_ON_FAILURE@@@ (halt if a step fails immediately) | 938 # Support: @@@HALT_ON_FAILURE@@@ (halt if a step fails immediately) |
| 943 if line.startswith('@@@HALT_ON_FAILURE@@@'): | 939 if annotator.Match.halt_on_failure(line): |
| 944 self.halt_on_failure = True | 940 self.halt_on_failure = True |
| 945 # Support: @@@HONOR_ZERO_RETURN_CODE@@@ (succeed on 0 return, even if some | 941 # Support: @@@HONOR_ZERO_RETURN_CODE@@@ (succeed on 0 return, even if some |
| 946 # steps have failed) | 942 # steps have failed) |
| 947 if line.startswith('@@@HONOR_ZERO_RETURN_CODE@@@'): | 943 if annotator.Match.honor_zero_return_code(line): |
| 948 self.honor_zero_return_code = True | 944 self.honor_zero_return_code = True |
| 949 # Support: @@@STEP_CLEAR@@@ (reset step description) | 945 # Support: @@@STEP_CLEAR@@@ (reset step description) |
| 950 if line.startswith('@@@STEP_CLEAR@@@'): | 946 if annotator.Match.step_clear(line): |
| 951 self.cursor['step_text'] = [] | 947 self.cursor['step_text'] = [] |
| 952 self.updateCursorText() | 948 self.updateCursorText() |
| 953 # Support: @@@STEP_SUMMARY_CLEAR@@@ (reset step summary) | 949 # Support: @@@STEP_SUMMARY_CLEAR@@@ (reset step summary) |
| 954 if line.startswith('@@@STEP_SUMMARY_CLEAR@@@'): | 950 if annotator.Match.step_summary_clear(line): |
| 955 self.cursor['step_summary_text'] = [] | 951 self.cursor['step_summary_text'] = [] |
| 956 self.updateCursorText() | 952 self.updateCursorText() |
| 957 # Support: @@@STEP_TEXT@<msg>@@@ | 953 # Support: @@@STEP_TEXT@<msg>@@@ |
| 958 m = re.match('^@@@STEP_TEXT@(.*)@@@', line) | 954 m = annotator.Match.step_text(line) |
| 959 if m: | 955 if m: |
| 960 self.cursor['step_text'].append(m.group(1)) | 956 self.cursor['step_text'].append(m[0]) |
| 961 self.updateCursorText() | 957 self.updateCursorText() |
| 962 # Support: @@@STEP_SUMMARY_TEXT@<msg>@@@ | 958 # Support: @@@STEP_SUMMARY_TEXT@<msg>@@@ |
| 963 m = re.match('^@@@STEP_SUMMARY_TEXT@(.*)@@@', line) | 959 m = annotator.Match.step_summary_text(line) |
| 964 if m: | 960 if m: |
| 965 self.cursor['step_summary_text'].append(m.group(1)) | 961 self.cursor['step_summary_text'].append(m[0]) |
| 966 self.updateCursorText() | 962 self.updateCursorText() |
| 967 # Support: @@@SEED_STEP <stepname>@@@ (seed a new section) | 963 # Support: @@@SEED_STEP <stepname>@@@ (seed a new section) |
| 968 m = re.match('^@@@SEED_STEP (.*)@@@', line) | 964 m = annotator.Match.seed_step(line) |
| 969 if m: | 965 if m: |
| 970 step_name = m.group(1) | 966 step_name = m[0] |
| 971 # Add new one. | 967 # Add new one. |
| 972 self.addSection(step_name) | 968 self.addSection(step_name) |
| 973 # Support: @@@STEP_CURSOR <stepname>@@@ (set cursor to specified section) | 969 # Support: @@@STEP_CURSOR <stepname>@@@ (set cursor to specified section) |
| 974 m = re.match('^@@@STEP_CURSOR (.*)@@@', line) | 970 m = annotator.Match.step_cursor(line) |
| 975 if m: | 971 if m: |
| 976 step_name = m.group(1) | 972 step_name = m[0] |
| 977 self.cursor = self.lookupCursor(step_name) | 973 self.cursor = self.lookupCursor(step_name) |
| 978 # Support: @@@BUILD_STEP <step_name>@@@ (start a new section) | 974 # Support: @@@BUILD_STEP <step_name>@@@ (start a new section) |
| 979 m = re.match('^@@@BUILD_STEP (.*)@@@', line) | 975 m = annotator.Match.build_step(line) |
| 980 if m: | 976 if m: |
| 981 step_name = m.group(1) | 977 step_name = m[0] |
| 982 # Ignore duplicate consecutive step labels (for robustness). | 978 # Ignore duplicate consecutive step labels (for robustness). |
| 983 if step_name != self.sections[-1]['name']: | 979 if step_name != self.sections[-1]['name']: |
| 984 # Finish up last section. | 980 # Finish up last section. |
| 985 self.finishCursor() | 981 self.finishCursor() |
| 986 section = self.addSection(step_name) | 982 section = self.addSection(step_name) |
| 987 self.startStep(section) | 983 self.startStep(section) |
| 988 self.cursor = section | 984 self.cursor = section |
| 989 | 985 |
| 990 def handleReturnCode(self, return_code): | 986 def handleReturnCode(self, return_code): |
| 991 # Treat all non-zero return codes as failure. | 987 # Treat all non-zero return codes as failure. |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1076 def evaluateCommand(self, cmd): | 1072 def evaluateCommand(self, cmd): |
| 1077 observer_result = self.script_observer.annotate_status | 1073 observer_result = self.script_observer.annotate_status |
| 1078 # Check if ProcessLogShellStep detected a failure or warning also. | 1074 # Check if ProcessLogShellStep detected a failure or warning also. |
| 1079 log_processor_result = ProcessLogShellStep.evaluateCommand(self, cmd) | 1075 log_processor_result = ProcessLogShellStep.evaluateCommand(self, cmd) |
| 1080 return BuilderStatus.combine(observer_result, log_processor_result) | 1076 return BuilderStatus.combine(observer_result, log_processor_result) |
| 1081 | 1077 |
| 1082 def commandComplete(self, cmd): | 1078 def commandComplete(self, cmd): |
| 1083 self.script_observer.handleReturnCode(cmd.rc) | 1079 self.script_observer.handleReturnCode(cmd.rc) |
| 1084 self._removePreamble() | 1080 self._removePreamble() |
| 1085 return ProcessLogShellStep.commandComplete(self, cmd) | 1081 return ProcessLogShellStep.commandComplete(self, cmd) |
| OLD | NEW |