diff --git a/.gitmessage b/.gitmessage new file mode 100644 index 00000000000..f4a25a837bc --- /dev/null +++ b/.gitmessage @@ -0,0 +1,10 @@ + + +## To avoid merge commit in CI run (add a leading space to apply): +#no-merge-commit + +## Running specified job (add a leading space to apply): +#job_ +#job_stateless_tests_release +#job_package_debug +#job_integration_tests_asan diff --git a/tests/ci/build_report_check.py b/tests/ci/build_report_check.py index 755217f89b5..d9925725eec 100644 --- a/tests/ci/build_report_check.py +++ b/tests/ci/build_report_check.py @@ -78,7 +78,7 @@ def main(): pr_info = PRInfo() commit = get_commit(gh, pr_info.sha) - atexit.register(update_mergeable_check, gh, pr_info, build_check_name) + atexit.register(update_mergeable_check, commit, pr_info, build_check_name) rerun_helper = RerunHelper(commit, build_check_name) if rerun_helper.is_already_finished_by_status(): diff --git a/tests/ci/ci_config.py b/tests/ci/ci_config.py index 8bf9c62a17b..d28e008ef50 100644 --- a/tests/ci/ci_config.py +++ b/tests/ci/ci_config.py @@ -847,6 +847,7 @@ CI_CONFIG.validate() # checks required by Mergeable Check REQUIRED_CHECKS = [ + "PR Check", "ClickHouse build check", "ClickHouse special build check", "Docs Check", diff --git a/tests/ci/clickbench.py b/tests/ci/clickbench.py index 26a826a19ad..f9fadae4e03 100644 --- a/tests/ci/clickbench.py +++ b/tests/ci/clickbench.py @@ -133,7 +133,7 @@ def main(): pr_info = PRInfo() commit = get_commit(gh, pr_info.sha) - atexit.register(update_mergeable_check, gh, pr_info, check_name) + atexit.register(update_mergeable_check, commit, pr_info, check_name) rerun_helper = RerunHelper(commit, check_name) if rerun_helper.is_already_finished_by_status(): diff --git a/tests/ci/commit_status_helper.py b/tests/ci/commit_status_helper.py index 2eac974858c..598eef9922e 100644 --- a/tests/ci/commit_status_helper.py +++ b/tests/ci/commit_status_helper.py @@ -15,11 +15,10 @@ from github.CommitStatus import CommitStatus from github.GithubException import GithubException from github.GithubObject import NotSet from github.IssueComment import IssueComment -from github.PullRequest import PullRequest from github.Repository import Repository from ci_config import CI_CONFIG, REQUIRED_CHECKS, CHECK_DESCRIPTIONS, CheckDescription -from env_helper import GITHUB_REPOSITORY, GITHUB_RUN_URL, TEMP_PATH +from env_helper import GITHUB_JOB_URL, GITHUB_REPOSITORY, TEMP_PATH from pr_info import PRInfo, SKIP_MERGEABLE_CHECK_LABEL from report import ( ERROR, @@ -437,11 +436,11 @@ def set_mergeable_check( context=MERGEABLE_NAME, description=description, state=state, - target_url=GITHUB_RUN_URL, + target_url=GITHUB_JOB_URL(), ) -def update_mergeable_check(gh: Github, pr_info: PRInfo, check_name: str) -> None: +def update_mergeable_check(commit: Commit, pr_info: PRInfo, check_name: str) -> None: not_run = ( pr_info.labels.intersection({SKIP_MERGEABLE_CHECK_LABEL, "release"}) or check_name not in REQUIRED_CHECKS @@ -454,7 +453,6 @@ def update_mergeable_check(gh: Github, pr_info: PRInfo, check_name: str) -> None logging.info("Update Mergeable Check by %s", check_name) - commit = get_commit(gh, pr_info.sha) statuses = get_commit_filtered_statuses(commit) required_checks = [ @@ -475,14 +473,17 @@ def update_mergeable_check(gh: Github, pr_info: PRInfo, check_name: str) -> None else: fail.append(status.context) + state: StatusType = SUCCESS + + if success: + description = ", ".join(success) + else: + description = "awaiting job statuses" + if fail: description = "failed: " + ", ".join(fail) - description = format_description(description) - if mergeable_status is None or mergeable_status.description != description: - set_mergeable_check(commit, description, FAILURE) - return - - description = ", ".join(success) + state = FAILURE description = format_description(description) + if mergeable_status is None or mergeable_status.description != description: - set_mergeable_check(commit, description) + set_mergeable_check(commit, description, state) diff --git a/tests/ci/docs_check.py b/tests/ci/docs_check.py index 6f68918e63c..1424ab8895d 100644 --- a/tests/ci/docs_check.py +++ b/tests/ci/docs_check.py @@ -67,7 +67,7 @@ def main(): if rerun_helper.is_already_finished_by_status(): logging.info("Check is already finished according to github status, exiting") sys.exit(0) - atexit.register(update_mergeable_check, gh, pr_info, NAME) + atexit.register(update_mergeable_check, commit, pr_info, NAME) if not pr_info.has_changes_in_documentation() and not args.force: logging.info("No changes in documentation") diff --git a/tests/ci/fast_test_check.py b/tests/ci/fast_test_check.py index 1ce6ab617ec..093537fdeb0 100644 --- a/tests/ci/fast_test_check.py +++ b/tests/ci/fast_test_check.py @@ -124,7 +124,7 @@ def main(): gh = Github(get_best_robot_token(), per_page=100) commit = get_commit(gh, pr_info.sha) - atexit.register(update_mergeable_check, gh, pr_info, NAME) + atexit.register(update_mergeable_check, commit, pr_info, NAME) rerun_helper = RerunHelper(commit, NAME) if rerun_helper.is_already_finished_by_status(): diff --git a/tests/ci/finish_check.py b/tests/ci/finish_check.py index 92d2fddef0f..6c615817164 100644 --- a/tests/ci/finish_check.py +++ b/tests/ci/finish_check.py @@ -18,9 +18,9 @@ def main(): pr_info = PRInfo(need_orgs=True) gh = Github(get_best_robot_token(), per_page=100) - # Update the Mergeable Check at the final step - update_mergeable_check(gh, pr_info, CI_STATUS_NAME) commit = get_commit(gh, pr_info.sha) + # Update the Mergeable Check at the final step + update_mergeable_check(commit, pr_info, CI_STATUS_NAME) statuses = [ status diff --git a/tests/ci/functional_test_check.py b/tests/ci/functional_test_check.py index c7ae91d88b2..4d81161b6de 100644 --- a/tests/ci/functional_test_check.py +++ b/tests/ci/functional_test_check.py @@ -254,7 +254,7 @@ def main(): ) commit = get_commit(gh, pr_info.sha) - atexit.register(update_mergeable_check, gh, pr_info, check_name) + atexit.register(update_mergeable_check, commit, pr_info, check_name) if validate_bugfix_check and "pr-bugfix" not in pr_info.labels: if args.post_commit_status == "file": diff --git a/tests/ci/install_check.py b/tests/ci/install_check.py index b8cfa0acd3d..5ef65f3f38b 100644 --- a/tests/ci/install_check.py +++ b/tests/ci/install_check.py @@ -279,7 +279,7 @@ def main(): if CI: gh = Github(get_best_robot_token(), per_page=100) commit = get_commit(gh, pr_info.sha) - atexit.register(update_mergeable_check, gh, pr_info, args.check_name) + atexit.register(update_mergeable_check, commit, pr_info, args.check_name) rerun_helper = RerunHelper(commit, args.check_name) if rerun_helper.is_already_finished_by_status(): diff --git a/tests/ci/libfuzzer_test_check.py b/tests/ci/libfuzzer_test_check.py index 58e78d571c5..6de0614541a 100644 --- a/tests/ci/libfuzzer_test_check.py +++ b/tests/ci/libfuzzer_test_check.py @@ -118,7 +118,7 @@ def main(): gh = Github(get_best_robot_token(), per_page=100) pr_info = PRInfo() commit = get_commit(gh, pr_info.sha) - atexit.register(update_mergeable_check, gh, pr_info, check_name) + atexit.register(update_mergeable_check, commit, pr_info, check_name) temp_path.mkdir(parents=True, exist_ok=True) diff --git a/tests/ci/run_check.py b/tests/ci/run_check.py index d1949a4da0b..fb56a65fe0b 100644 --- a/tests/ci/run_check.py +++ b/tests/ci/run_check.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +import atexit import sys import logging from typing import Tuple @@ -13,9 +14,8 @@ from commit_status_helper import ( post_commit_status, post_labels, remove_labels, - set_mergeable_check, + update_mergeable_check, ) -from docs_check import NAME as DOCS_NAME from env_helper import GITHUB_REPOSITORY, GITHUB_SERVER_URL from get_robot_token import get_best_robot_token from pr_info import FORCE_TESTS_LABEL, PRInfo @@ -24,6 +24,7 @@ from lambda_shared_package.lambda_shared.pr import ( TRUSTED_CONTRIBUTORS, check_pr_description, ) +from report import FAILURE TRUSTED_ORG_IDS = { 54801242, # clickhouse @@ -34,6 +35,7 @@ CAN_BE_TESTED_LABEL = "can be tested" DO_NOT_TEST_LABEL = "do not test" FEATURE_LABEL = "pr-feature" SUBMODULE_CHANGED_LABEL = "submodule changed" +PR_CHECK = "PR Check" def pr_is_by_trusted_user(pr_user_login, pr_user_orgs): @@ -58,24 +60,20 @@ def pr_is_by_trusted_user(pr_user_login, pr_user_orgs): # Returns whether we should look into individual checks for this PR. If not, it # can be skipped entirely. -# Returns can_run, description, labels_state -def should_run_ci_for_pr(pr_info: PRInfo) -> Tuple[bool, str, str]: +# Returns can_run, description +def should_run_ci_for_pr(pr_info: PRInfo) -> Tuple[bool, str]: # Consider the labels and whether the user is trusted. print("Got labels", pr_info.labels) if FORCE_TESTS_LABEL in pr_info.labels: print(f"Label '{FORCE_TESTS_LABEL}' set, forcing remaining checks") - return True, f"Labeled '{FORCE_TESTS_LABEL}'", "pending" + return True, f"Labeled '{FORCE_TESTS_LABEL}'" if DO_NOT_TEST_LABEL in pr_info.labels: print(f"Label '{DO_NOT_TEST_LABEL}' set, skipping remaining checks") - return False, f"Labeled '{DO_NOT_TEST_LABEL}'", "success" + return False, f"Labeled '{DO_NOT_TEST_LABEL}'" if OK_SKIP_LABELS.intersection(pr_info.labels): - return ( - True, - "Don't try new checks for release/backports/cherry-picks", - "success", - ) + return True, "Don't try new checks for release/backports/cherry-picks" if CAN_BE_TESTED_LABEL not in pr_info.labels and not pr_is_by_trusted_user( pr_info.user_login, pr_info.user_orgs @@ -83,9 +81,9 @@ def should_run_ci_for_pr(pr_info: PRInfo) -> Tuple[bool, str, str]: print( f"PRs by untrusted users need the '{CAN_BE_TESTED_LABEL}' label - please contact a member of the core team" ) - return False, "Needs 'can be tested' label", "failure" + return False, "Needs 'can be tested' label" - return True, "No special conditions apply", "pending" + return True, "No special conditions apply" def main(): @@ -98,7 +96,7 @@ def main(): print("::notice ::Cannot run, no PR exists for the commit") sys.exit(1) - can_run, description, labels_state = should_run_ci_for_pr(pr_info) + 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) @@ -106,6 +104,7 @@ def main(): description = format_description(description) gh = Github(get_best_robot_token(), per_page=100) commit = get_commit(gh, pr_info.sha) + atexit.register(update_mergeable_check, commit, pr_info, PR_CHECK) description_error, category = check_pr_description(pr_info.body, GITHUB_REPOSITORY) pr_labels_to_add = [] @@ -136,22 +135,6 @@ def main(): if pr_labels_to_remove: remove_labels(gh, pr_info, pr_labels_to_remove) - # FIXME: it should rather be in finish check. no reason to stop ci run. - if FEATURE_LABEL in pr_info.labels and not pr_info.has_changes_in_documentation(): - print( - f"The '{FEATURE_LABEL}' in the labels, " - "but there's no changed documentation" - ) - post_commit_status( # do not pass pr_info here intentionally - commit, - "failure", - "", - f"expect adding docs for {FEATURE_LABEL}", - DOCS_NAME, - pr_info, - ) - sys.exit(0) - if description_error: print( "::error ::Cannot run, PR description does not match the template: " @@ -171,34 +154,40 @@ def main(): "failure", url, format_description(description_error), - CI_STATUS_NAME, + PR_CHECK, pr_info, ) sys.exit(1) - set_mergeable_check(commit, "skipped") - ci_report_url = create_ci_report(pr_info, []) + if FEATURE_LABEL in pr_info.labels and not pr_info.has_changes_in_documentation(): + print( + f"The '{FEATURE_LABEL}' in the labels, " + "but there's no changed documentation" + ) + post_commit_status( + commit, + FAILURE, + "", + f"expect adding docs for {FEATURE_LABEL}", + PR_CHECK, + pr_info, + ) + # allow the workflow to continue + if not can_run: print("::notice ::Cannot run") - post_commit_status( - commit, - labels_state, - ci_report_url, - description, - CI_STATUS_NAME, - pr_info, - ) sys.exit(1) - else: - print("::notice ::Can run") - post_commit_status( - commit, - "pending", - ci_report_url, - description, - CI_STATUS_NAME, - pr_info, - ) + + ci_report_url = create_ci_report(pr_info, []) + print("::notice ::Can run") + post_commit_status( + commit, + "pending", + ci_report_url, + description, + CI_STATUS_NAME, + pr_info, + ) if __name__ == "__main__": diff --git a/tests/ci/style_check.py b/tests/ci/style_check.py index a5498fac393..b37dcb59237 100644 --- a/tests/ci/style_check.py +++ b/tests/ci/style_check.py @@ -145,7 +145,7 @@ def main(): gh = GitHub(get_best_robot_token(), create_cache_dir=False) commit = get_commit(gh, pr_info.sha) - atexit.register(update_mergeable_check, gh, pr_info, NAME) + atexit.register(update_mergeable_check, commit, pr_info, NAME) rerun_helper = RerunHelper(commit, NAME) if rerun_helper.is_already_finished_by_status(): diff --git a/tests/ci/unit_tests_check.py b/tests/ci/unit_tests_check.py index d6767cf8b7f..f1238a00bd4 100644 --- a/tests/ci/unit_tests_check.py +++ b/tests/ci/unit_tests_check.py @@ -187,7 +187,7 @@ def main(): gh = Github(get_best_robot_token(), per_page=100) commit = get_commit(gh, pr_info.sha) - atexit.register(update_mergeable_check, gh, pr_info, check_name) + atexit.register(update_mergeable_check, commit, pr_info, check_name) rerun_helper = RerunHelper(commit, check_name) if rerun_helper.is_already_finished_by_status():