Home | History | Annotate | Download | only in buildbot
      1 #!/usr/bin/env python
      2 # Copyright (c) 2012 Google Inc. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 
      7 """Argument-less script to select what to run on the buildbots."""
      8 
      9 
     10 import os
     11 import shutil
     12 import subprocess
     13 import sys
     14 
     15 
     16 if sys.platform in ['win32', 'cygwin']:
     17   EXE_SUFFIX = '.exe'
     18 else:
     19   EXE_SUFFIX = ''
     20 
     21 
     22 BUILDBOT_DIR = os.path.dirname(os.path.abspath(__file__))
     23 TRUNK_DIR = os.path.dirname(BUILDBOT_DIR)
     24 ROOT_DIR = os.path.dirname(TRUNK_DIR)
     25 ANDROID_DIR = os.path.join(ROOT_DIR, 'android')
     26 OUT_DIR = os.path.join(TRUNK_DIR, 'out')
     27 
     28 
     29 def CallSubProcess(*args, **kwargs):
     30   """Wrapper around subprocess.call which treats errors as build exceptions."""
     31   retcode = subprocess.call(*args, **kwargs)
     32   if retcode != 0:
     33     print '@@@STEP_EXCEPTION@@@'
     34     sys.exit(1)
     35 
     36 
     37 def PrepareAndroidTree():
     38   """Prepare an Android tree to run 'android' format tests."""
     39   if os.environ['BUILDBOT_CLOBBER'] == '1':
     40     print '@@@BUILD_STEP Clobber Android checkout@@@'
     41     shutil.rmtree(ANDROID_DIR)
     42 
     43   # The release of Android we use is static, so there's no need to do anything
     44   # if the directory already exists.
     45   if os.path.isdir(ANDROID_DIR):
     46     return
     47 
     48   print '@@@BUILD_STEP Initialize Android checkout@@@'
     49   os.mkdir(ANDROID_DIR)
     50   CallSubProcess(['git', 'config', '--global', 'user.name', 'trybot'])
     51   CallSubProcess(['git', 'config', '--global',
     52                   'user.email', 'chrome-bot (at] google.com'])
     53   CallSubProcess(['git', 'config', '--global', 'color.ui', 'false'])
     54   CallSubProcess(
     55       ['repo', 'init',
     56        '-u', 'https://android.googlesource.com/platform/manifest',
     57        '-b', 'android-4.2.1_r1',
     58        '-g', 'all,-notdefault,-device,-darwin,-mips,-x86'],
     59       cwd=ANDROID_DIR)
     60 
     61   print '@@@BUILD_STEP Sync Android@@@'
     62   CallSubProcess(['repo', 'sync', '-j4'], cwd=ANDROID_DIR)
     63 
     64   print '@@@BUILD_STEP Build Android@@@'
     65   CallSubProcess(
     66       ['/bin/bash',
     67        '-c', 'source build/envsetup.sh && lunch full-eng && make -j4'],
     68       cwd=ANDROID_DIR)
     69 
     70 
     71 def GypTestFormat(title, format=None, msvs_version=None):
     72   """Run the gyp tests for a given format, emitting annotator tags.
     73 
     74   See annotator docs at:
     75     https://sites.google.com/a/chromium.org/dev/developers/testing/chromium-build-infrastructure/buildbot-annotations
     76   Args:
     77     format: gyp format to test.
     78   Returns:
     79     0 for sucesss, 1 for failure.
     80   """
     81   if not format:
     82     format = title
     83 
     84   print '@@@BUILD_STEP ' + title + '@@@'
     85   sys.stdout.flush()
     86   env = os.environ.copy()
     87   if msvs_version:
     88     env['GYP_MSVS_VERSION'] = msvs_version
     89   command = ' '.join(
     90       [sys.executable, 'trunk/gyptest.py',
     91        '--all',
     92        '--passed',
     93        '--format', format,
     94        '--chdir', 'trunk'])
     95   if format == 'android':
     96     # gyptest needs the environment setup from envsetup/lunch in order to build
     97     # using the 'android' backend, so this is done in a single shell.
     98     retcode = subprocess.call(
     99         ['/bin/bash',
    100          '-c', 'source build/envsetup.sh && lunch full-eng && cd %s && %s'
    101          % (ROOT_DIR, command)],
    102         cwd=ANDROID_DIR, env=env)
    103   else:
    104     retcode = subprocess.call(command, cwd=ROOT_DIR, env=env, shell=True)
    105   if retcode:
    106     # Emit failure tag, and keep going.
    107     print '@@@STEP_FAILURE@@@'
    108     return 1
    109   return 0
    110 
    111 
    112 def GypBuild():
    113   # Dump out/ directory.
    114   print '@@@BUILD_STEP cleanup@@@'
    115   print 'Removing %s...' % OUT_DIR
    116   shutil.rmtree(OUT_DIR, ignore_errors=True)
    117   print 'Done.'
    118 
    119   retcode = 0
    120   # The Android gyp bot runs on linux so this must be tested first.
    121   if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-android':
    122     PrepareAndroidTree()
    123     retcode += GypTestFormat('android')
    124   elif sys.platform.startswith('linux'):
    125     retcode += GypTestFormat('ninja')
    126     retcode += GypTestFormat('make')
    127   elif sys.platform == 'darwin':
    128     retcode += GypTestFormat('ninja')
    129     retcode += GypTestFormat('xcode')
    130     retcode += GypTestFormat('make')
    131   elif sys.platform == 'win32':
    132     retcode += GypTestFormat('ninja')
    133     if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-win64':
    134       retcode += GypTestFormat('msvs-2010', format='msvs', msvs_version='2010')
    135       retcode += GypTestFormat('msvs-2012', format='msvs', msvs_version='2012')
    136   else:
    137     raise Exception('Unknown platform')
    138   if retcode:
    139     # TODO(bradnelson): once the annotator supports a postscript (section for
    140     #     after the build proper that could be used for cumulative failures),
    141     #     use that instead of this. This isolates the final return value so
    142     #     that it isn't misattributed to the last stage.
    143     print '@@@BUILD_STEP failures@@@'
    144     sys.exit(retcode)
    145 
    146 
    147 if __name__ == '__main__':
    148   GypBuild()
    149