diff --git a/zh/technical-committee/governance/sanity_check.py b/zh/technical-committee/governance/sanity_check.py new file mode 100644 index 0000000000000000000000000000000000000000..8e082c1e28e54f66641e2360c2d2577cb61b805d --- /dev/null +++ b/zh/technical-committee/governance/sanity_check.py @@ -0,0 +1,217 @@ +#!/usr/bin/python3 +""" +This is a sanity checking tool for openEuler community database +""" +import yaml +import sys +import argparse +import os.path + +def check_1(sigs, exps): + """ + Repository in src-openeuler and openeuler should be managed by the single SIG. + """ + print("Repository in src-openeuler and openeuler should be managed by the single SIG.") + + repositories = {} + errors_found = 0 + + for sig in sigs: + if sig["name"] == "Private": + continue + for repo in sig["repositories"]: + repo_name = repo.replace("src-openeuler/", "").replace("openeuler/", "") + supervisor = repositories.get(repo_name, set()) + supervisor.add(sig["name"]) + repositories[repo_name] = supervisor + + for k in repositories: + v = repositories[k] + if len(v) != 1: + if k in exps: + continue + print("WARNING! " + k + ": Co-managed by these SIGs " + str(v) + "\n") + errors_found = errors_found + 1 + + if errors_found == 0: + print("PASS WITHOUT ISSUES FOUND.") + return errors_found + + +def check_2(sigs, exps): + """ + Repository in src-openeuler or openeuler should never be duplicated. + """ + print("Repository in src-openeuler or openeuler should never be duplicated.") + + repositories = {} + errors_found = 0 + + for sig in sigs: + if sig["name"] == "Private": + continue + for repo in sig["repositories"]: + supervisor = repositories.get(repo, set()) + if sig["name"] in supervisor: + print("WARNING! " + repo + " has been managed by " + sig["name"] + " multiple times.\n") + errors_found = errors_found + 1 + else: + supervisor.add(sig["name"]) + repositories[repo] = supervisor + + for k in repositories: + v = repositories[k] + if len(v) != 1: + if k in exps: + continue + print(k + ": " + str(v) + "\n") + errors_found = errors_found + 1 + + if errors_found == 0: + print("PASS WITHOUT ISSUES FOUND.") + return errors_found + + +def check_3(sigs): + """ + Repository managed by both SIG and Private. + """ + print("Repository managed by both SIG and Private.") + + supervisors = {} + + for sig in sigs: + for repo in sig["repositories"]: + supervisor = supervisors.get(repo, set()) + supervisor.add(sig["name"]) + supervisors[repo] = supervisor + + print("There're " + str(len(supervisors)) + " repositories in total.") + + co_managed = 0 + private_only = 0 + + for k in supervisors: + v = supervisors[k] + if "Private" in v: + if len(v) != 1: + co_managed = co_managed + 1 + else: + private_only = private_only + 1 + print("There're " + str(co_managed) + " repositories co-managed by Private") + print("There're " + str(private_only) + " repositories managed by Private only") + return supervisors + + +def check_4(exps, prefix, oe_repos, supervisors, cross_checked_repo): + """ + YAML in repository/ should be consisitent with sigs.yaml + """ + print("repository/{prefix}.yaml should be consisitent with sigs.yaml".format(prefix=prefix)) + + errors_found = 0 + + for repo in oe_repos: + name = prefix + "/" + repo["name"] + if name in cross_checked_repo: + print("WARNING! Repository {name} in {prefix}.yaml has duplication.".format(name=name, prefix=prefix)) + errors_found = errors_found + 1 + if not supervisors.get(name, False): + if name not in exps: + print("WARNING! Repository {name} in {prefix}.yaml cannot be found in sigs.yaml" + .format(name=name, prefix=prefix)) + errors_found = errors_found + 1 + if repo["type"] == "public" and "Private" in supervisors.get(name, set()): + print("WARNING! Repository {name} marked as public in {prefix}.yaml, but listed in Private SIG." + .format(name=name, prefix=prefix)) + errors_found = errors_found + 1 + + if repo["type"] == "private" and "Private" not in supervisors.get(name, set()): + print("WARNING! Repository {name} marked as private in {prefix}.yaml, but not listed in Private SIG." + .format(name=name, prefix=prefix)) + errors_found = errors_found + 1 + + cross_checked_repo.add(name) + + if errors_found == 0: + print("PASS WITHOUT ISSUES FOUND.") + return errors_found, cross_checked_repo + + +def check_6(cross_checked_repo, supervisors): + """ + All repositories in sigs.yaml must list in either openeuler.yaml or src-openeuler.yaml + """ + print("All repositories in sigs.yaml must list in either openeuler.yaml or src-openeuler.yaml") + errors_found = 0 + + if len(cross_checked_repo) != len(supervisors): + for repo in supervisors: + if not repo in cross_checked_repo: + print("WARNING! {name} listed in sigs.yaml, but neither openeuler.yaml nor src-openeuler.yaml" + .format(name=repo)) + errors_found = errors_found + 1 + + if errors_found == 0: + print("PASS WITHOUT ISSUES FOUND.") + + return errors_found + + +def load_yaml(d, f): + """ + Helper for load YAML database + """ + p = os.path.expanduser(os.path.join(d, f)) + try: + y = yaml.load(open(p), Loader=yaml.Loader) + except FileNotFoundError: + print("Cannot Load {path}".format(path=p)) + print("Could be wrong path") + sys.exit(1) + return y + + +if __name__ == "__main__": + par = argparse.ArgumentParser() + + par.add_argument("community", type=str, help="Local path of community repository") + args = par.parse_args() + + sigs_yaml = load_yaml(args.community, "sig/sigs.yaml") + sig_list = sigs_yaml["sigs"] + known_exceptions_yaml = load_yaml(args.community, "zh/technical-committee/governance/exceptions.yaml") + exception_list = known_exceptions_yaml["exceptions"] + openeuler_repo_yaml = load_yaml(args.community, "repository/openeuler.yaml") + openeuler_repos = openeuler_repo_yaml["repositories"] + srcopeneuler_repo_yaml = load_yaml(args.community, "repository/src-openeuler.yaml") + srcopeneuler_repos = srcopeneuler_repo_yaml["repositories"] + + repo_supervisors = {} + repo_cross_checked = set() + + print("Sanity Check among different YAML database inside openEuler community.") + issues_found = 0 + print("\nCheck 1:") + issues_found = issues_found + check_1(sig_list, exception_list) + + print("\nCheck 2:") + issues_found = issues_found + check_2(sig_list, exception_list) + + print("\nCheck 3:") + repo_supervisors = check_3(sig_list) + + print("\nCheck 4:") + issues, repo_cross_checked = check_4(exception_list, "openeuler", + openeuler_repos, repo_supervisors, repo_cross_checked) + issues_found = issues_found + issues + + print("\nCheck 5:") + issues, repo_cross_checked = check_4(exception_list, "src-openeuler", + srcopeneuler_repos, repo_supervisors, repo_cross_checked) + issues_found = issues_found + issues + + print("\nCheck 6:") + issues_found = issues_found + check_6(repo_cross_checked, repo_supervisors) + + sys.exit(issues_found)