aboutsummaryrefslogtreecommitdiff
path: root/llvm_tools
diff options
context:
space:
mode:
authorManoj Gupta <manojgupta@google.com>2020-04-01 18:06:07 -0700
committerManoj Gupta <manojgupta@chromium.org>2020-04-02 16:05:18 +0000
commit58582262e483c0909f98f429225cb2498d086143 (patch)
treebc565dcc74474f80310dee7e59af94b5f5677045 /llvm_tools
parent5a1fd9fb57f00498eb301b5e2c685f0509367e56 (diff)
downloadtoolchain-utils-58582262e483c0909f98f429225cb2498d086143.tar.gz
llvm_tools: Add tool for CQ dry run for update CL
Add tool to update packages and start a CQ dry run on the CL and its dependencies. BUG=chromium:1067029 TEST=unit tests Change-Id: I593b7ee40985d9146f9d16f3e3e7d64bdeb8727a Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/2133242 Tested-by: Manoj Gupta <manojgupta@chromium.org> Reviewed-by: George Burgess <gbiv@chromium.org>
Diffstat (limited to 'llvm_tools')
-rwxr-xr-xllvm_tools/update_packages_and_test_cq.py196
-rwxr-xr-xllvm_tools/update_packages_and_test_cq_unittest.py130
2 files changed, 326 insertions, 0 deletions
diff --git a/llvm_tools/update_packages_and_test_cq.py b/llvm_tools/update_packages_and_test_cq.py
new file mode 100755
index 00000000..0e5e409b
--- /dev/null
+++ b/llvm_tools/update_packages_and_test_cq.py
@@ -0,0 +1,196 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs CQ dry run after updating the packages."""
+
+from __future__ import print_function
+
+import argparse
+import datetime
+import json
+import os
+
+from assert_not_in_chroot import VerifyOutsideChroot
+from failure_modes import FailureModes
+from get_llvm_hash import GetLLVMHashAndVersionFromSVNOption
+from get_llvm_hash import is_svn_option
+from subprocess_helpers import ChrootRunCommand
+from subprocess_helpers import ExecCommandAndCaptureOutput
+import update_chromeos_llvm_hash
+
+
+def GetCommandLineArgs():
+ """Parses the command line for the command line arguments.
+
+ Returns:
+ The log level to use when retrieving the LLVM hash or google3 LLVM version,
+ the chroot path to use for executing chroot commands,
+ a list of a package or packages to update their LLVM next hash,
+ and the LLVM version to use when retrieving the LLVM hash.
+ """
+
+ # Default path to the chroot if a path is not specified.
+ cros_root = os.path.expanduser('~')
+ cros_root = os.path.join(cros_root, 'chromiumos')
+
+ # Create parser and add optional command-line arguments.
+ parser = argparse.ArgumentParser(
+ description=
+ 'Runs a tryjob if successfully updated LLVM_NEXT_HASH of packages.')
+
+ # Add argument for the absolute path to the file that contains information on
+ # the previous tested svn version.
+ parser.add_argument(
+ '--last_tested',
+ help='the absolute path to the file that contains the last tested '
+ 'svn version')
+
+ # Add argument for other change lists that want to run alongside the tryjob
+ # which has a change list of updating a package's git hash.
+ parser.add_argument(
+ '--extra_change_lists',
+ type=int,
+ nargs='+',
+ help='change lists that would like to be run alongside the change list '
+ 'of updating the packages')
+
+ # Add argument for a specific chroot path.
+ parser.add_argument(
+ '--chroot_path',
+ default=cros_root,
+ help='the path to the chroot (default: %(default)s)')
+
+ # Add argument for whether to display command contents to `stdout`.
+ parser.add_argument(
+ '--verbose',
+ action='store_true',
+ help='display contents of a command to the terminal '
+ '(default: %(default)s)')
+
+ # Add argument for the LLVM version to use.
+ parser.add_argument(
+ '--llvm_version',
+ type=is_svn_option,
+ required=True,
+ help='which git hash of LLVM to find '
+ '{google3, ToT, <svn_version>} '
+ '(default: finds the git hash of the google3 LLVM '
+ 'version)')
+
+ args_output = parser.parse_args()
+
+ return args_output
+
+
+def GetLastTestedSVNVersion(last_tested_file):
+ """Gets the lasted tested svn version from the file.
+
+ Args:
+ last_tested_file: The absolute path to the file that contains the last
+ tested svn version.
+
+ Returns:
+ The last tested svn version or 'None' if the file did not have a last tested
+ svn version (the file exists, but failed to convert the contents to an
+ integer) or the file does not exist.
+ """
+
+ if not last_tested_file:
+ return None
+
+ last_svn_version = None
+
+ # Get the last tested svn version if the file exists.
+ try:
+ with open(last_tested_file) as file_obj:
+ # For now, the first line contains the last tested svn version.
+ return int(file_obj.read().rstrip())
+
+ except (IOError, ValueError):
+ pass
+
+ return last_svn_version
+
+
+def GetCQDependString(dependent_cls):
+ """Get CQ dependency string e.g. `Cq-Depend: chromium:MM, chromium:NN`."""
+
+ if not dependent_cls:
+ return None
+
+ # Cq-Depend must start a new paragraph prefixed with "Cq-Depend".
+ return '\nCq-Depend: ' + ', '.join(('chromium:%s' % i) for i in dependent_cls)
+
+
+def startCQDryRun(cl, dependent_cls, chroot_path):
+ """Start CQ dry run for the changelist and dependencies."""
+
+ gerrit_abs_path = os.path.join(chroot_path, 'chromite/bin/gerrit')
+
+ cl_list = [cl]
+ cl_list.extend(dependent_cls)
+
+ for changes in cl_list:
+ cq_dry_run_cmd = [gerrit_abs_path, 'label-cq', str(changes), '1']
+
+ ExecCommandAndCaptureOutput(cq_dry_run_cmd)
+
+
+def main():
+ """Updates the packages' 'LLVM_NEXT_HASH' and submits tryjobs.
+
+ Raises:
+ AssertionError: The script was run inside the chroot.
+ """
+
+ VerifyOutsideChroot()
+
+ args_output = GetCommandLineArgs()
+
+ last_svn_version = GetLastTestedSVNVersion(args_output.last_tested)
+
+ update_packages = [
+ 'sys-devel/llvm', 'sys-libs/compiler-rt', 'sys-libs/libcxx',
+ 'sys-libs/libcxxabi', 'sys-libs/llvm-libunwind'
+ ]
+
+ patch_metadata_file = 'PATCHES.json'
+
+ svn_option = args_output.llvm_version
+
+ git_hash, svn_version = GetLLVMHashAndVersionFromSVNOption(svn_option)
+
+ # There is no need to run tryjobs when the SVN version matches the last tested
+ # SVN version.
+ if last_svn_version == svn_version:
+ print('svn version (%d) matches the last tested svn version (%d) in %s' %
+ (svn_version, last_svn_version, args_output.last_tested))
+ return
+
+ update_chromeos_llvm_hash.verbose = args_output.verbose
+ extra_commit_msg = GetCQDependString(args_output.extra_change_lists)
+
+ change_list = update_chromeos_llvm_hash.UpdatePackages(
+ update_packages, update_chromeos_llvm_hash.LLVMVariant.next, git_hash,
+ svn_version, args_output.chroot_path, patch_metadata_file,
+ FailureModes.DISABLE_PATCHES, svn_option, extra_commit_msg)
+
+ print('Successfully updated packages to %d' % svn_version)
+ print('Gerrit URL: %s' % change_list.url)
+ print('Change list number: %d' % change_list.cl_number)
+
+ startCQDryRun(change_list.cl_number, args_output.extra_change_lists,
+ args_output.chroot_path)
+
+ # Updated the packages and submitted tryjobs successfully, so the file will
+ # contain 'svn_version' which will now become the last tested svn version.
+ if args_output.last_tested:
+ with open(args_output.last_tested, 'w', encoding='utf-8') as file_obj:
+ file_obj.write(str(svn_version))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/llvm_tools/update_packages_and_test_cq_unittest.py b/llvm_tools/update_packages_and_test_cq_unittest.py
new file mode 100755
index 00000000..58f99e83
--- /dev/null
+++ b/llvm_tools/update_packages_and_test_cq_unittest.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unittests for running tryjobs after updating packages."""
+
+from __future__ import print_function
+
+import json
+import unittest
+import unittest.mock as mock
+
+from test_helpers import ArgsOutputTest
+from test_helpers import CreateTemporaryFile
+from update_chromeos_llvm_hash import CommitContents
+import update_chromeos_llvm_hash
+import update_packages_and_test_cq
+
+
+class UpdatePackagesAndRunTestCQTest(unittest.TestCase):
+ """Unittests for CQ dry run after updating packages."""
+
+ def testGetCQDependString(self):
+ test_no_changelists = []
+ test_single_changelist = [1234]
+ test_multiple_changelists = [1234, 5678]
+
+ self.assertEqual(
+ update_packages_and_test_cq.GetCQDependString(test_no_changelists),
+ None)
+
+ self.assertEqual(
+ update_packages_and_test_cq.GetCQDependString(test_single_changelist),
+ '\nCq-Depend: chromium:1234')
+
+ self.assertEqual(
+ update_packages_and_test_cq.GetCQDependString(
+ test_multiple_changelists),
+ '\nCq-Depend: chromium:1234, chromium:5678')
+
+ # Mock ExecCommandAndCaptureOutput for the gerrit command execution.
+ @mock.patch.object(
+ update_packages_and_test_cq,
+ 'ExecCommandAndCaptureOutput',
+ return_value=None)
+ def teststartCQDryRunNoDeps(self, mock_exec_cmd):
+ chroot_path = '/abs/path/to/chroot'
+ test_cl_number = 1000
+
+ # test with no deps cls.
+ extra_cls = []
+ update_packages_and_test_cq.startCQDryRun(test_cl_number, extra_cls,
+ chroot_path)
+
+ expected_gerrit_message = [
+ '%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
+ str(test_cl_number), '1'
+ ]
+
+ mock_exec_cmd.assert_called_once_with(expected_gerrit_message)
+
+ # Mock ExecCommandAndCaptureOutput for the gerrit command execution.
+ @mock.patch.object(
+ update_packages_and_test_cq,
+ 'ExecCommandAndCaptureOutput',
+ return_value=None)
+ # test with a single deps cl.
+ def teststartCQDryRunSingleDep(self, mock_exec_cmd):
+ chroot_path = '/abs/path/to/chroot'
+ test_cl_number = 1000
+
+ extra_cls = [2000]
+ update_packages_and_test_cq.startCQDryRun(test_cl_number, extra_cls,
+ chroot_path)
+
+ expected_gerrit_cmd_1 = [
+ '%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
+ str(test_cl_number), '1'
+ ]
+ expected_gerrit_cmd_2 = [
+ '%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
+ str(2000), '1'
+ ]
+
+ self.assertEqual(mock_exec_cmd.call_count, 2)
+ self.assertEqual(mock_exec_cmd.call_args_list[0][0][0],
+ expected_gerrit_cmd_1)
+ self.assertEqual(mock_exec_cmd.call_args_list[1][0][0],
+ expected_gerrit_cmd_2)
+
+ # Mock ExecCommandAndCaptureOutput for the gerrit command execution.
+ @mock.patch.object(
+ update_packages_and_test_cq,
+ 'ExecCommandAndCaptureOutput',
+ return_value=None)
+ def teststartCQDryRunMultipleDep(self, mock_exec_cmd):
+ chroot_path = '/abs/path/to/chroot'
+ test_cl_number = 1000
+
+ # test with multiple deps cls.
+ extra_cls = [3000, 4000]
+ update_packages_and_test_cq.startCQDryRun(test_cl_number, extra_cls,
+ chroot_path)
+
+ expected_gerrit_cmd_1 = [
+ '%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
+ str(test_cl_number), '1'
+ ]
+ expected_gerrit_cmd_2 = [
+ '%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
+ str(3000), '1'
+ ]
+ expected_gerrit_cmd_3 = [
+ '%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
+ str(4000), '1'
+ ]
+
+ self.assertEqual(mock_exec_cmd.call_count, 3)
+ self.assertEqual(mock_exec_cmd.call_args_list[0][0][0],
+ expected_gerrit_cmd_1)
+ self.assertEqual(mock_exec_cmd.call_args_list[1][0][0],
+ expected_gerrit_cmd_2)
+ self.assertEqual(mock_exec_cmd.call_args_list[2][0][0],
+ expected_gerrit_cmd_3)
+
+
+if __name__ == '__main__':
+ unittest.main()