diff options
author | George Burgess IV <gbiv@google.com> | 2024-04-15 10:12:57 -0600 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2024-04-15 22:12:57 +0000 |
commit | 53ba4150fc1a28086ae239938e2201d022fabe78 (patch) | |
tree | 7318c03a618da84a670245cd6e1e9c6f731a4a7c | |
parent | f8e584c226ae80b91180c1779afd1fdf537efce7 (diff) | |
download | toolchain-utils-53ba4150fc1a28086ae239938e2201d022fabe78.tar.gz |
llvm_tools: add bb_add.py
This allows for folks (...mostly automation and the mage) to
conveniently run `bb add` with 'well-known' toolchain CLs/CL stacks,
like the current llvm-next CL stack, or the disable-werror CL, or
similar.
BUG=b:333462347
TEST=Unittests
Change-Id: I43aa2f3a863a4121a6920a4e7a4adcd412057644
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/5454854
Reviewed-by: Ryan Beltran <ryanbeltran@chromium.org>
Commit-Queue: George Burgess <gbiv@chromium.org>
Tested-by: George Burgess <gbiv@chromium.org>
-rwxr-xr-x | llvm_tools/bb_add.py | 91 | ||||
-rwxr-xr-x | llvm_tools/bb_add_test.py | 100 | ||||
-rw-r--r-- | llvm_tools/cros_cls.py | 7 |
3 files changed, 196 insertions, 2 deletions
diff --git a/llvm_tools/bb_add.py b/llvm_tools/bb_add.py new file mode 100755 index 00000000..1ff83490 --- /dev/null +++ b/llvm_tools/bb_add.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# Copyright 2024 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Runs `bb add`, with additional convenience features.""" + +import argparse +import logging +import os +import shlex +import sys +from typing import Iterable, List + +import cros_cls +import llvm_next + + +def generate_bb_add_command( + use_llvm_next: bool, + disable_werror: bool, + extra_cls: Iterable[cros_cls.ChangeListURL], + bots: Iterable[str], +) -> List[str]: + cls: List[cros_cls.ChangeListURL] = [] + if use_llvm_next: + if not llvm_next.LLVM_NEXT_TESTING_CLS: + raise ValueError( + "llvm-next testing requested, but no llvm-next CLs exist." + ) + cls += llvm_next.LLVM_NEXT_TESTING_CLS + + if disable_werror: + cls.append(llvm_next.DISABLE_WERROR_CL) + + if extra_cls: + cls += extra_cls + + cmd = ["bb", "add"] + for cl in cls: + cmd += ("-cl", cl.crrev_url_without_http()) + cmd += bots + return cmd + + +def main(argv: List[str]) -> None: + logging.basicConfig( + format=">> %(asctime)s: %(levelname)s: %(filename)s:%(lineno)d: " + "%(message)s", + level=logging.INFO, + ) + + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument( + "--llvm-next", + action="store_true", + help="Add the current llvm-next patch set.", + ) + parser.add_argument( + "--disable-werror", + action="store_true", + help="Add the 'disable -Werror' patch sets", + ) + parser.add_argument( + "--cl", + action="append", + type=cros_cls.ChangeListURL.parse, + help=""" + CL to add to the `bb add` run. May be specified multiple times. In the + form crrev.com/c/123456. + """, + ) + parser.add_argument("bot", nargs="+", help="Bot(s) to run `bb add` with.") + opts = parser.parse_args(argv) + + cmd = generate_bb_add_command( + use_llvm_next=opts.llvm_next, + disable_werror=opts.disable_werror, + extra_cls=opts.cl, + bots=opts.bot, + ) + logging.info("Running `bb add` command: %s...", shlex.join(cmd)) + # execvp raises if it fails, so no need to check. + os.execvp(cmd[0], cmd) + + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/llvm_tools/bb_add_test.py b/llvm_tools/bb_add_test.py new file mode 100755 index 00000000..6f7fe6a7 --- /dev/null +++ b/llvm_tools/bb_add_test.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +# Copyright 2024 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Tests for bb_add.py.""" + +from typing import Iterable +import unittest + +import bb_add +import cros_cls +import llvm_next + + +_ARBITRARY_BOTS = ["chromeos/cq/amd64-generic-cq"] + + +class Test(unittest.TestCase): + """Tests for bb_add.py.""" + + def set_llvm_next_cls(self, cls: Iterable[cros_cls.ChangeListURL]): + old_cls = llvm_next.LLVM_NEXT_TESTING_CLS + llvm_next.LLVM_NEXT_TESTING_CLS = cls + + def restore_cls(): + llvm_next.LLVM_NEXT_TESTING_CLS = old_cls + + self.addCleanup(restore_cls) + + def test_generate_bb_add_raises_if_no_llvm_next_cls(self): + self.set_llvm_next_cls(()) + with self.assertRaisesRegex( + ValueError, "^llvm-next testing requested.*" + ): + bb_add.generate_bb_add_command( + use_llvm_next=True, + disable_werror=False, + extra_cls=(), + bots=_ARBITRARY_BOTS, + ) + + def test_generate_bb_add_adds_llvm_next_cls(self): + self.set_llvm_next_cls((cros_cls.ChangeListURL(123, 1),)) + cmd = bb_add.generate_bb_add_command( + use_llvm_next=True, + disable_werror=False, + extra_cls=(), + bots=_ARBITRARY_BOTS, + ) + self.assertEqual( + cmd, ["bb", "add", "-cl", "crrev.com/c/123/1"] + _ARBITRARY_BOTS + ) + + def test_generate_bb_add_adds_disable_werror_cl(self): + self.set_llvm_next_cls((cros_cls.ChangeListURL(123, 1),)) + cmd = bb_add.generate_bb_add_command( + use_llvm_next=False, + disable_werror=True, + extra_cls=(), + bots=_ARBITRARY_BOTS, + ) + self.assertEqual( + cmd, + [ + "bb", + "add", + "-cl", + llvm_next.DISABLE_WERROR_CL.crrev_url_without_http(), + ] + + _ARBITRARY_BOTS, + ) + + def test_generate_bb_add_adds_extra_cls(self): + self.set_llvm_next_cls((cros_cls.ChangeListURL(123, 1),)) + cmd = bb_add.generate_bb_add_command( + use_llvm_next=False, + disable_werror=False, + extra_cls=( + cros_cls.ChangeListURL(123, 1), + cros_cls.ChangeListURL(126), + ), + bots=_ARBITRARY_BOTS, + ) + self.assertEqual( + cmd, + [ + "bb", + "add", + "-cl", + "crrev.com/c/123/1", + "-cl", + "crrev.com/c/126", + ] + + _ARBITRARY_BOTS, + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/llvm_tools/cros_cls.py b/llvm_tools/cros_cls.py index d5b5ffa0..b74132e2 100644 --- a/llvm_tools/cros_cls.py +++ b/llvm_tools/cros_cls.py @@ -112,13 +112,16 @@ class ChangeListURL: raise ValueError("A patchset number must be specified.") return result - def __str__(self): + def crrev_url_without_http(self): namespace = "i" if self.internal else "c" - result = f"https://crrev.com/{namespace}/{self.cl_id}" + result = f"crrev.com/{namespace}/{self.cl_id}" if self.patch_set is not None: result += f"/{self.patch_set}" return result + def __str__(self): + return f"https://{self.crrev_url_without_http()}" + def builder_url(build_id: BuildID) -> str: """Returns a builder URL given a build ID.""" |