ClickHouse/tests/ci/run_check.py

215 lines
6.2 KiB
Python
Raw Normal View History

2021-09-15 12:59:39 +00:00
#!/usr/bin/env python3
2021-09-15 13:04:29 +00:00
import logging
import sys
from typing import Tuple
2021-11-26 14:00:09 +00:00
from github import Github
from ci_config import StatusNames
from commit_status_helper import (
create_ci_report,
format_description,
get_commit,
post_commit_status,
post_labels,
remove_labels,
)
from env_helper import GITHUB_REPOSITORY, GITHUB_SERVER_URL
from get_robot_token import get_best_robot_token
from lambda_shared_package.lambda_shared.pr import (
CATEGORY_TO_LABEL,
TRUSTED_CONTRIBUTORS,
Labels,
check_pr_description,
)
from pr_info import PRInfo
from report import FAILURE, PENDING, SUCCESS
2021-09-15 12:59:39 +00:00
TRUSTED_ORG_IDS = {
54801242, # clickhouse
}
OK_SKIP_LABELS = {Labels.RELEASE, Labels.PR_BACKPORT, Labels.PR_CHERRYPICK}
PR_CHECK = "PR Check"
2021-09-15 12:59:39 +00:00
def pr_is_by_trusted_user(pr_user_login, pr_user_orgs):
if pr_user_login.lower() in TRUSTED_CONTRIBUTORS:
logging.info("User '%s' is trusted", pr_user_login)
2021-09-15 12:59:39 +00:00
return True
logging.info("User '%s' is not trusted", pr_user_login)
2021-09-15 12:59:39 +00:00
for org_id in pr_user_orgs:
if org_id in TRUSTED_ORG_IDS:
2022-01-13 11:06:50 +00:00
logging.info(
"Org '%s' is trusted; will mark user %s as trusted",
org_id,
pr_user_login,
)
2021-09-15 12:59:39 +00:00
return True
logging.info("Org '%s' is not trusted", org_id)
2021-09-15 12:59:39 +00:00
return False
2022-01-13 11:06:50 +00:00
2021-09-15 12:59:39 +00:00
# Returns whether we should look into individual checks for this PR. If not, it
# can be skipped entirely.
# Returns can_run, description
def should_run_ci_for_pr(pr_info: PRInfo) -> Tuple[bool, str]:
2021-09-15 12:59:39 +00:00
# Consider the labels and whether the user is trusted.
2021-12-22 08:13:04 +00:00
print("Got labels", pr_info.labels)
2021-09-15 12:59:39 +00:00
if OK_SKIP_LABELS.intersection(pr_info.labels):
return True, "Don't try new checks for release/backports/cherry-picks"
if Labels.CAN_BE_TESTED not in pr_info.labels and not pr_is_by_trusted_user(
2022-01-13 11:06:50 +00:00
pr_info.user_login, pr_info.user_orgs
):
2022-09-07 08:51:02 +00:00
print(
f"PRs by untrusted users need the '{Labels.CAN_BE_TESTED}' label - "
"please contact a member of the core team"
2022-09-07 08:51:02 +00:00
)
return False, "Needs 'can be tested' label"
2021-09-15 12:59:39 +00:00
return True, "No special conditions apply"
2021-09-15 12:59:39 +00:00
2021-11-26 14:00:09 +00:00
2023-04-06 09:03:32 +00:00
def main():
2021-09-15 12:59:39 +00:00
logging.basicConfig(level=logging.INFO)
2022-03-29 17:28:18 +00:00
pr_info = PRInfo(need_orgs=True, pr_event_from_api=True, need_changed_files=True)
# The case for special branches like backports and releases without created
# PRs, like merged backport branches that are reset immediately after merge
if pr_info.number == 0:
print("::notice ::Cannot run, no PR exists for the commit")
sys.exit(1)
can_run, description = should_run_ci_for_pr(pr_info)
if can_run and OK_SKIP_LABELS.intersection(pr_info.labels):
print("::notice :: Early finish the check, running in a special PR")
sys.exit(0)
2023-02-27 12:11:17 +00:00
description = format_description(description)
gh = Github(get_best_robot_token(), per_page=100)
commit = get_commit(gh, pr_info.sha)
2022-01-13 11:08:31 +00:00
description_error, category = check_pr_description(pr_info.body, GITHUB_REPOSITORY)
2022-03-30 08:58:34 +00:00
pr_labels_to_add = []
pr_labels_to_remove = []
2022-03-29 17:50:06 +00:00
if (
2022-04-19 12:47:18 +00:00
category in CATEGORY_TO_LABEL
and CATEGORY_TO_LABEL[category] not in pr_info.labels
2022-03-29 17:50:06 +00:00
):
2022-04-19 12:47:18 +00:00
pr_labels_to_add.append(CATEGORY_TO_LABEL[category])
2022-03-30 08:58:34 +00:00
for label in pr_info.labels:
2022-03-30 09:19:11 +00:00
if (
2022-04-19 12:47:18 +00:00
label in CATEGORY_TO_LABEL.values()
and category in CATEGORY_TO_LABEL
and label != CATEGORY_TO_LABEL[category]
2022-03-30 09:19:11 +00:00
):
2022-03-30 08:58:34 +00:00
pr_labels_to_remove.append(label)
2022-03-29 13:48:57 +00:00
2022-03-29 17:28:18 +00:00
if pr_info.has_changes_in_submodules():
pr_labels_to_add.append(Labels.SUBMODULE_CHANGED)
elif Labels.SUBMODULE_CHANGED in pr_info.labels:
pr_labels_to_remove.append(Labels.SUBMODULE_CHANGED)
2022-03-30 08:58:34 +00:00
if any(label in Labels.AUTO_BACKPORT for label in pr_labels_to_add):
backport_labels = [Labels.MUST_BACKPORT, Labels.MUST_BACKPORT_CLOUD]
pr_labels_to_add += [
label for label in backport_labels if label not in pr_info.labels
]
print(
f"::notice :: Add backport labels [{backport_labels}] for a given PR category"
)
print(f"Change labels: add {pr_labels_to_add}, remove {pr_labels_to_remove}")
2022-03-30 08:58:34 +00:00
if pr_labels_to_add:
post_labels(gh, pr_info, pr_labels_to_add)
if pr_labels_to_remove:
remove_labels(gh, pr_info, pr_labels_to_remove)
2022-03-29 17:28:18 +00:00
2022-04-19 12:47:18 +00:00
if description_error:
2022-04-04 23:06:46 +00:00
print(
"::error ::Cannot run, PR description does not match the template: "
2022-04-19 12:47:18 +00:00
f"{description_error}"
2022-04-04 23:06:46 +00:00
)
2022-01-26 12:23:20 +00:00
logging.info(
2023-04-20 11:55:33 +00:00
"PR body doesn't match the template: (start)\n%s\n(end)\nReason: %s",
2022-04-04 23:06:46 +00:00
pr_info.body,
2022-04-19 12:47:18 +00:00
description_error,
2022-01-26 12:23:20 +00:00
)
2022-01-13 11:08:31 +00:00
url = (
f"{GITHUB_SERVER_URL}/{GITHUB_REPOSITORY}/"
"blob/master/.github/PULL_REQUEST_TEMPLATE.md?plain=1"
)
post_commit_status(
2023-04-20 11:55:33 +00:00
commit,
FAILURE,
2023-04-20 11:55:33 +00:00
url,
format_description(description_error),
PR_CHECK,
2023-04-20 11:55:33 +00:00
pr_info,
2022-01-13 11:08:31 +00:00
)
sys.exit(1)
if (
Labels.PR_FEATURE in pr_info.labels
and not pr_info.has_changes_in_documentation()
):
print(
f"The '{Labels.PR_FEATURE}' in the labels, "
"but there's no changed documentation"
2023-04-20 11:55:33 +00:00
)
post_commit_status(
commit,
FAILURE,
"",
f"expect adding docs for {Labels.PR_FEATURE}",
PR_CHECK,
pr_info,
)
# allow the workflow to continue
if not can_run:
post_commit_status(
commit,
FAILURE,
"",
description,
PR_CHECK,
pr_info,
)
print("::notice ::Cannot run")
sys.exit(1)
2024-02-28 12:37:07 +00:00
post_commit_status(
commit,
SUCCESS,
"",
"ok",
PR_CHECK,
pr_info,
)
ci_report_url = create_ci_report(pr_info, [])
print("::notice ::Can run")
2024-04-08 16:09:47 +00:00
2024-04-17 20:23:41 +00:00
if not pr_info.is_merge_queue:
2024-04-08 16:09:47 +00:00
# we need clean CI status for MQ to merge (no pending statuses)
post_commit_status(
commit,
PENDING,
ci_report_url,
description,
StatusNames.CI,
2024-04-08 16:09:47 +00:00
pr_info,
)
2023-04-06 09:03:32 +00:00
if __name__ == "__main__":
main()