| # coding=utf8 |
| # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Runs presubmit check on the source tree.""" |
| |
| import logging |
| import os |
| import sys |
| import time |
| |
| from verification import base |
| |
| import find_depot_tools # pylint: disable=W0611 |
| import subprocess2 |
| |
| |
| class PresubmitCheckVerifier(base.VerifierCheckout): |
| name = 'presubmit' |
| |
| def __init__(self, context_obj, timeout=6*60): |
| super(PresubmitCheckVerifier, self).__init__(context_obj) |
| self.root_dir = os.path.dirname(os.path.abspath(__file__)) |
| self.execution_timeout = timeout |
| |
| def verify(self, pending): |
| """Runs the presubmit script synchronously. |
| |
| TODO(maruel): Now that it runs out of process, it should be run |
| asynchronously. That means that the PRESUBMIT checks needs to be better |
| written, if an integration tests starts a service, it needs to be able to |
| use an ephemeral port and not an hardcoded port. |
| """ |
| logging.info('Presubmit check for %s' % ','.join(pending.files)) |
| cmd = [ |
| sys.executable, |
| os.path.join(self.root_dir, 'presubmit_shim.py'), |
| '--commit', |
| '--author', str(pending.owner), |
| '--issue', str(pending.issue), |
| '--patchset', str(pending.patchset), |
| '--name', pending.pending_name(), |
| '--description', pending.description, |
| '--rietveld_url', self.context.rietveld.url, |
| ] |
| cmd.extend(pending.files) |
| start = time.time() |
| self.send_status(pending, {}) |
| |
| # Disable breakpad, no need to notify maintainers on internal crashes. |
| env = os.environ.copy() |
| env['NO_BREAKPAD'] = '1' |
| |
| try: |
| # Do not pass them through the command line. |
| data = '%s\n%s\n' % ( |
| self.context.rietveld.email, self.context.rietveld.password) |
| # Use check_output() so stdout is kept when an exception is thrown. |
| output = subprocess2.check_output( |
| cmd, |
| timeout=self.execution_timeout, |
| stderr=subprocess2.STDOUT, |
| stdin=data, |
| env=env, |
| preexec_fn=os.setpgrp) |
| pending.verifications[self.name] = base.SimpleStatus(state=base.SUCCEEDED) |
| self.send_status( |
| pending, |
| { |
| 'duration': time.time() - start, |
| 'output': output, |
| }) |
| except subprocess2.CalledProcessError as e: |
| output = ( |
| 'Presubmit check for %s failed and returned exit status %s.\n') % ( |
| pending.pending_name(), e.returncode) |
| duration = time.time() - start |
| timed_out = duration > self.execution_timeout |
| if timed_out: |
| output += ( |
| 'The presubmit check was hung. It took %2.1f seconds to execute ' |
| 'and the time limit is %2.1f seconds.\n') % ( |
| duration, self.execution_timeout) |
| output += '\n%s' % e.stdout |
| pending.verifications[self.name] = base.SimpleStatus( |
| state=base.FAILED, error_message=output) |
| self.send_status( |
| pending, |
| { |
| 'duration': duration, |
| 'output': e.stdout, |
| 'return': e.returncode, |
| 'timed_out': timed_out, |
| }) |
| |
| def update_status(self, queue): |
| pass |