2024-10-01 19:19:35 +00:00
|
|
|
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:
|
2024-11-15 12:49:28 +00:00
|
|
|
print(f"ERROR: GH command validation error.")
|
2024-10-01 19:19:35 +00:00
|
|
|
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,
|
|
|
|
)
|