From 056b64baf858ad4d9a5065bace04b83d9dce4d44 Mon Sep 17 00:00:00 2001 From: smileknife Date: Tue, 13 Oct 2020 22:58:21 +0800 Subject: [PATCH] reconstruct review tool Signed-off-by: smileknife --- advisors/helper/reviewer_checklist.yaml | 115 ++++++++++ advisors/oe_review | 45 ---- advisors/{tc_review => review_tool.py} | 274 ++++++++++++++++++------ advisors/self_review | 101 --------- 4 files changed, 319 insertions(+), 216 deletions(-) create mode 100644 advisors/helper/reviewer_checklist.yaml delete mode 100755 advisors/oe_review rename advisors/{tc_review => review_tool.py} (41%) delete mode 100755 advisors/self_review diff --git a/advisors/helper/reviewer_checklist.yaml b/advisors/helper/reviewer_checklist.yaml new file mode 100644 index 00000000..acb282f4 --- /dev/null +++ b/advisors/helper/reviewer_checklist.yaml @@ -0,0 +1,115 @@ +basic: + PRSubmissionSPEC: + - + name: PR-title-check + condition: null + claim: PR的标题是否清晰易懂? + explain: 提交标题应该一句话说明本提交实现的内容。 + - + name: PR-content-check + condition: null + claim: PR的内容描述是否详细具体? + explain: 提交的描述应该用一段话说明本提交的背景和实现原理。 + - + name: PR-consistency-check + condition: null + claim: PR和实际代码修改是否一致? + explain: 提交的说明文字应该和实际代码修改内容保持一致。 + - + name: PR-standard-check + condition: null + claim: PR是否符合gitee的规范检查要求? + explain: 码云对提交的缺陷扫描、规范扫描告警每一条都需要确认。 + - + name: PR-one-submission + condition: null + claim: PR中是否只有一次提交? + explain: 如果PR中包含多次提交,建议整合成一个,保持提交记录整洁。 + - + name: PR-temp-check + condition: new-file-add + claim: PR中不包含临时文件 + explain: 不能提交临时或无用文件。 + CleanCode: + - + name: static-check + condition: code-modified + claim: 新增代码是否符合规范要求? + explain: 修改涉及代码使用 {lang} 语言开发,建议使用 {checker} 检查并清零告警。 + OpenSourceCompliance: + - + name: license-check + condition: new-file-add + claim: 新增代码文件起始是否含有License信息? + explain: 代码文件开头需要有Copyright和License信息,所使用的License需和本项目使用的License兼容。 + SecurityPrivacy: + - + name: sensitive-info-check + condition: code-modified + claim: 新增代码是否包含密码、口令、token、密钥等敏感数据? + explain: 提交的代码不应包含密码等敏感数据。 +customization: + community: + - + name: sanity_check + condition: sanity_check + claim: "" + explain: "" + cmd: "python3 zh/technical-committee/governance/sanity_check.py ." + failed: + claim: "PR必须通过CI检查" + explain: "sanity_check.py 在这个 PR 中发现错误。" + success: + claim: "是否所有变更的代码仓都被恰当的 SIG 管理?" + explain: "代码仓应当由有能力且有意愿的SIG管理,同一类的软件尽量归属同一个SIG。" + lgtm-chk: + claim: "{sig}的维护者是否同意变更?" + explain: "需要 {owners} 中至少一人在PR的review中留下 \"/lgtm\" 表示确认。" + dlt-chk: + claim: "是否确认删除 {repo} ?" + explain: "为了保证兼容性,技术委员会建议将 {repo} 移动到 sig-recycle 管理一段时间,给用户切换时间。" + - + name: maintainer-add-explain + condition: maintainer-change + claim: "如果新增维护者,有没有对他/她能力的客观说明?" + explain: "PR提交者需要提出相应的举证说明维护者候选人的技术能力与社区活跃程度。" + - + name: maintainer-change-lgtm + condition: maintainer-change + claim: "{sig} 中的其他维护者是否同意增加/删除维护者?" + explain: "需要 {owners} 中至少两人代表在此 PR 的 review 中留下 \"/lgtm\" 表示确认同意接纳或者移除维护者。" + - + name: sig-update-lgtm + condition: sig-update + claim: "{sig} 是否同意更新 SIG 信息?" + explain: "{owners} 中是否有代表通过在此 PR 的 review 中留下 \"/lgtm\" 表示同意。" + - + name: repo-info-check + condition: repo-introduce + claim: "是否正确提供代码仓上游信息?" + explain: "使用软件社区的正式官方网址,或者无单独正式官网的情况下,提供主流代码托管商上面对应的项目网址(如github)。不可使用maven等托管库作为官方网址。" + - + name: repo-name-check + condition: repo-introduce + claim: "代码仓名称是否规范?" + explain: "代码仓名称必须和上游官网/社区保持一致,不可随意命名。不允许以软件包中的子模块作为代码仓名。当软件是某个语言的开发库时,可以使用前缀予以规范化管理(如 python-,perl-等)。" + - + name: upstream-lifecycle-check + condition: repo-introduce + claim: "新引入代码仓的上游是否仍处于生命周期内?" + explain: "已经衰退的软件,生命周期结束,社区停运,或超过5年没有任何更新的软件,原则上不引入openEuler。如果提交者认为非常有必要,可以考虑在 openeuler 中 fork 以后独立维护。" + - + name: repo-license-check + condition: repo-introduce + claim: "新引入的代码仓的 License 授权是否都与 openEuler 兼容?" + explain: "openEuler只能接纳可以被允许集成的软件。" + - + name: repo-copyright-check + condition: repo-introduce + claim: "新引入的代码仓的是否有 Copyright 信息?" + explain: "我们期望软件有明确的 Copyright 信息。" + - + name: encrypt-algorithm-check + condition: repo-introduce + claim: "新引入代码仓是否不涉及从美国代码托管网站引入加解密算法的实现?" + explain: "openEuler作为开源项目整体已经备案,无论是否涉及都不需要额外处理。" diff --git a/advisors/oe_review b/advisors/oe_review deleted file mode 100755 index 5ceb938e..00000000 --- a/advisors/oe_review +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/python3 -#****************************************************************************** -# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. -# licensed under the Mulan PSL v2. -# You can use this software according to the terms and conditions of the Mulan PSL v2. -# You may obtain a copy of Mulan PSL v2 at: -# http://license.coscl.org.cn/MulanPSL2 -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -# PURPOSE. -# See the Mulan PSL v2 for more details. -# ******************************************************************************/ -""" -Review tool for openEuler submission -""" -import os -import argparse -import subprocess - -def main(): - """ - Main entrance of the functionality - """ - pars = argparse.ArgumentParser() - pars.add_argument("-p", "--pull", type=str, help="Number ID of Pull Request", required=True) - pars.add_argument("repo", help="Repository to be reviewed") - pars.add_argument("-r", "--reuse", help="Reuse current local git dirctory", action="store_true") - - args = pars.parse_args() - - gitee_url_prefix = "git@gitee.com:src-openeuler/" - - if not args.reuse: - subprocess.call(["git", "clone", gitee_url_prefix + args.repo]) - os.chdir(args.repo.split('/')[1]) - - subprocess.call(["git", "fetch", - gitee_url_prefix + args.repo, - "pull/{n}/head:pr_{n}".format(n=args.pull)]) - - print("You are reviewing {repo} pull {n}".format(repo=args.repo, n=args.pull)) - print("Don't forget to try to merge master branch") - -if __name__ == "__main__": - main() diff --git a/advisors/tc_review b/advisors/review_tool.py similarity index 41% rename from advisors/tc_review rename to advisors/review_tool.py index 19a9dfd5..9e983952 100755 --- a/advisors/tc_review +++ b/advisors/review_tool.py @@ -18,45 +18,85 @@ import re import sys import argparse import subprocess - +import shutil +import yaml import gitee -BASIC_CHK = """ -**以下为 openEuler-Advisor 的 tc_review 生成审视要求清单** +CHK_TABLE_HEADER = """ +**以下为 openEuler-Advisor 的 review_tool 生成审视要求清单** **[Y]** 审视者确认符合要求 | **[N]** 审视者认为不符合要求 | **[NA]** 审视者认为与本PR无关 | **[?]** 审视者无法确认是否符合要求 | **[ ]** 审视过程中 -|审视情况|审视要求|审视要求说明| -|:--:|:--|:--| -|[ ]|PR的标题是否清晰易懂?|提交标题应该一句话说明本提交实现的内容。| -|[ ]|PR的内容描述是否详细具体?|提交的描述应该用一段话说明本提交的背景和实现原理。| -|[ ]|PR和实际代码修改是否一致?|提交的说明文字应该和实际代码修改内容保持一致。| -|[ ]|PR是否符合gitee的规范检查要求?|码云对提交的缺陷扫描、规范扫描告警每一条都需要确认。| -|[ ]|PR中是否只有一次提交?|如果PR中包含多次提交,应当整合成一个,保持提交记录整洁。| +|审视项编号|审视类别|审视要求|审视要求说明|审视结果| +|:--:|:--|:--|:--|:--:| """ -OWNER_CHK = "|[ ]|如果新增维护者,有没有对他/她能力的客观说明?|PR提交者需要提出相应的举证说明维护者候选人的技术能力与社区活跃程度。|\n" -OWNER_CHK_1 = "|[ ]|{sig} 中的其他维护者是否同意增加/删除维护者?|需要 {owners} 中至少两人代表在此 PR 的 review 中留下 "\ - "\"/lgtm\" 表示确认同意接纳或者移除维护者。|\n" +SANITY_CHK_CMD = "python3 zh/technical-committee/governance/sanity_check.py ." -INFO_CHK = "|[ ]|{sig} 是否同意更新 SIG 信息?| {owners} 中是否有代表通过在此 PR 的 review 中留下 \"/lgtm\" 表示同意。|\n" +CHECKLIST = "helper/reviewer_checklist.yaml" -REPO_CHK = "|[ ]|是否所有变更的代码仓都被恰当的 SIG 管理?|代码仓应当由有能力且有意愿的SIG管理,同一类的软件尽量归属同一个SIG。|\n" -REPO_CHK_1 = "|[ ]|{sig}的维护者是否同意变更|需要 {owners} 中至少一人在PR的review中留下 \"/lgtm\" 表示确认。|\n" +categorizer = {'PRSubmissionSPEC':'PR提交规范', + 'CleanCode':'Clean Code', + 'OpenSourceCompliance':'开源合规性', + 'SecurityPrivacy':'安全及隐私', + 'customization':'定制项'} -DEL_CHK = "|[ ]|是否确认删除 {repo} ?|为了保证兼容性,技术委员会建议将 {repo} 移动到 sig-recycle 管理一段时间,给用户切换时间。|\n" +__NUMBER = 0 -UPSTREAM_CHK = "|[ ]|是否正确提供代码仓上游信息?|使用软件社区的正式官方网址,或者无单独正式官网的情况下,提供主流代码托管商上面"\ - "对应的项目网址(如github)。不可使用maven等托管库作为官方网址。|\n" -NAME_CHK = "|[ ]|代码仓名称是否规范?|代码仓名称必须和上游官网/社区保持一致,不可随意命名。不允许以软件包中的子模块作为代码仓名。"\ - "当软件是某个语言的开发库时,可以使用前缀予以规范化管理(如 python-,perl-等)。|\n" -EOS_CHK = "|[ ]|新引入代码仓的上游是否仍处于生命周期内?|已经衰退的软件,生命周期结束,社区停运,或超过5年没有任何更新的软件,"\ - "原则上不引入openEuler。如果提交者认为非常有必要,可以考虑在 openeuler 中 fork 以后独立维护。|\n" -LICENSE_CHK = "|[ ]|新引入的代码仓的 License 授权是否都与 openEuler 兼容?|openEuler只能接纳可以被允许集成的软件。|\n" -COPYRIGHT_CHK = "|[ ]|新引入的代码仓的是否有 Copyright 信息?|我们期望软件有明确的 Copyright 信息。|\n" -ENCRYPTION_CHK = "|[ ]|新引入代码仓是否不涉及从美国代码托管网站引入加解密算法的实现?| "\ - "openEuler作为开源项目整体已经备案,无论是否涉及都不需要额外处理。|\n" +def check_new_code(): + """ + Check if new code file has been introduced + """ + lst_files = subprocess.getoutput("git diff --name-only --diff-filter=A remotes/origin/master..") + return bool(lst_files.splitlines()) + + +def check_code_lang(): + """ + Check this PR code programming language + """ + langs = [] + checkers = [] + lst_files = subprocess.getoutput("git diff --name-only remotes/origin/master..") + for item in lst_files.splitlines(): + if item.endswith(".py") and "Python" not in langs: + langs.append("Python") + checkers.append("pylint-3") + elif item.endswith(".go") and "GO" not in langs: + langs.append("GO") + checkers.append("golint") + elif item.endswith(".c") and "C/C++" not in langs: + langs.append("C/C++") + checkers.append("pclint") + elif item.endswith(".cpp") and "C/C++" not in langs: + langs.append("C/C++") + checkers.append("pclint") + elif item.endswith(".h") and "C/C++" not in langs: + langs.append("C/C++") + checkers.append("pclint") + return langs, checkers + + +def load_checklist(chklist_path): + """ + load configuration + """ + try: + with open(chklist_path, 'r', encoding = 'utf-8') as f: + return yaml.load(f.read(), Loader = yaml.Loader) + except OSError as reason: + print("Load yaml failed!" + str(reason)) + return None + + +def join_check_item(category, claim, explain): + """ + join check item as a table row + """ + global __NUMBER + res = "|" + str(__NUMBER) + "|" + category + "|" + claim + "|" + explain + "|[ ]|\n" + __NUMBER += 1 + return res -SANITY_CHK_CMD = "python3 zh/technical-committee/governance/sanity_check.py ." def check_repository_changes(): """ @@ -68,15 +108,17 @@ def check_repository_changes(): return True return False -def check_repository_mgmt_changes(sigs): +def check_repository_mgmt_changes(sigs, info): """ Return additional checking item if management of repository has been changed """ review_body = "" need_additional_review = False - ret_code, lst_files = subprocess.getstatusoutput(SANITY_CHK_CMD) + ret_code, lst_files = subprocess.getstatusoutput(info['cmd']) if ret_code != 0: - return False, "|[ ]|PR必须通过CI检查|sanity_check.py 在这个 PR 中发现错误。|\n" + chk = join_check_item(categorizer['customization'], + info['failed']['claim'], info['failed']['explain']) + return chk for item in lst_files.splitlines(): if item.startswith("SUGGESTION: This PR needs to be reviewed"): need_additional_review = True @@ -87,12 +129,19 @@ def check_repository_mgmt_changes(sigs): sig = result.group(1) owners = result.group(2) if sig not in sigs: - review_body += REPO_CHK_1.format(sig=sig, owners=owners) + chk = join_check_item(categorizer['customization'], + info['lgtm-chk']['claim'], info['lgtm-chk']['explain']) + review_body += chk.format(sig=sig, owners=owners) else: result = re.match("WARNING! deleting (.*)", item) if result: - review_body += DEL_CHK.format(repo=result.group(1)) - return need_additional_review, review_body + chk = join_check_item(categorizer['customization'], + info['dlt-chk']['claim'], info['dlt-chk']['explain']) + review_body += chk.format(repo=result.group(1)) + if need_additional_review: + review_body += join_check_item(categorizer['customization'], + info['success']['claim'], info['success']['explain']) + return review_body def check_maintainer_changes(): @@ -116,6 +165,7 @@ def check_maintainer_changes(): sigs[sig] = " ".join(owners) return sigs + def check_sig_information_changes(): """ return all SIGs with changed information @@ -142,7 +192,88 @@ def check_sig_information_changes(): sigs[sig] = " ".join(owners) return sigs -def review(pull_request): + +def basic_review(cklist): + """ + basic review body + """ + review_body = "" + for key1, value1 in cklist['basic'].items(): + for value2 in value1: + if value2["condition"] == "code-modified": + if value2["name"] == "static-check": + langs, checkers = check_code_lang() + if not langs: + continue + item = join_check_item(categorizer[key1], + value2['claim'], value2['explain']) + item = item.format(lang="/".join(langs), checker="/".join(checkers)) + review_body += item + elif value2["condition"] == "new-file-add": + if not check_new_code(): + continue + item = join_check_item(categorizer[key1], + value2['claim'], value2['explain']) + review_body += item + else: + item = join_check_item(categorizer[key1], + value2['claim'], value2['explain']) + review_body += item + return review_body + + +def community_maintainer_change_review(cstm_item, sigs): + """ + maintainer changed review body + """ + review_body = "" + if cstm_item['name'] == "maintainer-add-explain": + item = join_check_item(categorizer['customization'], + cstm_item['claim'], cstm_item['explain']) + review_body += item + elif cstm_item['name'] == "maintainer-change-lgtm": + for sig in sigs: + item = join_check_item(categorizer['customization'], + cstm_item['claim'], cstm_item['explain']) + review_body += item.format(sig=sig, owners=sigs[sig]) + return review_body + + +def community_review(custom_items): + """ + generate repository 'community' review body + """ + review_body = "" + sigs = check_maintainer_changes() + info_sigs = check_sig_information_changes() + repo_change = check_repository_changes() + for cstm_item in custom_items: + if cstm_item['condition'] == "maintainer-change": + if not sigs: + continue + review_body += community_maintainer_change_review(cstm_item, sigs) + elif cstm_item['condition'] == "sig-update": + if not info_sigs: + continue + for sig in info_sigs: + if sig in sigs: + continue + item = join_check_item(categorizer['customization'], + cstm_item['claim'], cstm_item['explain']) + review_body += item.format(sig=sig, owners=info_sigs[sig]) + elif cstm_item['condition'] == 'repo-introduce': + if not repo_change: + continue + item = join_check_item(categorizer['customization'], + cstm_item['claim'], cstm_item['explain']) + review_body += item + elif cstm_item['condition'] == 'sanity_check': + add_review = check_repository_mgmt_changes(info_sigs, cstm_item) + review_body += add_review + return review_body + + +def review(pull_request, repo_name, chklist_path): """ Return check list of this PR """ @@ -150,51 +281,53 @@ def review(pull_request): if not pull_request["mergeable"]: return "PR中存在冲突,无法自动合并。需要先解决冲突,才可以开展评审。" - review_body = BASIC_CHK - subprocess.call(["git", "merge", "--no-edit", "remotes/origin/master"]) - sigs = check_maintainer_changes() - if sigs: - review_body += OWNER_CHK - for sig in sigs: - review_body += OWNER_CHK_1.format(sig=sig, owners=sigs[sig]) - - info_sigs = check_sig_information_changes() - for sig in info_sigs: - if sig in sigs: - continue - review_body += INFO_CHK.format(sig=sig, owners=info_sigs[sig]) - - additional, add_review = check_repository_mgmt_changes(info_sigs) - if additional: - review_body += REPO_CHK - review_body += add_review - - if check_repository_changes(): - review_body += UPSTREAM_CHK - review_body += NAME_CHK - review_body += EOS_CHK - review_body += LICENSE_CHK - review_body += COPYRIGHT_CHK - review_body += ENCRYPTION_CHK + review_body = CHK_TABLE_HEADER + cklist = load_checklist(chklist_path) + review_body += basic_review(cklist) + custom_items = cklist['customization'].get(repo_name, None) + if custom_items: + if repo_name == "community": + review_body += community_review(custom_items) + else: + for cstm_item in custom_items: + item = join_check_item(categorizer['customization'], + cstm_item['claim'], cstm_item['explain']) + review_body += item return review_body + def main(): """ Main entrance of the functionality """ + cur_path = os.path.dirname(os.path.abspath(sys.argv[0])) + pars = argparse.ArgumentParser() + pars.add_argument("-n", "--repo", type=str, help="Repository name that include group", + required=True, default=False) pars.add_argument("-p", "--pull", type=str, help="Number ID of Pull Request", required=True) pars.add_argument("-r", "--reuse", help="Reuse current local git dirctory", action="store_true") + pars.add_argument("-w", "--workdir", type=str, help="Work directory", default=cur_path) args = pars.parse_args() user_gitee = gitee.Gitee() - - gitee_url = "git@gitee.com:openeuler/community" - + chklist_path = os.path.join(cur_path, CHECKLIST) + work_dir = os.path.realpath(args.workdir) + if not os.path.exists(work_dir): + os.makedirs(work_dir) + gitee_url = "git@gitee.com:{repo}".format(repo=args.repo) + group = args.repo.split('/')[0] + repo_name = args.repo.split('/')[1] + local_path = os.path.join(work_dir, repo_name) if not args.reuse: - subprocess.call(["git", "clone", gitee_url]) - os.chdir(args.repo.split('/')[1]) + if os.path.exists(local_path): + shutil.rmtree(local_path) + subprocess.call(["git", "clone", gitee_url, local_path]) + if not os.path.exists(local_path): + print("%s not exist, can not use option -r" % local_path) + sys.exit(1) + os.chdir(local_path) ret_code = subprocess.call(["git", "checkout", "master"]) if ret_code != 0: @@ -219,11 +352,12 @@ def main(): subprocess.call(["git", "checkout", "pr_{n}".format(n=args.pull)]) - pull_request = user_gitee.get_pr("community", args.pull, "openeuler") - review_comment = review(pull_request) - #print(review_comment) + subprocess.call(["git", "merge", "--no-edit", "remotes/origin/master"]) + + pull_request = user_gitee.get_pr(repo_name, args.pull, group) + review_comment = review(pull_request, repo_name, chklist_path) - user_gitee.create_pr_comment("community", args.pull, review_comment, "openeuler") + user_gitee.create_pr_comment(repo_name, args.pull, review_comment, group) if __name__ == "__main__": main() diff --git a/advisors/self_review b/advisors/self_review deleted file mode 100755 index 7b29dbba..00000000 --- a/advisors/self_review +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/python3 -#****************************************************************************** -# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. -# licensed under the Mulan PSL v2. -# You can use this software according to the terms and conditions of the Mulan PSL v2. -# You may obtain a copy of Mulan PSL v2 at: -# http://license.coscl.org.cn/MulanPSL2 -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -# PURPOSE. -# See the Mulan PSL v2 for more details. -# ******************************************************************************/ -""" -Review tool for openEuler submission -""" -import os -import argparse -import subprocess - -import gitee - -BASIC_CHK = """ -**以下为 openEuler-Advisor 生成的审视要求清单** -**[Y]** 审视者确认符合要求 | **[N]** 审视者认为不符合要求 | **[?]** 审视者无法确认是否符合要求 | **[ ]** 审视过程中 -|审视情况|审视要求|审视要求说明| -|:--:|:--|:--| -|[ ]|PR的标题是否清晰易懂?|提交标题应该一句话说明本提交实现的内容。| -|[ ]|PR的内容描述是否详细具体?|提交的描述应该用一段话说明本提交的背景和实现原理。| -|[ ]|PR和实际代码修改是否一致?|提交的说明文字应该和实际代码修改内容保持一致。| -|[ ]|PR是否符合gitee的规范检查要求?|码云对提交的缺陷扫描、规范扫描告警每一条都需要确认。| -|[ ]|PR中是否只有一次提交?|如果PR中包含多次提交,应当整合成一个,保持提交记录整洁。| -""" - -LICENSE_CHK = "|[ ]|新增代码文件起始是否含有License信息?|"\ - "openEuler-Advisor遵循Mulan PSL v2协议,代码文件开头需要有Copyright和License信息。|\n" -PYLINT_CHK = "|[ ]|新增代码是否符合规范要求?|openEuler-Advisor主要由python3开发,建议pylint-3告警清零。|\n" - -def check_new_code(): - """ - Check if new code file has been introduced - """ - lst_files = subprocess.getoutput("git diff --name-only --diff-filter=A remotes/origin/master..") - return bool(lst_files.splitlines()) - - -def check_python_code_changes(): - """ - Check if this PR includes python code - """ - lst_files = subprocess.getoutput("git diff --name-only remotes/origin/master..") - for item in lst_files.splitlines(): - if item.endswith(".py"): - return True - return False - - -def review(pull_request): - """ - Return review check list - """ - _ = pull_request - review_body = BASIC_CHK - if check_python_code_changes(): - review_body += PYLINT_CHK - if check_new_code(): - review_body += LICENSE_CHK - return review_body - -def main(): - """ - Main entrance of the functionality - """ - pars = argparse.ArgumentParser() - pars.add_argument("-p", "--pull", type=str, help="Number ID of Pull Request", required=True) - pars.add_argument("-r", "--reuse", help="Reuse current local git dirctory", action="store_true") - - args = pars.parse_args() - - user_gitee = gitee.Gitee() - - gitee_url = "git@gitee.com:openeuler/openEuler-Advisor" - - if not args.reuse: - subprocess.call(["git", "clone", gitee_url]) - os.chdir(args.repo.split('/')[1]) - - subprocess.call(["git", "fetch", gitee_url, - "pull/{n}/head:pr_{n}".format(n=args.pull)]) - - print("You are reviewing pull {n}".format(n=args.pull)) - - subprocess.call(["git", "checkout", "pr_{n}".format(n=args.pull)]) - subprocess.call(["git", "merge", "--no-edit", "master"]) - - pull_request = user_gitee.get_pr("openEuler-Advisor", args.pull, "openeuler") - review_comment = review(pull_request) - - user_gitee.create_pr_comment("openEuler-Advisor", args.pull, review_comment, "openeuler") - -if __name__ == "__main__": - main() -- Gitee