Home | History | Annotate | Download | only in upload_dm_results
      1 # Copyright 2016 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 
      6 # Recipe for uploading DM results.
      7 
      8 
      9 
     10 import calendar
     11 
     12 from recipe_engine import recipe_api
     13 
     14 
     15 DM_JSON = 'dm.json'
     16 UPLOAD_ATTEMPTS = 5
     17 VERBOSE_LOG = 'verbose.log'
     18 
     19 
     20 class UploadDmResultsApi(recipe_api.RecipeApi):
     21   def cp(self, name, src, dst, extra_args=None):
     22     cmd = ['gsutil', 'cp']
     23     if extra_args:
     24       cmd.extend(extra_args)
     25     cmd.extend([src, dst])
     26 
     27     name = 'upload %s' % name
     28     for i in xrange(UPLOAD_ATTEMPTS):
     29       step_name = name
     30       if i > 0:
     31         step_name += ' (attempt %d)' % (i+1)
     32       try:
     33         self.m.step(step_name, cmd=cmd)
     34         break
     35       except self.m.step.StepFailure:
     36         if i == UPLOAD_ATTEMPTS - 1:
     37           raise
     38 
     39   def run(self):
     40     builder_name = self.m.properties['buildername']
     41     revision = self.m.properties['revision']
     42 
     43     results_dir = self.m.path['start_dir'].join('dm')
     44 
     45     # Move dm.json and verbose.log to their own directory.
     46     json_file = results_dir.join(DM_JSON)
     47     log_file = results_dir.join(VERBOSE_LOG)
     48     tmp_dir = self.m.path['start_dir'].join('tmp_upload')
     49     self.m.shutil.makedirs('tmp dir', tmp_dir, infra_step=True)
     50     self.m.shutil.copy('copy dm.json', json_file, tmp_dir)
     51     self.m.shutil.copy('copy verbose.log', log_file, tmp_dir)
     52     self.m.shutil.remove('rm old dm.json', json_file)
     53     self.m.shutil.remove('rm old verbose.log', log_file)
     54 
     55     # Upload the images.
     56     image_dest_path = 'gs://%s/dm-images-v1' % self.m.properties['gs_bucket']
     57     files_to_upload = self.m.file.glob(
     58         'find images',
     59         results_dir.join('*'),
     60         test_data=[results_dir.join('someimage.png')],
     61         infra_step=True)
     62     if len(files_to_upload) > 0:
     63       self.cp('images', results_dir.join('*'), image_dest_path)
     64 
     65     # Upload the JSON summary and verbose.log.
     66     now = self.m.time.utcnow()
     67     summary_dest_path = '/'.join([
     68         'dm-json-v1',
     69         str(now.year ).zfill(4),
     70         str(now.month).zfill(2),
     71         str(now.day  ).zfill(2),
     72         str(now.hour ).zfill(2),
     73         revision,
     74         builder_name,
     75         str(int(calendar.timegm(now.utctimetuple())))])
     76 
     77     # Trybot results are further siloed by issue/patchset.
     78     issue = str(self.m.properties.get('issue', ''))
     79     patchset = str(self.m.properties.get('patchset', ''))
     80     if self.m.properties.get('patch_storage', '') == 'gerrit':
     81       issue = str(self.m.properties['patch_issue'])
     82       patchset = str(self.m.properties['patch_set'])
     83     if issue and patchset:
     84       summary_dest_path = '/'.join((
     85           'trybot', summary_dest_path, issue, patchset))
     86 
     87     summary_dest_path = 'gs://%s/%s' % (self.m.properties['gs_bucket'],
     88                                         summary_dest_path)
     89 
     90     self.cp('JSON and logs', tmp_dir.join('*'), summary_dest_path,
     91        ['-z', 'json,log'])
     92