def add_pr_labels(pull, labels): """Adds PR labels""" if not labels or Config().DRY_RUN: return print("Add PR labels:", labels) for label in labels: pull.add_to_labels(label)
def set_pr_labels(pull, labels): """Sets new PR labels (all previously set labels are removed)""" if not labels or Config().DRY_RUN: return print("Set PR labels:", labels) # set_labels() should accept list but fails with empty "AssertionError:" pull.set_labels(labels)
def _test(): """Test and debug""" Config(cli_args=["DRY_RUN=True"]) dev_emails = get_dev_emails() print("dev_emails:", dev_emails) gh_api = GithubOrgApi() gh_api.get_org_emails()
def __init__(self): self._cfg = Config() self.server = Server(self._cfg.LDAP_SERVER, get_info=ALL) self.connection = Connection(self.server, user=self._cfg.LDAP_USER, password=self._cfg.LDAP_PASSWORD, auto_bind=True) self.connection.bind()
def __init__(self): self._cfg = Config() self.github = Github(self._cfg.GITHUB_TOKEN) self.github_org = self.github.get_organization(self._cfg.GITHUB_ORGANIZATION) self.repo = self.github.get_repo(f"{self._cfg.GITHUB_ORGANIZATION}/{self._cfg.GITHUB_REPO}") self.github_users_by_email = {} self.org_members_by_login = {} self.members_to_remove = set() self.members_to_fix_name = set()
def remove_members(gh_api, cfg_emails, org_emails, dev_emails, org_emails_no_in_ldap): """Checks and remove members""" print( f"\n{'=' * 10} Check accounts below and remove from the GitHub organization or " f"configuration {'=' * 10}") cfg_emails_no_in_org = sorted(cfg_emails.difference(org_emails)) print( f"\nCfg developer emails - absent in GitHub organization {len(cfg_emails_no_in_org)}:", "; ".join(cfg_emails_no_in_org), ) non_member_ignored_logins = set(Config().IGNORE_LOGINS).difference( set(gh_api.org_members_by_login.keys())) print( f"\nIgnored logins - absent in GitHub organization {len(non_member_ignored_logins)}:\n", "\n".join(non_member_ignored_logins), ) org_emails_no_in_dev = sorted(org_emails.difference(dev_emails)) print( f"\nOrg member emails - absent in cfg and LDAP PDLs {len(org_emails_no_in_dev)}:", "; ".join(org_emails_no_in_dev), ) print( f"\nOrg member emails - absent in LDAP at all {len(org_emails_no_in_ldap)}:", "; ".join(sorted(org_emails_no_in_ldap)), ) print("\nOrg members - no real name:") members_to_fix_name = sorted(gh_api.members_to_fix_name, key=lambda member: member.email) print_users(members_to_fix_name) print( "\nOrg member emails - no real name:", "; ".join([member.email.lower() for member in members_to_fix_name]), ) print("\nOrg members - no Intel emails:") print_users(gh_api.members_to_remove) gh_api.remove_users(org_emails_no_in_ldap | gh_api.members_to_remove)
def get_dev_emails(): """ Read a file with developer emails. Supported email formats [email protected] Import from Outlook: Last_name, First_name <*****@*****.**> """ re_email = re.compile(r".+<(.+)>") emails = set() cfg = Config() with open(cfg.properties["EMAILS_FILE_PATH"]) as file_obj: for line in file_obj: line = line.strip().lower() if not line or line.startswith("#"): continue re_outlook_email = re_email.match(line) if re_outlook_email: line = re_outlook_email.group(1).strip() if not is_intel_email(line): print(f'Wrong email in {cfg.properties["EMAILS_FILE_PATH"]}: {line}') continue emails.add(line) return emails
def is_user_ignored(user): """Checks that user should be ignored""" if is_valid_user(user) and user.login.lower() not in Config().IGNORE_LOGINS: return False return True
def get_label_by_team_name_map(team_name): """Generates label by PR reviwer team name using config map""" return Config().TEAM_TO_LABEL.get(team_name)
def main(): """The main entry point function""" arg_parser = ArgumentParser() arg_parser.add_argument( "--cfg-file", metavar="PATH", default=Config.default_cfg_path, help=f"Path to json configuration file, e.g. {Config.default_cfg_path}", ) arg_parser.add_argument( "--pr", metavar="NUMBER", help="Get GitHub pull request with the number" ) arg_parser.add_argument( "--pr-state", default="open", choices=["open", "closed"], help="Set GitHub pull request state", ) arg_parser.add_argument( "--newer", metavar="MINUTES", help="Get newly created GitHub pull request only" ) arg_parser.add_argument( "--check-commits", action="store_true", help="Check and compare git commit email with GitHub account email", ) args, unknown_args = arg_parser.parse_known_args() Config(args.cfg_file, unknown_args) gh_api = github_api.GithubOrgApi() if args.pr: pulls = [gh_api.repo.get_pull(int(args.pr))] else: pulls = gh_api.repo.get_pulls(state=args.pr_state) print(f"\nPRs count ({args.pr_state}):", pulls.totalCount) if args.newer: pr_created_after = ( datetime.datetime.now() - datetime.timedelta(minutes=int(args.newer)) ).astimezone() print("Checking PRs created after:", pr_created_after) non_org_intel_pr_users = set() non_org_pr_users = set() wrong_pulls = {} for pull in pulls: pr_created_at = pull.created_at.replace(tzinfo=datetime.timezone.utc).astimezone() if args.newer and pr_created_at <= pr_created_after: print(f"\nIGNORE: {get_pr_info_str(pull)}") continue print(f"\n{get_pr_info_str(pull)}") if args.check_commits: wrong_commits = get_wrong_commits(pull) if wrong_commits: wrong_pulls[pull.number] = wrong_commits else: update_labels(gh_api, pull, non_org_intel_pr_users, non_org_pr_users) if wrong_pulls: for pull_number, wrong_commits in wrong_pulls.items(): print( f"\nERROR: Remove or replace wrong commits in the PR {pull_number}:\n ", "\n ".join(wrong_commits), ) print( "\nAbout commit signature verification:\n ", "https://docs.github.com/en/github/authenticating-to-github/" "managing-commit-signature-verification/about-commit-signature-verification", ) sys.exit(1) if non_org_intel_pr_users: print("\nNon org user with Intel email or company:") github_api.print_users(non_org_intel_pr_users) if non_org_pr_users: print("\nNon org user with NO Intel email or company:") github_api.print_users(non_org_pr_users)
def main(): """The main entry point function""" arg_parser = ArgumentParser() arg_parser.add_argument( "--cfg-file", metavar="PATH", default=Config.default_cfg_path, help=f"Path to json configuration file, e.g. {Config.default_cfg_path}", ) arg_parser.add_argument("--teams", action="store_true", help="Check GitHub teams") arg_parser.add_argument("--no-ldap", action="store_true", help="Don't use LDAP info") args, unknown_args = arg_parser.parse_known_args() Config(args.cfg_file, unknown_args) gh_api = GithubOrgApi() if args.teams: gh_api.get_org_teams() return cfg_emails = get_dev_emails() print(f"\nCfg developer emails {len(cfg_emails)}:", "; ".join(sorted(cfg_emails))) dev_emails = set() dev_emails.update(cfg_emails) if not args.no_ldap: ldap_api = LdapApi() ldap_emails = ldap_api.get_user_emails() dev_emails.update(ldap_emails) print(f"\nLDAP developer emails {len(ldap_emails)}:", "; ".join(sorted(ldap_emails))) cfg_emails_no_in_ldap = ldap_api.get_absent_emails(cfg_emails) print( f"\nCfg developer emails - absent in LDAP at all {len(cfg_emails_no_in_ldap)}:", "; ".join(sorted(cfg_emails_no_in_ldap)), ) cfg_ldap_inters = cfg_emails.intersection(ldap_emails) print( f"\nCfg developer emails - present in LDAP developers {len(cfg_ldap_inters)}:", "; ".join(sorted(cfg_ldap_inters)), ) org_emails = gh_api.get_org_emails() print(f"\nOrg emails {len(org_emails)}:", "; ".join(sorted(org_emails))) org_emails_no_in_ldap = set() if not args.no_ldap: org_ldap_diff = org_emails.difference(ldap_emails) print( f"\nOrg member emails - absent in LDAP developers {len(org_ldap_diff)}:", "; ".join(sorted(org_ldap_diff)), ) for email in org_ldap_diff: user_info = ldap_api.get_user_info_by_email(email) if user_info: print_user_info(user_info, InfoLevel.PDL) else: org_emails_no_in_ldap.add(email) org_pendig_invitation_emails = gh_api.get_org_invitation_emails() invite_emails = dev_emails.difference(org_emails).difference( org_pendig_invitation_emails) print(f"\nInvite emails {len(invite_emails)}:", "; ".join(sorted(invite_emails))) valid_github_users = gh_api.get_valid_github_users(invite_emails) gh_api.invite_users(valid_github_users) remove_members(gh_api, cfg_emails, org_emails, dev_emails, org_emails_no_in_ldap)