• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
10import calendar
11
12from recipe_engine import recipe_api
13
14
15DM_JSON = 'dm.json'
16UPLOAD_ATTEMPTS = 5
17VERBOSE_LOG = 'verbose.log'
18
19
20class 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