2021-10-21 14:41:07 +00:00
|
|
|
#!/usr/bin/env python3
|
2024-06-10 09:18:03 +00:00
|
|
|
import argparse
|
2024-05-31 08:57:31 +00:00
|
|
|
import json
|
2021-10-27 07:03:23 +00:00
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
import sys
|
2023-08-29 14:35:53 +00:00
|
|
|
from pathlib import Path
|
2024-03-01 00:48:31 +00:00
|
|
|
from typing import List
|
2022-04-11 13:35:13 +00:00
|
|
|
|
2024-09-18 20:04:50 +00:00
|
|
|
from ci_config import CI
|
2022-03-22 16:39:58 +00:00
|
|
|
from env_helper import (
|
2024-09-18 20:04:50 +00:00
|
|
|
CI_CONFIG_PATH,
|
2022-03-22 16:39:58 +00:00
|
|
|
GITHUB_REPOSITORY,
|
2022-05-25 13:15:11 +00:00
|
|
|
GITHUB_SERVER_URL,
|
2024-09-18 20:04:50 +00:00
|
|
|
IS_CI,
|
2023-12-18 08:07:22 +00:00
|
|
|
REPORT_PATH,
|
2024-02-28 12:20:08 +00:00
|
|
|
TEMP_PATH,
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2024-02-28 12:20:08 +00:00
|
|
|
from pr_info import PRInfo
|
2023-09-01 20:35:31 +00:00
|
|
|
from report import (
|
|
|
|
ERROR,
|
2024-09-18 20:04:50 +00:00
|
|
|
FAILURE,
|
|
|
|
GITHUB_JOB_URL,
|
2023-09-01 20:35:31 +00:00
|
|
|
PENDING,
|
|
|
|
SUCCESS,
|
2024-02-28 12:20:08 +00:00
|
|
|
BuildResult,
|
2024-01-04 15:35:09 +00:00
|
|
|
JobReport,
|
2023-09-01 20:35:31 +00:00
|
|
|
create_build_html_report,
|
2024-06-14 16:45:08 +00:00
|
|
|
get_worst_status,
|
2023-09-01 20:35:31 +00:00
|
|
|
)
|
2024-01-04 15:35:09 +00:00
|
|
|
from stopwatch import Stopwatch
|
2021-10-21 14:41:07 +00:00
|
|
|
|
2023-11-12 09:12:04 +00:00
|
|
|
# Old way to read the neads_data
|
2022-11-15 12:01:27 +00:00
|
|
|
NEEDS_DATA_PATH = os.getenv("NEEDS_DATA_PATH", "")
|
2023-11-12 09:12:04 +00:00
|
|
|
# Now it's set here. Two-steps migration for backward compatibility
|
|
|
|
NEEDS_DATA = os.getenv("NEEDS_DATA", "")
|
2022-05-25 13:15:11 +00:00
|
|
|
|
|
|
|
|
2022-04-11 13:36:18 +00:00
|
|
|
def main():
|
2021-10-21 14:41:07 +00:00
|
|
|
logging.basicConfig(level=logging.INFO)
|
2024-01-04 15:35:09 +00:00
|
|
|
stopwatch = Stopwatch()
|
2023-08-29 14:35:53 +00:00
|
|
|
temp_path = Path(TEMP_PATH)
|
2023-12-18 08:07:22 +00:00
|
|
|
reports_path = Path(REPORT_PATH)
|
2023-08-29 14:35:53 +00:00
|
|
|
temp_path.mkdir(parents=True, exist_ok=True)
|
2021-10-21 15:32:15 +00:00
|
|
|
|
2023-09-01 20:35:31 +00:00
|
|
|
logging.info(
|
|
|
|
"Reports found:\n %s",
|
|
|
|
"\n ".join(p.as_posix() for p in reports_path.rglob("*.json")),
|
|
|
|
)
|
|
|
|
|
2024-06-10 09:18:03 +00:00
|
|
|
build_check_name = CI.JobNames.BUILD_CHECK
|
2022-06-28 08:27:25 +00:00
|
|
|
|
2021-11-26 14:00:09 +00:00
|
|
|
pr_info = PRInfo()
|
2021-12-01 14:23:51 +00:00
|
|
|
|
2024-06-10 09:18:03 +00:00
|
|
|
args = parse_args()
|
|
|
|
|
|
|
|
if (CI_CONFIG_PATH or IS_CI) and not args.reports:
|
2024-05-31 08:57:31 +00:00
|
|
|
# In CI only specific builds might be manually selected, or some wf does not build all builds.
|
|
|
|
# Filtering @builds_for_check to verify only builds that are present in the current CI workflow
|
|
|
|
with open(CI_CONFIG_PATH, encoding="utf-8") as jfd:
|
|
|
|
ci_config = json.load(jfd)
|
|
|
|
all_ci_jobs = (
|
|
|
|
ci_config["jobs_data"]["jobs_to_skip"]
|
|
|
|
+ ci_config["jobs_data"]["jobs_to_do"]
|
|
|
|
)
|
2024-06-10 09:18:03 +00:00
|
|
|
builds_for_check = [job for job in CI.BuildNames if job in all_ci_jobs]
|
2024-06-25 11:11:04 +00:00
|
|
|
print("NOTE: builds for check taken from ci configuration")
|
2024-06-10 09:18:03 +00:00
|
|
|
else:
|
|
|
|
builds_for_check = parse_args().reports
|
|
|
|
for job in builds_for_check:
|
|
|
|
assert job in CI.BuildNames, "Builds must be known build job names"
|
2024-06-25 11:11:04 +00:00
|
|
|
print("NOTE: builds for check taken from input arguments")
|
|
|
|
|
|
|
|
print(f"NOTE: following build reports will be checked: [{builds_for_check}]")
|
2024-05-31 08:57:31 +00:00
|
|
|
|
2024-03-01 00:48:31 +00:00
|
|
|
required_builds = len(builds_for_check)
|
|
|
|
missing_builds = 0
|
2021-11-30 15:33:29 +00:00
|
|
|
|
2022-04-11 13:36:18 +00:00
|
|
|
# Collect reports from json artifacts
|
2024-03-01 00:48:31 +00:00
|
|
|
build_results = [] # type: List[BuildResult]
|
2023-09-01 20:35:31 +00:00
|
|
|
for build_name in builds_for_check:
|
2024-01-04 15:35:09 +00:00
|
|
|
build_result = BuildResult.load_any(
|
|
|
|
build_name, pr_info.number, pr_info.head_ref
|
|
|
|
)
|
|
|
|
if not build_result:
|
2024-06-10 09:18:03 +00:00
|
|
|
if build_name == CI.BuildNames.FUZZERS:
|
|
|
|
logging.info("Build [%s] is missing - skip", CI.BuildNames.FUZZERS)
|
2024-03-01 00:48:31 +00:00
|
|
|
continue
|
|
|
|
logging.warning("Build results for %s is missing", build_name)
|
|
|
|
build_result = BuildResult.missing_result("missing")
|
|
|
|
build_result.job_name = build_name
|
|
|
|
build_result.status = PENDING
|
|
|
|
logging.info(
|
|
|
|
"There is missing report for %s, created a dummy result %s",
|
|
|
|
build_name,
|
|
|
|
build_result,
|
|
|
|
)
|
|
|
|
missing_builds += 1
|
|
|
|
build_results.insert(0, build_result)
|
|
|
|
else:
|
|
|
|
assert (
|
|
|
|
pr_info.head_ref == build_result.head_ref or pr_info.number > 0
|
|
|
|
), "BUG. if not a PR, report must be created on the same branch"
|
|
|
|
build_results.append(build_result)
|
2022-05-25 13:15:11 +00:00
|
|
|
|
2023-09-01 20:35:31 +00:00
|
|
|
# Calculate artifact groups like packages and binaries
|
|
|
|
total_groups = sum(len(br.grouped_urls) for br in build_results)
|
|
|
|
ok_groups = sum(
|
|
|
|
len(br.grouped_urls) for br in build_results if br.status == SUCCESS
|
|
|
|
)
|
2022-04-11 13:36:18 +00:00
|
|
|
logging.info("Totally got %s artifact groups", total_groups)
|
|
|
|
if total_groups == 0:
|
2023-09-01 20:35:31 +00:00
|
|
|
logging.error("No success builds, failing check without creating a status")
|
2021-12-09 09:17:03 +00:00
|
|
|
sys.exit(1)
|
2021-10-21 14:41:07 +00:00
|
|
|
|
2021-11-26 14:00:09 +00:00
|
|
|
branch_url = f"{GITHUB_SERVER_URL}/{GITHUB_REPOSITORY}/commits/master"
|
2021-10-21 14:41:07 +00:00
|
|
|
branch_name = "master"
|
|
|
|
if pr_info.number != 0:
|
2022-04-06 12:34:20 +00:00
|
|
|
branch_name = f"PR #{pr_info.number}"
|
2021-11-26 14:00:09 +00:00
|
|
|
branch_url = f"{GITHUB_SERVER_URL}/{GITHUB_REPOSITORY}/pull/{pr_info.number}"
|
|
|
|
commit_url = f"{GITHUB_SERVER_URL}/{GITHUB_REPOSITORY}/commit/{pr_info.sha}"
|
2023-01-04 11:18:53 +00:00
|
|
|
task_url = GITHUB_JOB_URL()
|
2021-10-21 14:41:07 +00:00
|
|
|
report = create_build_html_report(
|
|
|
|
build_check_name,
|
|
|
|
build_results,
|
|
|
|
task_url,
|
|
|
|
branch_url,
|
|
|
|
branch_name,
|
2022-03-22 16:39:58 +00:00
|
|
|
commit_url,
|
2021-10-21 14:41:07 +00:00
|
|
|
)
|
|
|
|
|
2023-08-29 14:35:53 +00:00
|
|
|
report_path = temp_path / "report.html"
|
|
|
|
report_path.write_text(report, encoding="utf-8")
|
2021-10-21 14:41:07 +00:00
|
|
|
|
2022-04-11 13:36:18 +00:00
|
|
|
# Prepare a commit status
|
2023-09-01 20:35:31 +00:00
|
|
|
summary_status = get_worst_status(br.status for br in build_results)
|
2021-10-21 14:41:07 +00:00
|
|
|
|
2023-06-01 06:51:44 +00:00
|
|
|
# Check if there are no builds at all, do not override bad status
|
2023-09-01 20:35:31 +00:00
|
|
|
if summary_status == SUCCESS:
|
|
|
|
if missing_builds:
|
2024-06-14 16:42:37 +00:00
|
|
|
summary_status = FAILURE
|
2023-06-01 06:51:44 +00:00
|
|
|
elif ok_groups == 0:
|
2023-09-01 20:35:31 +00:00
|
|
|
summary_status = ERROR
|
2021-11-30 15:33:29 +00:00
|
|
|
|
2024-06-14 16:42:37 +00:00
|
|
|
description = ""
|
|
|
|
|
2023-09-01 20:35:31 +00:00
|
|
|
if missing_builds:
|
2024-06-14 16:42:37 +00:00
|
|
|
description = f"{missing_builds} of {required_builds} builds are missing."
|
2022-03-30 09:15:54 +00:00
|
|
|
|
2024-06-14 16:42:37 +00:00
|
|
|
description += f" {ok_groups}/{total_groups} artifact groups are OK"
|
2021-10-21 14:41:07 +00:00
|
|
|
|
2024-01-04 15:35:09 +00:00
|
|
|
JobReport(
|
|
|
|
description=description,
|
|
|
|
test_results=[],
|
|
|
|
status=summary_status,
|
|
|
|
start_time=stopwatch.start_time_str,
|
|
|
|
duration=stopwatch.duration_seconds,
|
|
|
|
additional_files=[report_path],
|
|
|
|
).dump()
|
2022-03-29 12:41:47 +00:00
|
|
|
|
2024-04-19 12:27:10 +00:00
|
|
|
# We should fail the report job to rerun it in the following attempts
|
|
|
|
if summary_status != SUCCESS:
|
2022-03-29 12:41:47 +00:00
|
|
|
sys.exit(1)
|
2022-04-11 13:36:18 +00:00
|
|
|
|
|
|
|
|
2024-06-10 09:18:03 +00:00
|
|
|
def parse_args():
|
|
|
|
parser = argparse.ArgumentParser("Generates overall build report")
|
|
|
|
|
|
|
|
parser.add_argument(
|
|
|
|
"--reports",
|
|
|
|
nargs="+",
|
|
|
|
help="List of build reports to check",
|
|
|
|
)
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
|
|
|
2022-04-11 13:36:18 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|