| 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 | |
| 13 import time | 12 import time |
| 14 | 13 |
| 15 from twisted.python import log | 14 from twisted.python import log |
| 16 | 15 |
| 17 from buildbot import interfaces, util | 16 from buildbot import interfaces, util |
| 18 from buildbot.process import buildstep | 17 from buildbot.process import buildstep |
| 19 from buildbot.process.properties import WithProperties | 18 from buildbot.process.properties import WithProperties |
| 20 from buildbot.status import builder | 19 from buildbot.status import builder |
| 21 from buildbot.steps import shell | 20 from buildbot.steps import shell |
| 22 from buildbot.steps import source | 21 from buildbot.steps import source |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 | 59 |
| 61 class GClient(source.Source): | 60 class GClient(source.Source): |
| 62 """Check out a source tree using gclient.""" | 61 """Check out a source tree using gclient.""" |
| 63 | 62 |
| 64 name = 'update' | 63 name = 'update' |
| 65 | 64 |
| 66 def __init__(self, svnurl=None, rm_timeout=None, gclient_spec=None, env=None, | 65 def __init__(self, svnurl=None, rm_timeout=None, gclient_spec=None, env=None, |
| 67 sudo_for_remove=False, gclient_deps=None, gclient_nohooks=False, | 66 sudo_for_remove=False, gclient_deps=None, gclient_nohooks=False, |
| 68 no_gclient_branch=False, no_gclient_revision=False, | 67 no_gclient_branch=False, no_gclient_revision=False, |
| 69 gclient_transitive=False, primary_repo=None, | 68 gclient_transitive=False, primary_repo=None, |
| 70 gclient_jobs=None, **kwargs): | 69 gclient_jobs=None, blink_config=None, **kwargs): |
| 70 # TODO: We shouldn't need to hard-code blink-specific info here. We |
| 71 # should figure out how to generalize this to sub-repos somehow. |
| 71 source.Source.__init__(self, **kwargs) | 72 source.Source.__init__(self, **kwargs) |
| 72 if env: | 73 if env: |
| 73 self.args['env'] = env.copy() | 74 self.args['env'] = env.copy() |
| 74 self.args['rm_timeout'] = rm_timeout | 75 self.args['rm_timeout'] = rm_timeout |
| 75 self.args['svnurl'] = svnurl | 76 self.args['svnurl'] = svnurl |
| 76 self.args['sudo_for_remove'] = sudo_for_remove | 77 self.args['sudo_for_remove'] = sudo_for_remove |
| 77 # linux doesn't handle spaces in command line args properly so remove them. | 78 # linux doesn't handle spaces in command line args properly so remove them. |
| 78 # This doesn't matter for the format of the DEPS file. | 79 # This doesn't matter for the format of the DEPS file. |
| 79 self.args['gclient_spec'] = gclient_spec.replace(' ', '') | 80 self.args['gclient_spec'] = gclient_spec.replace(' ', '') |
| 80 self.args['gclient_deps'] = gclient_deps | 81 self.args['gclient_deps'] = gclient_deps |
| 81 self.args['gclient_nohooks'] = gclient_nohooks | 82 self.args['gclient_nohooks'] = gclient_nohooks |
| 82 self.args['no_gclient_branch'] = no_gclient_branch | 83 self.args['no_gclient_branch'] = no_gclient_branch |
| 83 self.args['no_gclient_revision'] = no_gclient_revision | 84 self.args['no_gclient_revision'] = no_gclient_revision |
| 84 self.args['gclient_transitive'] = gclient_transitive | 85 self.args['gclient_transitive'] = gclient_transitive |
| 85 self.args['primary_repo'] = primary_repo or '' | 86 self.args['primary_repo'] = primary_repo or '' |
| 86 self.args['gclient_jobs'] = gclient_jobs | 87 self.args['gclient_jobs'] = gclient_jobs |
| 88 self.args['blink_config'] = blink_config |
| 87 | 89 |
| 88 def computeSourceRevision(self, changes): | 90 def computeSourceRevision(self, changes): |
| 89 """Finds the latest revision number from the changeset that have | 91 """Finds the latest revision number from the changeset that have |
| 90 triggered the build. | 92 triggered the build. |
| 91 | 93 |
| 92 This is a hook method provided by the parent source.Source class and | 94 This is a hook method provided by the parent source.Source class and |
| 93 default implementation in source.Source returns None. Return value of this | 95 default implementation in source.Source returns None. Return value of this |
| 94 method is be used to set 'revsion' argument value for startVC() method.""" | 96 method is be used to set 'revsion' argument value for startVC() method.""" |
| 95 if not changes: | 97 if not changes: |
| 96 return None | 98 return None |
| 97 # Change revision numbers can be invalid, for a try job for instance. | 99 # Change revision numbers can be invalid, for a try job for instance. |
| 98 # TODO(maruel): Make this work for git hash. | 100 # TODO(maruel): Make this work for git hash. |
| 99 lastChange = max([change_to_revision(c) for c in changes]) | 101 lastChange = max([change_to_revision(c) for c in changes]) |
| 100 return lastChange | 102 return lastChange |
| 101 | 103 |
| 102 def startVC(self, branch, revision, patch): | 104 def startVC(self, branch, revision, patch): |
| 103 warnings = [] | 105 warnings = [] |
| 104 args = copy.copy(self.args) | 106 args = copy.copy(self.args) |
| 105 wk_revision = None | 107 |
| 106 # branch == 'trunk' means the change came from the blink poller, and the | |
| 107 # revision is a blink revision. | |
| 108 if branch == 'trunk': | |
| 109 wk_revision = revision | |
| 110 try: | |
| 111 # parent_wk_revision might be set, but empty. | |
| 112 if self.getProperty('parent_wk_revision'): | |
| 113 wk_revision = self.getProperty('parent_wk_revision') | |
| 114 except KeyError: | |
| 115 pass | |
| 116 nacl_revision = revision | |
| 117 try: | |
| 118 # parent_nacl_revision might be set, but empty. | |
| 119 if self.getProperty('parent_got_nacl_revision'): | |
| 120 nacl_revision = self.getProperty('parent_got_nacl_revision') | |
| 121 except KeyError: | |
| 122 pass | |
| 123 try: | 108 try: |
| 124 # parent_cr_revision might be set, but empty. | 109 # parent_cr_revision might be set, but empty. |
| 125 if self.getProperty('parent_cr_revision'): | 110 if self.getProperty('parent_cr_revision'): |
| 126 revision = 'src@' + self.getProperty('parent_cr_revision') | 111 revision = 'src@' + self.getProperty('parent_cr_revision') |
| 127 except KeyError: | 112 except KeyError: |
| 128 pass | 113 pass |
| 129 self.setProperty('primary_repo', args['primary_repo'], 'Source') | 114 self.setProperty('primary_repo', args['primary_repo'], 'Source') |
| 130 args['revision'] = revision | 115 args['revision'] = revision |
| 131 args['branch'] = branch | 116 args['branch'] = branch |
| 117 |
| 132 if args.get('gclient_spec'): | 118 if args.get('gclient_spec'): |
| 133 args['gclient_spec'] = args['gclient_spec'].replace( | 119 self.adjustGclientSpecForBlink(branch, revision, args) |
| 134 '$$WK_REV$$', str(wk_revision or '')) | 120 self.adjustGclientSpecForNaCl(branch, revision, patch, args) |
| 135 args['gclient_spec'] = args['gclient_spec'].replace( | 121 |
| 136 '$$NACL_REV$$', str(nacl_revision or '')) | |
| 137 webkit_try_revision = None | |
| 138 if patch: | |
| 139 match = re.match(r'third_party/WebKit@(\w+)', patch[1]) | |
| 140 if match: | |
| 141 webkit_try_revision = match.group(1) | |
| 142 if webkit_try_revision: | |
| 143 args['gclient_spec'] = args['gclient_spec'].replace( | |
| 144 '$$WK_TRY_REV$$', webkit_try_revision) | |
| 145 else: | |
| 146 args['gclient_spec'] = args['gclient_spec'].replace( | |
| 147 ',"webkit_revision":"$$WK_TRY_REV$$"', '') | |
| 148 if patch: | 122 if patch: |
| 149 args['patch'] = patch | 123 args['patch'] = patch |
| 150 elif args.get('patch') is None: | 124 elif args.get('patch') is None: |
| 151 del args['patch'] | 125 del args['patch'] |
| 126 |
| 152 cmd = buildstep.LoggedRemoteCommand('gclient', args) | 127 cmd = buildstep.LoggedRemoteCommand('gclient', args) |
| 153 self.startCommand(cmd, warnings) | 128 self.startCommand(cmd, warnings) |
| 154 | 129 |
| 130 def adjustGclientSpecForBlink(self, branch, revision, args): |
| 131 # If the bot in question is a dedicated bot for Blink changes (either |
| 132 # on a waterfall, or a blink-specific trybot), we want to set a custom |
| 133 # version of Blink, otherwise we leave the gclient spec alone. |
| 134 if args['blink_config'] != 'blink': |
| 135 return |
| 136 |
| 137 # branch == 'trunk' means the change came from the blink poller, and the |
| 138 # revision is a blink revision; otherwise, we use '', or HEAD. |
| 139 wk_revision = '' |
| 140 if branch == 'trunk': |
| 141 wk_revision = revision |
| 142 |
| 143 try: |
| 144 # parent_wk_revision might be set, but empty. |
| 145 if self.getProperty('parent_wk_revision'): |
| 146 wk_revision = self.getProperty('parent_wk_revision') |
| 147 except KeyError: |
| 148 pass |
| 149 |
| 150 # TODO: Make this be something less fragile. |
| 151 args['gclient_spec'] = args['gclient_spec'].replace( |
| 152 '"webkit_trunk"', |
| 153 '"webkit_revision":"%s","webkit_trunk"' % wk_revision) |
| 154 |
| 155 def adjustGclientSpecForNaCl(self, branch, revision, patch, args): |
| 156 nacl_revision = revision |
| 157 try: |
| 158 # parent_nacl_revision might be set, but empty. |
| 159 if self.getProperty('parent_got_nacl_revision'): |
| 160 nacl_revision = self.getProperty('parent_got_nacl_revision') |
| 161 except KeyError: |
| 162 pass |
| 163 args['gclient_spec'] = args['gclient_spec'].replace( |
| 164 '$$NACL_REV$$', str(nacl_revision or '')) |
| 165 |
| 155 def describe(self, done=False): | 166 def describe(self, done=False): |
| 156 """Tries to append the revision number to the description.""" | 167 """Tries to append the revision number to the description.""" |
| 157 description = source.Source.describe(self, done) | 168 description = source.Source.describe(self, done) |
| 158 self.appendChromeRevision(description) | 169 self.appendChromeRevision(description) |
| 159 self.appendWebKitRevision(description) | 170 self.appendWebKitRevision(description) |
| 160 self.appendNaClRevision(description) | 171 self.appendNaClRevision(description) |
| 161 self.appendV8Revision(description) | 172 self.appendV8Revision(description) |
| 162 return description | 173 return description |
| 163 | 174 |
| 164 def appendChromeRevision(self, description): | 175 def appendChromeRevision(self, description): |
| (...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1076 def evaluateCommand(self, cmd): | 1087 def evaluateCommand(self, cmd): |
| 1077 observer_result = self.script_observer.annotate_status | 1088 observer_result = self.script_observer.annotate_status |
| 1078 # Check if ProcessLogShellStep detected a failure or warning also. | 1089 # Check if ProcessLogShellStep detected a failure or warning also. |
| 1079 log_processor_result = ProcessLogShellStep.evaluateCommand(self, cmd) | 1090 log_processor_result = ProcessLogShellStep.evaluateCommand(self, cmd) |
| 1080 return BuilderStatus.combine(observer_result, log_processor_result) | 1091 return BuilderStatus.combine(observer_result, log_processor_result) |
| 1081 | 1092 |
| 1082 def commandComplete(self, cmd): | 1093 def commandComplete(self, cmd): |
| 1083 self.script_observer.handleReturnCode(cmd.rc) | 1094 self.script_observer.handleReturnCode(cmd.rc) |
| 1084 self._removePreamble() | 1095 self._removePreamble() |
| 1085 return ProcessLogShellStep.commandComplete(self, cmd) | 1096 return ProcessLogShellStep.commandComplete(self, cmd) |
| OLD | NEW |