diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..600d2d33badf45cc068e01d2e3c837e11c417bc4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode \ No newline at end of file diff --git a/gate_ci/.gitlint b/gate_ci/.gitlint new file mode 100644 index 0000000000000000000000000000000000000000..d85adb867e58a706e09444d470f5b096e0dc225d --- /dev/null +++ b/gate_ci/.gitlint @@ -0,0 +1,269 @@ +# Edit this file as you like. +# +# All these sections are optional. Each section with the exception of [general] represents +# one rule and each key in it is an option for that specific rule. +# +# Rules and sections can be referenced by their full name or by id. For example +# section "[body-max-line-length]" could also be written as "[B1]". Full section names are +# used in here for clarity. +# +[general] +# Ignore certain rules, this example uses both full name and id +# ignore=title-trailing-punctuation, T3 + +# verbosity should be a value between 1 and 3, the commandline -v flags take precedence over this +# verbosity = 2 + +# By default gitlint will ignore merge, revert, fixup and squash commits. +# ignore-merge-commits=true +# ignore-revert-commits=true +# ignore-fixup-commits=true +# ignore-squash-commits=true + +# Ignore any data send to gitlint via stdin +# ignore-stdin=true + +# Fetch additional meta-data from the local repository when manually passing a +# commit message to gitlint via stdin or --commit-msg. Disabled by default. +# staged=true + +# Hard fail when the target commit range is empty. Note that gitlint will +# already fail by default on invalid commit ranges. This option is specifically +# to tell gitlint to fail on *valid but empty* commit ranges. +# Disabled by default. +# fail-without-commits=true + +# Enable debug mode (prints more output). Disabled by default. +# debug=true + +# Enable community contributed rules +# See http://jorisroovers.github.io/gitlint/contrib_rules for details +#contrib=contrib-title-conventional-commits,CC1 +contrib=CC1 + +# Set the extra-path where gitlint will search for user defined rules +# See http://jorisroovers.github.io/gitlint/user_defined_rules for details +# extra-path=examples/ + +# This is an example of how to configure the "title-max-length" rule and +# set the line-length it enforces to 50 +[title-max-length] +line-length=80 + +# Conversely, you can also enforce minimal length of a title with the +# "title-min-length" rule: +[title-min-length] +min-length=5 + +# [title-must-not-contain-word] +# Comma-separated list of words that should not occur in the title. Matching is case +# insensitive. It's fine if the keyword occurs as part of a larger word (so "WIPING" +# will not cause a violation, but "WIP: my title" will. +# words=wip + +[title-match-regex] +# python-style regex that the commit-msg title must match +# Note that the regex can contradict with other rules if not used correctly +# (e.g. title-must-not-contain-word). +regex=^(([0-9a-zA-Z]|-|_){1,}(: ))(.){1,}$ + +[body-max-line-length] +line-length=72 + +[body-min-length] +min-length=5 + +# [body-is-missing] +# Whether to ignore this rule on merge commits (which typically only have a title) +# default = True +# ignore-merge-commits=false + +# [body-changed-file-mention] +# List of files that need to be explicitly mentioned in the body when they are changed +# This is useful for when developers often erroneously edit certain files or git submodules. +# By specifying this rule, developers can only change the file when they explicitly reference +# it in the commit message. +# files=gitlint-core/gitlint/rules.py,README.md + +# [body-match-regex] +# python-style regex that the commit-msg body must match. +# E.g. body must end in My-Commit-Tag: foo +# regex=My-Commit-Tag: foo$ + +# [author-valid-email] +# python-style regex that the commit author email address must match. +# For example, use the following regex if you only want to allow email addresses from foo.com +# regex=[^@]+@foo.com + +# [ignore-by-title] +# Ignore certain rules for commits of which the title matches a regex +# E.g. Match commit titles that start with "Release" +# regex=^Release(.*) + +# Ignore certain rules, you can reference them by their id or by their full name +# Use 'all' to ignore all rules +# ignore=T1,body-min-length + +# [ignore-by-body] +# Ignore certain rules for commits of which the body has a line that matches a regex +# E.g. Match bodies that have a line that that contain "release" +# regex=(.*)release(.*) +# +# Ignore certain rules, you can reference them by their id or by their full name +# Use 'all' to ignore all rules +# ignore=T1,body-min-length + +# [ignore-body-lines] +# Ignore certain lines in a commit body that match a regex. +# E.g. Ignore all lines that start with 'Co-Authored-By' +# regex=^Co-Authored-By + +# [ignore-by-author-name] +# Ignore certain rules for commits of which the author name matches a regex +# E.g. Match commits made by dependabot +# regex=(.*)dependabot(.*) +# +# Ignore certain rules, you can reference them by their id or by their full name +# Use 'all' to ignore all rules +# ignore=T1,body-min-length + +# This is a contrib rule - a community contributed rule. These are disabled by default. +# You need to explicitly enable them one-by-one by adding them to the "contrib" option +# under [general] section above. +# [contrib-title-conventional-commits] +# Specify allowed commit types. For details see: https://www.conventionalcommits.org/ +# types = bugfix,user-story,epic# Edit this file as you like. +# +# All these sections are optional. Each section with the exception of [general] represents +# one rule and each key in it is an option for that specific rule. +# +# Rules and sections can be referenced by their full name or by id. For example +# section "[body-max-line-length]" could also be written as "[B1]". Full section names are +# used in here for clarity. +# +[general] +# Ignore certain rules, this example uses both full name and id +# ignore=title-trailing-punctuation, T3 + +# verbosity should be a value between 1 and 3, the commandline -v flags take precedence over this +# verbosity = 2 + +# By default gitlint will ignore merge, revert, fixup and squash commits. +# ignore-merge-commits=true +# ignore-revert-commits=true +# ignore-fixup-commits=true +# ignore-squash-commits=true + +# Ignore any data send to gitlint via stdin +# ignore-stdin=true + +# Fetch additional meta-data from the local repository when manually passing a +# commit message to gitlint via stdin or --commit-msg. Disabled by default. +# staged=true + +# Hard fail when the target commit range is empty. Note that gitlint will +# already fail by default on invalid commit ranges. This option is specifically +# to tell gitlint to fail on *valid but empty* commit ranges. +# Disabled by default. +# fail-without-commits=true + +# Enable debug mode (prints more output). Disabled by default. +# debug=true + +# Enable community contributed rules +# See http://jorisroovers.github.io/gitlint/contrib_rules for details +#contrib=contrib-title-conventional-commits,CC1 +contrib=CC1 + +# Set the extra-path where gitlint will search for user defined rules +# See http://jorisroovers.github.io/gitlint/user_defined_rules for details +# extra-path=examples/ + +# This is an example of how to configure the "title-max-length" rule and +# set the line-length it enforces to 50 +[title-max-length] +line-length=80 + +# Conversely, you can also enforce minimal length of a title with the +# "title-min-length" rule: +[title-min-length] +min-length=5 + +# [title-must-not-contain-word] +# Comma-separated list of words that should not occur in the title. Matching is case +# insensitive. It's fine if the keyword occurs as part of a larger word (so "WIPING" +# will not cause a violation, but "WIP: my title" will. +# words=wip + +[title-match-regex] +# python-style regex that the commit-msg title must match +# Note that the regex can contradict with other rules if not used correctly +# (e.g. title-must-not-contain-word). +regex=^(([0-9a-zA-Z]|-|_){1,}(: ))(.){1,}$ + +[body-max-line-length] +line-length=72 + +[body-min-length] +min-length=5 + +# [body-is-missing] +# Whether to ignore this rule on merge commits (which typically only have a title) +# default = True +# ignore-merge-commits=false + +# [body-changed-file-mention] +# List of files that need to be explicitly mentioned in the body when they are changed +# This is useful for when developers often erroneously edit certain files or git submodules. +# By specifying this rule, developers can only change the file when they explicitly reference +# it in the commit message. +# files=gitlint-core/gitlint/rules.py,README.md + +# [body-match-regex] +# python-style regex that the commit-msg body must match. +# E.g. body must end in My-Commit-Tag: foo +# regex=My-Commit-Tag: foo$ + +# [author-valid-email] +# python-style regex that the commit author email address must match. +# For example, use the following regex if you only want to allow email addresses from foo.com +# regex=[^@]+@foo.com + +# [ignore-by-title] +# Ignore certain rules for commits of which the title matches a regex +# E.g. Match commit titles that start with "Release" +# regex=^Release(.*) + +# Ignore certain rules, you can reference them by their id or by their full name +# Use 'all' to ignore all rules +# ignore=T1,body-min-length + +# [ignore-by-body] +# Ignore certain rules for commits of which the body has a line that matches a regex +# E.g. Match bodies that have a line that that contain "release" +# regex=(.*)release(.*) +# +# Ignore certain rules, you can reference them by their id or by their full name +# Use 'all' to ignore all rules +# ignore=T1,body-min-length + +# [ignore-body-lines] +# Ignore certain lines in a commit body that match a regex. +# E.g. Ignore all lines that start with 'Co-Authored-By' +# regex=^Co-Authored-By + +# [ignore-by-author-name] +# Ignore certain rules for commits of which the author name matches a regex +# E.g. Match commits made by dependabot +# regex=(.*)dependabot(.*) +# +# Ignore certain rules, you can reference them by their id or by their full name +# Use 'all' to ignore all rules +# ignore=T1,body-min-length + +# This is a contrib rule - a community contributed rule. These are disabled by default. +# You need to explicitly enable them one-by-one by adding them to the "contrib" option +# under [general] section above. +# [contrib-title-conventional-commits] +# Specify allowed commit types. For details see: https://www.conventionalcommits.org/ +# types = bugfix,user-story,epic \ No newline at end of file diff --git a/gate_ci/comment.yaml b/gate_ci/comment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3eb8038302d6870b70360b676a72fcd85242087b --- /dev/null +++ b/gate_ci/comment.yaml @@ -0,0 +1,2 @@ +openeuler: + arch_list: ['aarch64','arm'] \ No newline at end of file diff --git a/gate_ci/gitee_comment_openeuler.py b/gate_ci/gitee_comment_openeuler.py new file mode 100644 index 0000000000000000000000000000000000000000..419b7720198292779e700b2bb85c20e3f3168ef2 --- /dev/null +++ b/gate_ci/gitee_comment_openeuler.py @@ -0,0 +1,468 @@ +# -*- coding: utf-8 -*- +""" +# ********************************************************************************** +# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. +# [openeuler-jenkins] is 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. +# Author: +# Create: 2020-09-23 +# Description: comment pr with build result +# ********************************************************************************** +""" +import os +import re +import stat +import sys +import logging.config +import json +import argparse +import warnings +import yaml +from urllib.parse import unquote + +from yaml.error import YAMLError +from src.ac.framework.ac_result import ACResult, SUCCESS +from src.proxy.gitee_proxy import GiteeProxy +from src.proxy.kafka_proxy import KafkaProducerProxy +from src.proxy.jenkins_proxy import JenkinsProxy +from src.utils.dist_dataset import DistDataset + + +class Comment(object): + """ + comments process + """ + + def __init__(self, pr, jenkins_proxy, *check_item_comment_files): + """ + + :param pr: pull request number + """ + self._pr = pr + self._check_item_comment_files = check_item_comment_files + self._up_builds = [] + self._up_up_builds = [] + self._get_upstream_builds(jenkins_proxy) + self.ac_result = {} + self.compare_package_result = {} + self.check_item_result = {} + self._arch_list=self.get_arch_list() + + @staticmethod + def get_arch_list(): + comment_dir = os.path.dirname(os.path.realpath(__file__))+"/comment.yaml" + with open(comment_dir, "r") as f: + try: + arch_list = yaml.safe_load(f) + arch_list = arch_list["openeuler"]["arch_list"] + except YAMLError: + logger.exception("illegal yaml format of check item comment file ") + return arch_list + + def comment_build(self, gitee_proxy): + """ + 构建结果 + :param jenkins_proxy: + :param gitee_proxy: + :return: + """ + comments = self._comment_build_html_format() + gitee_proxy.comment_pr(self._pr, "\n".join(comments)) + + return "\n".join(comments) + + def comment_at(self, committer, gitee_proxy): + """ + 通知committer + @committer + :param committer: + :param gitee_proxy: + :return: + """ + gitee_proxy.comment_pr(self._pr, "@{}".format(committer)) + + def check_build_result(self): + """ + build result check + :return: + """ + build_result = sum([ACResult.get_instance(build["result"]) for build in self._up_builds], SUCCESS) + return build_result + + def _get_upstream_builds(self, jenkins_proxy): + """ + get upstream builds + :param jenkins_proxy: + :return: + """ + base_job_name = os.environ.get("JOB_NAME") + base_build_id = os.environ.get("BUILD_ID") + base_build_id = int(base_build_id) + logger.debug("base_job_name: %s, base_build_id: %s", base_job_name, base_build_id) + base_build = jenkins_proxy.get_build_info(base_job_name, base_build_id) + logger.debug("get base build") + self._up_builds = jenkins_proxy.get_upstream_builds(base_build) + if self._up_builds: + logger.debug("get up_builds") + self._up_up_builds = jenkins_proxy.get_upstream_builds(self._up_builds[0]) + + def _comment_build_html_format(self): + """ + 组装构建信息,并评论pr + :param jenkins_proxy: JenkinsProxy object + :return: + """ + comments = ["", self.comment_html_table_th()] + + if self._up_up_builds: + logger.debug("get up_up_builds") + comments.extend(self._comment_of_ac(self._up_up_builds[0])) + if self._up_builds: + comments.extend(self._comment_of_check_item(self._up_builds)) + + comments.append("
") + return comments + + def _comment_of_ac(self, build): + """ + 组装门禁检查结果 + :param build: Jenkins Build object,门禁检查jenkins构建对象 + :return: + """ + if "ACL" not in os.environ: + logger.debug("no ac check") + return [] + + try: + acl = json.loads(os.environ["ACL"]) + logger.debug("ac result: %s", acl) + except ValueError: + logger.exception("invalid ac result format") + return [] + except Exception as e: + logger.exception(e) + return [] + + comments = [] + + for index, item in enumerate(acl): + ac_result = ACResult.get_instance(item["result"]) + if index == 0: + build_url = build["url"] + comments.append(self.__class__.comment_html_table_tr( + item["name"], ac_result.emoji, ac_result.hint, + "{}{}".format(build_url, "console"), build["number"], rowspan=len(acl))) + else: + comments.append(self.__class__.comment_html_table_tr_rowspan( + item["name"], ac_result.emoji, ac_result.hint)) + self.ac_result[item["name"]] = ac_result.hint + logger.info("ac comment: %s", comments) + + return comments + + def match(self,name, comment_file): + for arch_name in self._arch_list: + if "/"+arch_name+"/" in name and "_"+arch_name+"_" in comment_file: + return True + return False + + def _comment_of_check_item(self, builds): + """ + check item comment + :param builds: + :return: + """ + comment_file_dict = self._get_comment_file_dict() + build_dict = self._get_build_dict(builds) + tr_list = [] + for arch_name,arch_result in build_dict.items(): + arch_name_rows_span = 0 + arch_comment_dict = comment_file_dict.get(arch_name,{}) + is_first = True + first_image = "" + for image_name, image_result in arch_result.items(): + image_rows_span = 0 + if "result" in image_result and ACResult.get_instance(image_result.get("result")) == SUCCESS: + image_rows_span = len(arch_comment_dict.get(image_name, {})) + arch_name_rows_span += 1 + image_rows_span + if is_first: + first_image = image_name + is_first = False + + for image_name, image_result in arch_result.items(): + image_name_rows_span = 1 + if "result" in image_result and ACResult.get_instance(image_result.get("result")) == SUCCESS: + image_name_rows_span += len(arch_comment_dict.get(image_name, {})) + if image_name == first_image: + tr_list.append({"arch_name": arch_name, "arch_name_rows_span": arch_name_rows_span, \ + "image_name": image_name, "image_name_rows_span": image_name_rows_span, "check_name": "build", \ + "status": image_result["result"], "build_url": image_result["build_url"], "build_no": image_result["build_no"]}) + if "result" in image_result and ACResult.get_instance(image_result.get("result")) == SUCCESS: + for check_name, check_result in arch_comment_dict.get(image_name,{}).items(): + tr_list.append({"check_name": check_name,"status": check_result}) + else: + tr_list.append({"image_name": image_name, "image_name_rows_span": image_name_rows_span, "check_name": "build", \ + "status": image_result["result"], "build_url": image_result["build_url"], "build_no": image_result["build_no"]}) + if "result" in image_result and ACResult.get_instance(image_result.get("result")) == SUCCESS: + for check_name,check_result in arch_comment_dict.get(image_name, {}).items(): + tr_list.append({"check_name": check_name, "status": check_result}) + + comments = [] + for tr in tr_list: + tr_str = "" + if "arch_name" in tr: + tr_str += "{}".format(tr.get("arch_name_rows_span"), tr.get("arch_name")) + if "image_name" in tr: + tr_str += "{}".format(tr.get("image_name_rows_span"), tr.get("image_name")) + tr_str += "{}".format(tr.get("check_name")) + ac_result = ACResult.get_instance(tr.get("status")) + tr_str += "{}{}".format(ac_result.emoji, ac_result.hint) + if "build_url" in tr: + tr_str += "#{}".format(\ + tr.get("image_name_rows_span"),\ + "{}{}".format(tr.get("build_url"), "console"),\ + tr.get("build_no")) + tr_str += "" + comments.append(tr_str) + return comments + + def _get_build_dict(self,builds): + res_dict = {} + for build in builds: + name, _ = JenkinsProxy.get_job_path_build_no_from_build_url(build["url"]) + status = build["result"] + build_url = build["url"] + + is_continue = True + arch = "" + for arch_name in self._arch_list: + if "/"+arch_name+"/" in name: + arch = arch_name + is_continue = False + break + if is_continue: + continue + current_arch = res_dict.get(arch, {}) + image_name = re.compile(r'\((.+)\)').search(unquote(name)).group(1) + current_arch[image_name] = {"result": status, "build_url": build_url, "build_no": build["number"]} + res_dict[arch] = current_arch + return res_dict + + + def _get_comment_file_dict(self): + res_dict = {} + for check_comment_file in self._check_item_comment_files: + current_name = "" + current_arch = {} + for arch in self._arch_list: + if "_" + arch + "_" in check_comment_file: + current_name = arch + current_arch = res_dict.get(arch, {}) + break + if os.path.exists(check_comment_file): + with open(check_comment_file, "r") as f: + image_name = re.compile(r'\((.+)\)').search(check_comment_file).group(1) + image_dict = current_arch.get(image_name, {}) + try: + content = yaml.safe_load(f) + except YAMLError: # yaml base exception + logger.exception("illegal yaml format of check item comment file ") + logger.debug("comment: %s", content) + for item in content: + image_dict[item.get("name")] = item.get("result") + current_arch[image_name] = image_dict + else: + logger.info(check_comment_file+" is not exists") + continue + res_dict[current_name] = current_arch + + return res_dict + + + @classmethod + def comment_html_table_th(cls): + """ + table header + """ + return "Check Name Build Result Build Details" + + @classmethod + def comment_html_table_tr(cls, name, icon, status, href, build_no, hashtag=True, rowspan=1): + """ + one row or span row + """ + return "{} {}{} " \ + "{}{}".format( + name, icon, status, rowspan, href, "#" if hashtag else "", build_no) + + @classmethod + def comment_html_table_tr_rowspan(cls, name, icon, status): + """ + span row + """ + return "{} {}{}".format(name, icon, status) + + def _get_job_url(self, comment_url): + """ + get_job_url + :param url: + :return: + """ + build_urls = {"trigger": self._up_up_builds[0]["url"], + "comment": os.path.join(comment_url, os.environ.get("BUILD_ID")) + } + for build in self._up_builds: + arch = "" + try: + arch_index = 3 + list_step = 2 + if build["url"]: + job_path = re.sub(r"http[s]?://", "", build["url"]) + arch = job_path.split("/")[::list_step][arch_index] + except IndexError: + logger.info("get arch from job failed, index error.") + except KeyError: + logger.info("not find build url key") + if arch: + build_urls[arch] = build["url"] + + return build_urls + + def _get_all_job_result(self, check_details): + """ + get_all_job_result + :return: + """ + + check_details["static_code"] = self.ac_result + for arch, arch_result in self.check_item_result.items(): + if self.compare_package_result.get(arch): + arch_result["compare_package"] = self.compare_package_result.get(arch) + check_details[arch] = arch_result + + return check_details + + def get_all_result_to_kafka(self, comment_url): + """ + 名称 类型 必选 说明 + build_urls 字典 是 包含多个门禁工程链接和显示文本 + check_total 字符串 是 门禁整体结果 + check_details 字典 是 门禁各个检查项结果 + :return: + """ + check_details = {} + build_urls = self._get_job_url(comment_url) + self._get_all_job_result(check_details) + + if self.check_build_result() == SUCCESS: + check_total = 'SUCCESS' + else: + check_total = 'FAILED' + + all_dict = {"build_urls": build_urls, + "check_total": check_total, + "check_details": check_details + } + logger.info("all_dict = %s", all_dict) + flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL + modes = stat.S_IWUSR | stat.S_IRUSR + try: + with os.fdopen(os.open("build_result.yaml", flags, modes), "w") as f: + yaml.safe_dump(all_dict, f) + except IOError: + logger.exception("save build result file exception") + + +def init_args(): + """ + init args + :return: + """ + parser = argparse.ArgumentParser() + parser.add_argument("-p", type=int, dest="pr", help="pull request number") + parser.add_argument("-m", type=str, dest="comment_id", help="uniq comment id") + parser.add_argument("-c", type=str, dest="committer", help="commiter") + parser.add_argument("-o", type=str, dest="owner", help="gitee owner") + parser.add_argument("-r", type=str, dest="repo", help="repo name") + parser.add_argument("-t", type=str, dest="gitee_token", help="gitee api token") + + parser.add_argument("-b", type=str, dest="jenkins_base_url", default="https://openeulerjenkins.osinfra.cn/", + help="jenkins base url") + parser.add_argument("-u", type=str, dest="jenkins_user", help="repo name") + parser.add_argument("-j", type=str, dest="jenkins_api_token", help="jenkins api token") + parser.add_argument("-f", type=str, dest="check_result_file", default="", help="compare package check item result") + parser.add_argument("-a", type=str, dest="check_item_comment_files", nargs="*", help="check item comment files") + + parser.add_argument("--disable", dest="enable", default=True, action="store_false", help="comment to gitee switch") + + return parser.parse_args() + + +if "__main__" == __name__: + args = init_args() + if not args.enable: + sys.exit(0) + + _ = not os.path.exists("log") and os.mkdir("log") + logger_conf_path = os.path.realpath(os.path.join(os.path.realpath(__file__), "../../conf/logger.conf")) + logging.config.fileConfig(logger_conf_path) + logger = logging.getLogger("build") + + dd = DistDataset() + dd.set_attr_stime("comment.job.stime") + + # gitee pr tag + gp = GiteeProxy(args.owner, args.repo, args.gitee_token) + gp.delete_tag_of_pr(args.pr, "ci_processing") + + jp = JenkinsProxy(args.jenkins_base_url, args.jenkins_user, args.jenkins_api_token) + url, build_time, reason = jp.get_job_build_info(os.environ.get("JOB_NAME"), int(os.environ.get("BUILD_ID"))) + dd.set_attr_ctime("comment.job.ctime", build_time) + dd.set_attr("comment.job.link", url) + dd.set_attr("comment.trigger.reason", reason) + + dd.set_attr_stime("comment.build.stime") + + comment = Comment(args.pr, jp, *args.check_item_comment_files) \ + if args.check_item_comment_files else Comment(args.pr, jp) + logger.info("comment: build result......") + comment_content = comment.comment_build(gp) + dd.set_attr_etime("comment.build.etime") + dd.set_attr("comment.build.content.html", comment_content) + + if comment.check_build_result() == SUCCESS: + gp.delete_tag_of_pr(args.pr, "ci_failed") + gp.create_tags_of_pr(args.pr, "ci_successful") + dd.set_attr("comment.build.tags", ["ci_successful"]) + dd.set_attr("comment.build.result", "successful") + if args.check_result_file: + comment.comment_compare_package_details(gp, args.check_result_file) + else: + gp.delete_tag_of_pr(args.pr, "ci_successful") + gp.create_tags_of_pr(args.pr, "ci_failed") + dd.set_attr("comment.build.tags", ["ci_failed"]) + dd.set_attr("comment.build.result", "failed") + if args.owner != "openeuler": + comment.get_all_result_to_kafka(url) + + logger.info("comment: at committer......") + comment.comment_at(args.committer, gp) + + dd.set_attr_etime("comment.job.etime") + + # suppress python warning + warnings.filterwarnings("ignore") + logging.getLogger("elasticsearch").setLevel(logging.WARNING) + logging.getLogger("kafka").setLevel(logging.WARNING) + + # upload to es + kp = KafkaProducerProxy(brokers=os.environ["KAFKAURL"].split(",")) + query = {"term": {"id": args.comment_id}} + script = {"lang": "painless", "source": "ctx._source.comment = params.comment", "params": dd.to_dict()} + kp.send("openeuler_statewall_ci_ac", key=args.comment_id, value=dd.to_dict())