diff options
author | Christopher Di Bella <cjdb@google.com> | 2021-02-05 23:35:53 +0000 |
---|---|---|
committer | Manoj Gupta <manojgupta@chromium.org> | 2021-02-12 16:15:36 +0000 |
commit | f5dbbbe456585460ac20f2eb661b7d0fc436d68b (patch) | |
tree | 6af30666dddb4b312ad13f572ec814458a5e747f /llvm_tools | |
parent | 21929ca0b632ed328920391488eeaae4811eb617 (diff) | |
download | toolchain-utils-f5dbbbe456585460ac20f2eb661b7d0fc436d68b.tar.gz |
adds cherry-picking to the nightly revert checker
BUG=chromium:1085465
TEST=nightly_revert_checker_test.py
Change-Id: I8069bb3f6ca8d07f54568b85373910a192d11ea5
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/2680123
Auto-Submit: Christopher Di Bella <cjdb@google.com>
Tested-by: Manoj Gupta <manojgupta@chromium.org>
Reviewed-by: George Burgess <gbiv@chromium.org>
Diffstat (limited to 'llvm_tools')
-rw-r--r-- | llvm_tools/README.md | 16 | ||||
-rwxr-xr-x | llvm_tools/cherrypick_cl.py | 198 | ||||
-rwxr-xr-x | llvm_tools/git.py | 22 | ||||
-rwxr-xr-x | llvm_tools/nightly_revert_checker.py | 237 | ||||
-rwxr-xr-x | llvm_tools/nightly_revert_checker_test.py | 18 |
5 files changed, 332 insertions, 159 deletions
diff --git a/llvm_tools/README.md b/llvm_tools/README.md index 783ec22d..8eff98ba 100644 --- a/llvm_tools/README.md +++ b/llvm_tools/README.md @@ -542,11 +542,23 @@ parents of 123abc. This is an automated wrapper around `revert_checker.py`. It checks to see if any new reverts happened across toolchains that we're trying to ship since it was -last run. If so, it sends emails to appropriate groups. +last run. If so, it either automatically cherry-picks the reverts, or sends +emails to appropriate groups. -Usage example: +Usage example for cherry-picking: +``` +PYTHONPATH=../ ./nightly_revert_checker.py \ + cherry-pick + --state_file state.json \ + --llvm_dir llvm-project-copy \ + --chromeos_dir ../../../../ + --reviewers=chromium-os-mage@google.com +``` + +Usage example for email: ``` PYTHONPATH=../ ./nightly_revert_checker.py \ + email --state_file state.json \ --llvm_dir llvm-project-copy \ --chromeos_dir ../../../../ diff --git a/llvm_tools/cherrypick_cl.py b/llvm_tools/cherrypick_cl.py index 9e306725..ff385f97 100755 --- a/llvm_tools/cherrypick_cl.py +++ b/llvm_tools/cherrypick_cl.py @@ -17,6 +17,8 @@ import os import shlex import subprocess import sys +import typing as t +from datetime import datetime import chroot import get_llvm_hash @@ -141,6 +143,123 @@ def get_package_names(sha: str, llvm_dir: str) -> list: return packages +def add_cherrypicks_for_packages(packages: t.List[str], symlinks: t.List[str], + start_rev: git_llvm_rev.Rev, + rev: git_llvm_rev.Rev, sha: str, + llvm_config: git_llvm_rev.LLVMConfig): + """Create a patch and add its metadata for each package""" + for package, symlink in zip(packages, symlinks): + symlink_dir = os.path.dirname(symlink) + patches_json_path = os.path.join(symlink_dir, 'files/PATCHES.json') + relative_patches_dir = 'cherry' if package == 'llvm' else '' + patches_dir = os.path.join(symlink_dir, 'files', relative_patches_dir) + logging.info('Cherrypicking %s (%s) into %s', rev, sha, package) + add_cherrypick(patches_json_path, patches_dir, relative_patches_dir, + start_rev, llvm_config.dir, rev, sha, package) + + +def make_cl(symlinks_to_uprev: t.List[str], llvm_symlink_dir: str, branch: str, + commit_messages: t.List[str], reviewers: t.Optional[t.List[str]], + cc: t.Optional[t.List[str]]): + symlinks_to_uprev = sorted(set(symlinks_to_uprev)) + for symlink in symlinks_to_uprev: + update_chromeos_llvm_hash.UprevEbuildSymlink(symlink) + subprocess.check_output(['git', 'add', '--all'], + cwd=os.path.dirname(symlink)) + git.UploadChanges(llvm_symlink_dir, branch, commit_messages, reviewers, cc) + git.DeleteBranch(llvm_symlink_dir, branch) + + +def resolve_symbolic_sha(start_sha: str, llvm_symlink_dir: str) -> str: + if start_sha == 'llvm': + return parse_ebuild_for_assignment(llvm_symlink_dir, 'LLVM_HASH') + + if start_sha == 'llvm-next': + return parse_ebuild_for_assignment(llvm_symlink_dir, 'LLVM_NEXT_HASH') + + return start_sha + + +def find_commits_and_make_cl(chroot_path: str, shas: t.List[str], + start_rev: git_llvm_rev.Rev, + llvm_config: git_llvm_rev.LLVMConfig, + llvm_symlink_dir: str, create_cl: bool, + reviewers: t.Optional[t.List[str]], + cc: t.Optional[t.List[str]]): + if create_cl: + branch = f'cherry-pick-{datetime.now().strftime("%Y%m%d%H%M%S%f")}' + git.CreateBranch(llvm_symlink_dir, branch) + symlinks_to_uprev = [] + commit_messages = [ + 'llvm: cherry-pick CLs from upstream\n', + ] + + for sha in shas: + sha = resolve_llvm_ref(llvm_config.dir, sha) + rev = git_llvm_rev.translate_sha_to_rev(llvm_config, sha) + # Find out the llvm projects changed in this commit + packages = get_package_names(sha, llvm_config.dir) + # Find out the ebuild symlinks of the corresponding ChromeOS packages + symlinks = chroot.GetChrootEbuildPaths(chroot_path, [ + 'sys-devel/llvm' if package == 'llvm' else 'sys-libs/' + package + for package in packages + ]) + symlinks = chroot.ConvertChrootPathsToAbsolutePaths(chroot_path, symlinks) + + add_cherrypicks_for_packages(packages, symlinks, start_rev, rev, sha, + llvm_config) + if create_cl: + symlinks_to_uprev.extend(symlinks) + commit_messages.extend([ + '\n\nreviews.llvm.org/rG%s\n' % sha, + subprocess.check_output(['git', 'log', '-n1', '--oneline', sha], + cwd=llvm_config.dir, + encoding='utf-8') + ]) + + if create_cl: + make_cl(symlinks_to_uprev, llvm_symlink_dir, branch, commit_messages, + reviewers, cc) + + +def do_cherrypick(chroot_path: str, + create_cl: bool, + start_sha: str, + shas: t.List[str], + reviewers: t.List[str] = None, + cc: t.List[str] = None): + llvm_symlink = chroot.ConvertChrootPathsToAbsolutePaths( + chroot_path, chroot.GetChrootEbuildPaths(chroot_path, + ['sys-devel/llvm']))[0] + llvm_symlink_dir = os.path.dirname(llvm_symlink) + + git_status = subprocess.check_output(['git', 'status', '-s'], + cwd=llvm_symlink_dir, + encoding='utf-8') + + if git_status: + error_path = os.path.dirname(os.path.dirname(llvm_symlink_dir)) + raise ValueError(f'Uncommited changes detected in {error_path}') + + start_sha = resolve_symbolic_sha(start_sha, llvm_symlink_dir) + logging.info('Base llvm hash == %s', start_sha) + + llvm_config = git_llvm_rev.LLVMConfig( + remote='origin', dir=get_llvm_hash.GetAndUpdateLLVMProjectInLLVMTools()) + start_sha = resolve_llvm_ref(llvm_config.dir, start_sha) + + find_commits_and_make_cl( + chroot_path=chroot_path, + shas=shas, + start_rev=git_llvm_rev.translate_sha_to_rev(llvm_config, start_sha), + llvm_config=llvm_config, + llvm_symlink_dir=llvm_symlink_dir, + create_cl=create_cl, + reviewers=reviewers, + cc=cc) + logging.info('Complete.') + + def main(): chroot.VerifyOutsideChroot() logging.basicConfig( @@ -170,80 +289,11 @@ def main(): help='Automatically create a CL if specified') args = parser.parse_args() - llvm_symlink = chroot.ConvertChrootPathsToAbsolutePaths( - args.chroot_path, - chroot.GetChrootEbuildPaths(args.chroot_path, ['sys-devel/llvm']))[0] - llvm_symlink_dir = os.path.dirname(llvm_symlink) - - git_status = subprocess.check_output(['git', 'status', '-s'], - cwd=llvm_symlink_dir, - encoding='utf-8') - if git_status: - raise ValueError('Uncommited changes detected in %s' % - os.path.dirname(os.path.dirname(llvm_symlink_dir))) - - start_sha = args.start_sha - if start_sha == 'llvm': - start_sha = parse_ebuild_for_assignment(llvm_symlink_dir, 'LLVM_HASH') - elif start_sha == 'llvm-next': - start_sha = parse_ebuild_for_assignment(llvm_symlink_dir, 'LLVM_NEXT_HASH') - logging.info('Base llvm hash == %s', start_sha) - - llvm_config = git_llvm_rev.LLVMConfig( - remote='origin', dir=get_llvm_hash.GetAndUpdateLLVMProjectInLLVMTools()) - - start_sha = resolve_llvm_ref(llvm_config.dir, start_sha) - start_rev = git_llvm_rev.translate_sha_to_rev(llvm_config, start_sha) - - if args.create_cl: - branch = 'cherry-pick' - git.CreateBranch(llvm_symlink_dir, branch) - symlinks_to_uprev = [] - commit_messages = [ - 'llvm: cherry-pick CLs from upstream\n', - ] - - for sha in args.sha: - sha = resolve_llvm_ref(llvm_config.dir, sha) - rev = git_llvm_rev.translate_sha_to_rev(llvm_config, sha) - # Find out the llvm projects changed in this commit - packages = get_package_names(sha, llvm_config.dir) - # Find out the ebuild symlinks of the corresponding ChromeOS packages - symlinks = chroot.GetChrootEbuildPaths(args.chroot_path, [ - 'sys-devel/llvm' if package == 'llvm' else 'sys-libs/' + package - for package in packages - ]) - symlinks = chroot.ConvertChrootPathsToAbsolutePaths(args.chroot_path, - symlinks) - - # Create a patch and add its metadata for each package - for package, symlink in zip(packages, symlinks): - symlink_dir = os.path.dirname(symlink) - patches_json_path = os.path.join(symlink_dir, 'files/PATCHES.json') - relative_patches_dir = 'cherry' if package == 'llvm' else '' - patches_dir = os.path.join(symlink_dir, 'files', relative_patches_dir) - logging.info('Cherrypicking %s (%s) into %s', rev, sha, package) - - add_cherrypick(patches_json_path, patches_dir, relative_patches_dir, - start_rev, llvm_config.dir, rev, sha, package) - if args.create_cl: - symlinks_to_uprev.extend(symlinks) - commit_messages.extend([ - '\n\nreviews.llvm.org/rG%s\n' % sha, - subprocess.check_output(['git', 'log', '-n1', '--oneline', sha], - cwd=llvm_config.dir, - encoding='utf-8') - ]) - - logging.info('Complete.') - - if args.create_cl: - symlinks_to_uprev = list(sorted(set(symlinks_to_uprev))) - for symlink in symlinks_to_uprev: - update_chromeos_llvm_hash.UprevEbuildSymlink(symlink) - subprocess.check_output(['git', 'add', '--all'], cwd=symlink_dir) - git.UploadChanges(llvm_symlink_dir, branch, commit_messages) - git.DeleteBranch(llvm_symlink_dir, branch) + do_cherrypick( + chroot_path=args.chroot_path, + create_cl=args.create_cl, + start_sha=args.start_sha, + shas=args.sha) if __name__ == '__main__': diff --git a/llvm_tools/git.py b/llvm_tools/git.py index 5d057a75..22c7002a 100755 --- a/llvm_tools/git.py +++ b/llvm_tools/git.py @@ -72,7 +72,7 @@ def DeleteBranch(repo, branch): subprocess.check_output(['git', '-C', repo, 'branch', '-D', branch]) -def UploadChanges(repo, branch, commit_messages): +def UploadChanges(repo, branch, commit_messages, reviewers=None, cc=None): """Uploads the changes in the specifed branch of the given repo for review. Args: @@ -80,6 +80,8 @@ def UploadChanges(repo, branch, commit_messages): branch: The name of the branch to upload. commit_messages: A string of commit message(s) (i.e. '[message]' of the changes made. + reviewers: A list of reviewers to add to the CL. + cc: A list of contributors to CC about the CL. Returns: A nametuple that has two (key, value) pairs, where the first pair is the @@ -101,12 +103,24 @@ def UploadChanges(repo, branch, commit_messages): subprocess.check_output(['git', 'commit', '-F', f.name], cwd=repo) # Upload the changes for review. + git_args = [ + 'repo', + 'upload', + '--yes', + f'--reviewers={",".join(reviewers)}' if reviewers else '--ne', + '--no-verify', + f'--br={branch}', + ] + + if cc: + git_args.append(f'--cc={",".join(cc)}') + out = subprocess.check_output( - ['repo', 'upload', '--yes', '--ne', '--no-verify', - '--br=%s' % branch], + git_args, stderr=subprocess.STDOUT, cwd=repo, - encoding='utf-8') + encoding='utf-8', + ) print(out) diff --git a/llvm_tools/nightly_revert_checker.py b/llvm_tools/nightly_revert_checker.py index 3a23890a..6b4ac53c 100755 --- a/llvm_tools/nightly_revert_checker.py +++ b/llvm_tools/nightly_revert_checker.py @@ -6,8 +6,8 @@ """Checks for new reverts in LLVM on a nightly basis. -If any reverts are found that were previously unknown, this fires off an email. -All LLVM SHAs to monitor are autodetected. +If any reverts are found that were previously unknown, this cherry-picks them or +fires off an email. All LLVM SHAs to monitor are autodetected. """ # pylint: disable=cros-logging-import @@ -29,12 +29,13 @@ import cros_utils.tiny_render as tiny_render import get_llvm_hash import git_llvm_rev import revert_checker +import cherrypick_cl State = t.Any -def _find_interesting_android_shas( - android_llvm_toolchain_dir: str) -> t.List[t.Tuple[str]]: +def _find_interesting_android_shas(android_llvm_toolchain_dir: str + ) -> t.List[t.Tuple[str, str]]: llvm_project = os.path.join(android_llvm_toolchain_dir, 'toolchain/llvm-project') @@ -55,8 +56,8 @@ def _find_interesting_android_shas( return result -def _parse_llvm_ebuild_for_shas( - ebuild_file: io.TextIOWrapper) -> t.List[t.Tuple[str]]: +def _parse_llvm_ebuild_for_shas(ebuild_file: io.TextIOWrapper + ) -> t.List[t.Tuple[str, str]]: def parse_ebuild_assignment(line: str) -> str: no_comments = line.split('#')[0] @@ -84,7 +85,8 @@ def _parse_llvm_ebuild_for_shas( return results -def _find_interesting_chromeos_shas(chromeos_base: str) -> t.List[t.Tuple[str]]: +def _find_interesting_chromeos_shas(chromeos_base: str + ) -> t.List[t.Tuple[str, str]]: llvm_dir = os.path.join(chromeos_base, 'src/third_party/chromiumos-overlay/sys-devel/llvm') candidate_ebuilds = [ @@ -193,18 +195,114 @@ def _read_state(state_file: str) -> State: return {} -def main(argv: t.List[str]) -> None: +def find_shas(llvm_dir: str, interesting_shas: t.List[t.Tuple[str, str]], + state: State, new_state: State): + for friendly_name, sha in interesting_shas: + logging.info('Finding reverts across %s (%s)', friendly_name, sha) + all_reverts = revert_checker.find_reverts( + llvm_dir, sha, root='origin/' + git_llvm_rev.MAIN_BRANCH) + logging.info('Detected the following revert(s) across %s:\n%s', + friendly_name, pprint.pformat(all_reverts)) + + new_state[sha] = [r.sha for r in all_reverts] + + if sha not in state: + logging.info('SHA %s is new to me', sha) + existing_reverts = set() + else: + existing_reverts = set(state[sha]) + + new_reverts = [r for r in all_reverts if r.sha not in existing_reverts] + if not new_reverts: + logging.info('...All of which have been reported.') + continue + + yield (friendly_name, sha, new_reverts) + + +def do_cherrypick(chroot_path: str, llvm_dir: str, + interesting_shas: t.List[t.Tuple[str, str]], state: State, + reviewers: t.List[str], cc: t.List[str]) -> State: + new_state: State = {} + seen: t.Set[str] = set() + for friendly_name, _sha, reverts in find_shas(llvm_dir, interesting_shas, + state, new_state): + if friendly_name in seen: + continue + seen.add(friendly_name) + for sha, reverted_sha in reverts: + cherrypick_cl.do_cherrypick( + chroot_path=chroot_path, + create_cl=True, + start_sha=reverted_sha, + shas=[sha], + reviewers=reviewers, + cc=cc) + return new_state + + +def do_email(is_dry_run: bool, llvm_dir: str, repository: str, + interesting_shas: t.List[t.Tuple[str, str]], state: State, + recipients: _EmailRecipients) -> State: + + def prettify_sha(sha: str) -> tiny_render.Piece: + rev = get_llvm_hash.GetVersionFrom(llvm_dir, sha) + + # 12 is arbitrary, but should be unambiguous enough. + short_sha = sha[:12] + return tiny_render.Switch( + text=f'r{rev} ({short_sha})', + html=tiny_render.Link( + href='https://reviews.llvm.org/rG' + sha, inner='r' + str(rev)), + ) + + def get_sha_description(sha: str) -> tiny_render.Piece: + return subprocess.check_output( + ['git', 'log', '-n1', '--format=%s', sha], + cwd=llvm_dir, + encoding='utf-8', + ).strip() + + new_state: State = {} + for friendly_name, sha, new_reverts in find_shas(llvm_dir, interesting_shas, + state, new_state): + email = _generate_revert_email(repository, friendly_name, sha, prettify_sha, + get_sha_description, new_reverts) + if is_dry_run: + logging.info('Would send email:\nSubject: %s\nBody:\n%s\n', email.subject, + tiny_render.render_text_pieces(email.body)) + else: + logging.info('Sending email with subject %r...', email.subject) + _send_revert_email(recipients, email) + logging.info('Email sent.') + return new_state + + +def parse_args(argv: t.List[str]) -> t.Any: parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( + 'action', + choices=['cherry-pick', 'email', 'dry-run'], + help='Automatically cherry-pick upstream reverts, send an email, or ' + 'write to stdout.') + parser.add_argument( '--state_file', required=True, help='File to store persistent state in.') parser.add_argument( '--llvm_dir', required=True, help='Up-to-date LLVM directory to use.') - parser.add_argument( - '--dry_run', - action='store_true', - help='Print email contents, rather than sending them.') parser.add_argument('--debug', action='store_true') + parser.add_argument( + '--reviewers', + type=str, + nargs='*', + help='Requests reviews from REVIEWERS. All REVIEWERS must have existing ' + 'accounts.') + parser.add_argument( + '--cc', + type=str, + nargs='*', + help='CCs the CL to the recipients. All recipients must have existing ' + 'accounts.') subparsers = parser.add_subparsers(dest='repository') subparsers.required = True @@ -219,91 +317,72 @@ def main(argv: t.List[str]) -> None: required=True, help='Up-to-date android-llvm-toolchain directory to use.') - opts = parser.parse_args(argv) + return parser.parse_args(argv) + + +def find_chroot(opts: t.Any, reviewers: t.List[str], cc: t.List[str] + ) -> t.Tuple[str, t.List[t.Tuple[str, str]], _EmailRecipients]: + recipients = reviewers + cc + if opts.repository == 'chromeos': + chroot_path = opts.chromeos_dir + return (chroot_path, _find_interesting_chromeos_shas(chroot_path), + _EmailRecipients(well_known=['mage'], direct=recipients)) + elif opts.repository == 'android': + if opts.action == 'cherry-pick': + raise RuntimeError( + "android doesn't currently support automatic cherry-picking.") + + chroot_path = opts.android_llvm_toolchain_dir + return (chroot_path, _find_interesting_android_shas(chroot_path), + _EmailRecipients( + well_known=[], + direct=['android-llvm-dev@google.com'] + recipients)) + else: + raise ValueError(f'Unknown repository {opts.repository}') + + +def main(argv: t.List[str]) -> int: + opts = parse_args(argv) logging.basicConfig( format='%(asctime)s: %(levelname)s: %(filename)s:%(lineno)d: %(message)s', level=logging.DEBUG if opts.debug else logging.INFO, ) - dry_run = opts.dry_run + action = opts.action llvm_dir = opts.llvm_dir repository = opts.repository state_file = opts.state_file + reviewers = opts.reviewers if opts.reviewers else [] + cc = opts.cc if opts.cc else [] - if repository == 'chromeos': - interesting_shas = _find_interesting_chromeos_shas(opts.chromeos_dir) - recipients = _EmailRecipients(well_known=['mage'], direct=[]) - elif repository == 'android': - interesting_shas = _find_interesting_android_shas( - opts.android_llvm_toolchain_dir) - recipients = _EmailRecipients( - well_known=[], direct=['android-llvm-dev@google.com']) - else: - raise ValueError('Unknown repository %s' % opts.repository) - + chroot_path, interesting_shas, recipients = find_chroot(opts, reviewers, cc) logging.info('Interesting SHAs were %r', interesting_shas) state = _read_state(state_file) logging.info('Loaded state\n%s', pprint.pformat(state)) - def prettify_sha(sha: str) -> tiny_render.Piece: - rev = get_llvm_hash.GetVersionFrom(llvm_dir, sha) - - # 12 is arbitrary, but should be unambiguous enough. - short_sha = sha[:12] - return tiny_render.Switch( - text='r%s (%s)' % (rev, short_sha), - html=tiny_render.Link( - href='https://reviews.llvm.org/rG' + sha, inner='r' + str(rev)), - ) - - def get_sha_description(sha: str) -> tiny_render.Piece: - return subprocess.check_output( - ['git', 'log', '-n1', '--format=%s', sha], - cwd=llvm_dir, - encoding='utf-8', - ).strip() - - new_state: State = {} - revert_emails_to_send: t.List[t.Tuple[str, t.List[revert_checker - .Revert]]] = [] - for friendly_name, sha in interesting_shas: - logging.info('Finding reverts across %s (%s)', friendly_name, sha) - all_reverts = revert_checker.find_reverts( - llvm_dir, sha, root='origin/' + git_llvm_rev.MAIN_BRANCH) - logging.info('Detected the following revert(s) across %s:\n%s', - friendly_name, pprint.pformat(all_reverts)) - - new_state[sha] = [r.sha for r in all_reverts] - - if sha not in state: - logging.info('SHA %s is new to me', sha) - existing_reverts = set() - else: - existing_reverts = set(state[sha]) - - new_reverts = [r for r in all_reverts if r.sha not in existing_reverts] - if not new_reverts: - logging.info('...All of which have been reported.') - continue - - revert_emails_to_send.append( - _generate_revert_email(repository, friendly_name, sha, prettify_sha, - get_sha_description, new_reverts)) - # We want to be as free of obvious side-effects as possible in case something - # above breaks. Hence, send the email as late as possible. - for email in revert_emails_to_send: - if dry_run: - logging.info('Would send email:\nSubject: %s\nBody:\n%s\n', email.subject, - tiny_render.render_text_pieces(email.body)) - else: - logging.info('Sending email with subject %r...', email.subject) - _send_revert_email(recipients, email) - logging.info('Email sent.') + # above breaks. Hence, action as late as possible. + if action == 'cherry-pick': + new_state = do_cherrypick( + chroot_path=chroot_path, + llvm_dir=llvm_dir, + interesting_shas=interesting_shas, + state=state, + reviewers=reviewers, + cc=cc) + else: + new_state = do_email( + is_dry_run=action == 'dry-run', + llvm_dir=llvm_dir, + repository=repository, + interesting_shas=interesting_shas, + state=state, + recipients=recipients) _write_state(state_file, new_state) + return 0 if __name__ == '__main__': diff --git a/llvm_tools/nightly_revert_checker_test.py b/llvm_tools/nightly_revert_checker_test.py index 68338a59..72c51f81 100755 --- a/llvm_tools/nightly_revert_checker_test.py +++ b/llvm_tools/nightly_revert_checker_test.py @@ -10,6 +10,7 @@ from __future__ import print_function import io import unittest +from unittest.mock import patch import cros_utils.tiny_render as tiny_render import nightly_revert_checker @@ -153,6 +154,23 @@ class Test(unittest.TestCase): self.assertIn('Failed to detect SHAs', str(e.exception)) + @patch('revert_checker.find_reverts') + @patch('cherrypick_cl.do_cherrypick') + def test_do_cherrypick_is_called(self, do_cherrypick, find_reverts): + find_reverts.return_value = [ + revert_checker.Revert('12345abcdef', 'fedcba54321') + ] + nightly_revert_checker.do_cherrypick( + chroot_path='/path/to/chroot', + llvm_dir='/path/to/llvm', + interesting_shas=[('12345abcdef', 'fedcba54321')], + state={}, + reviewers=['meow@chromium.org'], + cc=['purr@chromium.org']) + + do_cherrypick.assert_called_once() + find_reverts.assert_called_once() + if __name__ == '__main__': unittest.main() |