|  | #!/usr/bin/env python3 | 
|  | # Copyright 2022 The IREE Authors | 
|  | # | 
|  | # Licensed under the Apache License v2.0 with LLVM Exceptions. | 
|  | # See https://llvm.org/LICENSE.txt for license information. | 
|  | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  |  | 
|  | from ghapi.all import GhApi | 
|  | import argparse | 
|  | import dataclasses | 
|  | import os | 
|  | import sys | 
|  | import time | 
|  |  | 
|  | CLA_CHECK_NAME = "cla/google" | 
|  | REPO_OWNER = "google" | 
|  | REPO_NAME = "iree" | 
|  |  | 
|  |  | 
|  | class ApiWrapper: | 
|  |  | 
|  | def __init__(self): | 
|  | self._api = GhApi() | 
|  |  | 
|  | def get_cla_check(self, ref): | 
|  | response = self._api.checks.list_for_ref(owner=REPO_OWNER, | 
|  | repo=REPO_NAME, | 
|  | ref=ref, | 
|  | check_name=CLA_CHECK_NAME) | 
|  | if len(response.check_runs) == 1: | 
|  | return response.check_runs[0] | 
|  | elif len(response.check_runs) == 0: | 
|  | return None | 
|  |  | 
|  | def wait_for_cla_check(self, ref, wait_secs=2): | 
|  | # We want to override the previous output when logging about waiting, so | 
|  | # this doesn't print a bunch of unhelpful log lines. Carriage return takes | 
|  | # us back to the beginning of the line, but it doesn't override previous | 
|  | # output past the end of the new output, so we pad things to ensure that | 
|  | # each line is at least as long as the previous one. Note that this approach | 
|  | # only works if a print statement doesn't overflow a single line (at least | 
|  | # on my machine). In that case, the beginning of the line is partway through | 
|  | # the previous print, although it at least starts on a new line. Better | 
|  | # suggestions welcome. | 
|  | min_line_length = 0 | 
|  | # We don't need great precision | 
|  | start = time.monotonic() | 
|  | while True: | 
|  | cla_check = self.get_cla_check(ref) | 
|  | if cla_check is not None and cla_check.status == "completed": | 
|  | return cla_check | 
|  |  | 
|  | wait_time = int(round(time.monotonic() - start)) | 
|  | output_str = ( | 
|  | f"Waiting for CLA Check to complete on {ref}. Waited {wait_time}" | 
|  | f" seconds." | 
|  | f" CLA Check is currently" | 
|  | f" {'not found' if cla_check is None else cla_check.status}") | 
|  | min_line_length = max(min_line_length, len(output_str)) | 
|  | print(output_str.ljust(min_line_length), "\r", end="", flush=True) | 
|  |  | 
|  | time.sleep(wait_secs) | 
|  |  | 
|  |  | 
|  | def parse_args(): | 
|  | parser = argparse.ArgumentParser( | 
|  | description="Check if the given commit has passed the Google CLA check") | 
|  | parser.add_argument("ref", help="Git reference to check.") | 
|  | parser.add_argument( | 
|  | "--wait", | 
|  | nargs="?", | 
|  | metavar="N", | 
|  | help="Poll for a complete check every N seconds if one is not found." | 
|  | " Without this flag, the script will only check once. If this is set" | 
|  | " without a value, if will check every 2 seconds.", | 
|  | default=0, | 
|  | const=2, | 
|  | ) | 
|  | return parser.parse_args() | 
|  |  | 
|  |  | 
|  | def main(args): | 
|  | wrapper = ApiWrapper() | 
|  | if args.wait: | 
|  | cla_check = wrapper.wait_for_cla_check(args.ref, wait_secs=args.wait) | 
|  | else: | 
|  | cla_check = wrapper.get_cla_check(args.ref) | 
|  |  | 
|  | # Some of these should be impossible for the wait case, but it's simpler to | 
|  | # just check them again. | 
|  |  | 
|  | if cla_check is None: | 
|  | print(f"Didn't find CLA check for '{args.ref}'") | 
|  | sys.exit(3) | 
|  |  | 
|  | if cla_check.status != "completed": | 
|  | print(f"CLA check has not finished running for '{args.ref}'." | 
|  | f" Is '{cla_check.status}'") | 
|  | sys.exit(2) | 
|  |  | 
|  | # Doing it this way round so if there is some mistake in this check (e.g. | 
|  | # a typo, or 'success' is changed to 'passed') the whole thing fails. | 
|  | if cla_check.conclusion == "success": | 
|  | print(f"CLA check passed for '{args.ref}'") | 
|  | sys.exit(0) | 
|  |  | 
|  | print(f"CLA check did not succeed for '{args.ref}'." | 
|  | f" Completed with '{cla_check.conclusion}'") | 
|  | sys.exit(1) | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | main(parse_args()) |