• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2018 The Chromium OS 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"""Constants and util methods to interact with skylab inventory repo."""
6
7import logging
8import re
9
10import common
11
12from autotest_lib.client.common_lib import revision_control
13from chromite.lib import gob_util
14
15try:
16    from skylab_inventory import text_manager
17except ImportError:
18    pass
19
20
21INTERNAL_GERRIT_HOST = 'chrome-internal-review.googlesource.com'
22INTERNAL_GERRIT_HOST_URL = 'https://%s' % INTERNAL_GERRIT_HOST
23# The git url of the internal skylab_inventory
24INTERNAL_INVENTORY_REPO_URL = ('https://chrome-internal.googlesource.com/'
25                               'chromeos/infra_internal/skylab_inventory.git')
26INTERNAL_INVENTORY_CHANGE_PATTERN = (
27        r'https://chrome-internal-review.googlesource.com/c/chromeos/'
28        'infra_internal/skylab_inventory/\\+/([0-9]*)')
29MSG_INVALID_IN_SKYLAB = 'This is currently not supported with --skylab.'
30MSG_ONLY_VALID_IN_SKYLAB = 'This only applies to actions on skylab inventory.'
31
32
33class SkylabInventoryNotImported(Exception):
34    """skylab_inventory is not imported."""
35
36
37class InventoryRepoChangeNotFound(Exception):
38    """Error raised when no inventory repo change number is found."""
39
40
41class InventoryRepoDirNotClean(Exception):
42    """Error raised when the given inventory_repo_dir contains local changes."""
43
44
45def get_cl_url(change_number):
46    return INTERNAL_GERRIT_HOST_URL + '/' + str(change_number)
47
48
49def get_cl_message(change_number):
50    return ('Please submit the CL at %s to make the change effective.' %
51            get_cl_url(change_number))
52
53
54def construct_commit_message(subject, bug=None, test=None):
55    """Construct commit message for skylab inventory repo commit.
56
57    @param subject: Commit message subject.
58    @param bug: Bug number of the commit.
59    @param test: Tests of the commit.
60
61    @return: A commit message string.
62    """
63    return '\n'.join([subject, '', 'BUG=%s' % bug, 'TEST=%s' % test])
64
65
66def extract_inventory_change(output):
67    """Extract the change number from the output.
68
69    @param output: The git command output containing the change gerrit url.
70
71    @return: The change number (int) of the inventory change.
72    """
73    m = re.search(INTERNAL_INVENTORY_CHANGE_PATTERN, output)
74
75    if not m:
76        raise InventoryRepoChangeNotFound(
77                'Could not extract CL number from "%r"' % output)
78
79    return int(m.group(1))
80
81
82def submit_inventory_change(change_number):
83    """Set review labels and submit the inventory change.
84
85    @param change_number: The change number (int) of the inventory change.
86    """
87    logging.info('Setting review labels for %s.',
88                  get_cl_url(change_number))
89    gob_util.SetReview(
90        INTERNAL_GERRIT_HOST,
91        change=change_number,
92        labels={'Code-Review': 2, 'Verified': 1},
93        msg='Set TBR by "atest --skylab"',
94        notify='OWNER')
95
96    logging.info('Submitting the change.')
97    gob_util.SubmitChange(
98        INTERNAL_GERRIT_HOST,
99        change=change_number)
100
101
102class InventoryRepo(object):
103    """Class to present a inventory repository."""
104
105
106    def __init__(self, inventory_repo_dir):
107        self.inventory_repo_dir = inventory_repo_dir
108        self.git_repo = None
109
110
111    def initialize(self):
112        """Initialize inventory repo at the given dir."""
113        self.git_repo = revision_control.GitRepo(
114                self.inventory_repo_dir,
115                giturl=INTERNAL_INVENTORY_REPO_URL,
116                abs_work_tree=self.inventory_repo_dir)
117
118        if self.git_repo.is_repo_initialized():
119            if self.git_repo.status():
120                raise InventoryRepoDirNotClean(
121                       'The inventory_repo_dir "%s" contains uncommitted '
122                       'changes. Please clean up the local repo directory or '
123                       'use another clean directory.' % self.inventory_repo_dir)
124
125            logging.info('Inventory repo was already initialized, start '
126                         'pulling.')
127            self.git_repo.checkout('master')
128            self.git_repo.pull()
129        else:
130            logging.info('No inventory repo was found, start cloning.')
131            self.git_repo.clone(shallow=True)
132
133
134    def get_data_dir(self, data_subdir='skylab'):
135        """Get path to the data dir."""
136        return text_manager.get_data_dir(self.inventory_repo_dir, data_subdir)
137
138
139    def upload_change(self, commit_message, draft=False, dryrun=False,
140                      submit=False):
141        """Commit and upload the change to gerrit.
142
143        @param commit_message: Commit message of the CL to upload.
144        @param draft: Boolean indicating whether to upload the CL as a draft.
145        @param dryrun: Boolean indicating whether to run upload as a dryrun.
146        @param submit: Boolean indicating whether to submit the CL directly.
147
148        @return: Change number (int) of the CL if it's uploaded to Gerrit.
149        """
150        self.git_repo.commit(commit_message)
151
152        remote = self.git_repo.remote()
153        output = self.git_repo.upload_cl(
154                remote, 'master', draft=draft, dryrun=dryrun)
155
156        if not dryrun:
157            change_number = extract_inventory_change(output)
158
159            if submit:
160                submit_inventory_change(change_number)
161
162            return change_number
163