ClickHouse/ci/praktika/gh.py
2024-10-24 16:48:14 +02:00

106 lines
3.7 KiB
Python

import json
import time
from praktika._environment import _Environment
from praktika.result import Result
from praktika.settings import Settings
from praktika.utils import Shell
class GH:
@classmethod
def do_command_with_retries(cls, command):
res = False
retry_count = 0
out, err = "", ""
while retry_count < Settings.MAX_RETRIES_GH and not res:
ret_code, out, err = Shell.get_res_stdout_stderr(command, verbose=True)
res = ret_code == 0
if not res and "Validation Failed" in err:
print("ERROR: GH command validation error")
break
if not res and "Bad credentials" in err:
print("ERROR: GH credentials/auth failure")
break
if not res:
retry_count += 1
time.sleep(5)
if not res:
print(
f"ERROR: Failed to execute gh command [{command}] out:[{out}] err:[{err}] after [{retry_count}] attempts"
)
return res
@classmethod
def post_pr_comment(
cls, comment_body, or_update_comment_with_substring, repo=None, pr=None
):
if not repo:
repo = _Environment.get().REPOSITORY
if not pr:
pr = _Environment.get().PR_NUMBER
if or_update_comment_with_substring:
print(f"check comment [{comment_body}] created")
cmd_check_created = f'gh api -H "Accept: application/vnd.github.v3+json" \
"/repos/{repo}/issues/{pr}/comments" \
--jq \'.[] | {{id: .id, body: .body}}\' | grep -F "{or_update_comment_with_substring}"'
output = Shell.get_output(cmd_check_created)
if output:
comment_ids = []
try:
comment_ids = [
json.loads(item.strip())["id"] for item in output.split("\n")
]
except Exception as ex:
print(f"Failed to retrieve PR comments with [{ex}]")
for id in comment_ids:
cmd = f'gh api \
-X PATCH \
-H "Accept: application/vnd.github.v3+json" \
"/repos/{repo}/issues/comments/{id}" \
-f body=\'{comment_body}\''
print(f"Update existing comments [{id}]")
return cls.do_command_with_retries(cmd)
cmd = f'gh pr comment {pr} --body "{comment_body}"'
return cls.do_command_with_retries(cmd)
@classmethod
def post_commit_status(cls, name, status, description, url):
status = cls.convert_to_gh_status(status)
command = (
f"gh api -X POST -H 'Accept: application/vnd.github.v3+json' "
f"/repos/{_Environment.get().REPOSITORY}/statuses/{_Environment.get().SHA} "
f"-f state='{status}' -f target_url='{url}' "
f"-f description='{description}' -f context='{name}'"
)
return cls.do_command_with_retries(command)
@classmethod
def convert_to_gh_status(cls, status):
if status in (
Result.Status.PENDING,
Result.Status.SUCCESS,
Result.Status.FAILED,
Result.Status.ERROR,
):
return status
if status in Result.Status.RUNNING:
return Result.Status.PENDING
else:
assert (
False
), f"Invalid status [{status}] to be set as GH commit status.state"
if __name__ == "__main__":
# test
GH.post_pr_comment(
comment_body="foobar",
or_update_comment_with_substring="CI",
repo="ClickHouse/praktika",
pr=15,
)