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