44"""Script for getting explanations from the premerge advisor."""
55
66import argparse
7- import os
87import platform
98import sys
9+ import json
1010
1111import requests
12+ import github
13+ import github .PullRequest
1214
1315import generate_test_report_lib
1416
1517PREMERGE_ADVISOR_URL = (
1618 "http://premerge-advisor.premerge-advisor.svc.cluster.local:5000/explain"
1719)
20+ COMMENT_TAG = "<!--PREMERGE ADVISOR COMMENT: {platform}-->"
1821
1922
20- def main (commit_sha : str , build_log_files : list [str ]):
23+ def get_comment_id (platform : str , pr : github .PullRequest .PullRequest ) -> int | None :
24+ platform_comment_tag = COMMENT_TAG .format (platform = platform )
25+ for comment in pr .as_issue ().get_comments ():
26+ if platform_comment_tag in comment .body :
27+ return comment .id
28+ return None
29+
30+
31+ def get_comment (
32+ github_token : str ,
33+ pr_number : int ,
34+ body : str ,
35+ ) -> dict [str , str ]:
36+ repo = github .Github (github_token ).get_repo ("llvm/llvm-project" )
37+ pr = repo .get_issue (pr_number ).as_pull_request ()
38+ comment = {"body" : body }
39+ comment_id = get_comment_id (platform .system (), pr )
40+ if comment_id :
41+ comment ["id" ] = comment_id
42+
43+
44+ def main (
45+ commit_sha : str ,
46+ build_log_files : list [str ],
47+ github_token : str ,
48+ pr_number : int ,
49+ return_code : int ,
50+ ):
51+ """The main entrypoint for the script.
52+
53+ This function parses failures from files, requests information from the
54+ premerge advisor, and may write a Github comment depending upon the output.
55+ There are four different scenarios:
56+ 1. There has never been a previous failure and the job passes - We do not
57+ create a comment. We write out an empty file to the comment path so the
58+ issue-write workflow knows not to create anything.
59+ 2. There has never been a previous failure and the job fails - We create a
60+ new comment containing the failure information and any possible premerge
61+ advisor findings.
62+ 3. There has been a previous failure and the job passes - We update the
63+ existing comment by passing its ID and a passed message to the
64+ issue-write workflow.
65+ 4. There has been a previous failure and the job fails - We update the
66+ existing comment in the same manner as above, but generate the comment
67+ as if we have a failure.
68+
69+ Args:
70+ commit_sha: The base commit SHA for this PR run.
71+ build_log_files: The list of JUnit XML files and ninja logs.
72+ github_token: The token to use to access the Github API.
73+ pr_number: The number of the PR associated with this run.
74+ return_code: The numerical return code of ninja/CMake.
75+ """
76+ if return_code == 0 :
77+ with open ("comment" , "w" ) as comment_file_handle :
78+ comment = get_comment (
79+ ":white_check_mark: With the latest revision this PR passed "
80+ "the premerge checks."
81+ )
82+ if comment ["id" ]:
83+ json .dump ([comment ], comment_file_handle )
2184 junit_objects , ninja_logs = generate_test_report_lib .load_info_from_files (
2285 build_log_files
2386 )
@@ -45,13 +108,31 @@ def main(commit_sha: str, build_log_files: list[str]):
45108 )
46109 if advisor_response .status_code == 200 :
47110 print (advisor_response .json ())
111+ comments = [
112+ get_comment (
113+ github_token ,
114+ pr_number ,
115+ generate_test_report_lib .generate_report (
116+ generate_test_report_lib .compute_platform_title (),
117+ return_code ,
118+ junit_objects ,
119+ ninja_logs ,
120+ failure_explanations_list = advisor_response .json (),
121+ ),
122+ )
123+ ]
124+ with open ("comment" , "w" ) as comment_file_handle :
125+ json .dump (comments , comment_file_handle )
48126 else :
49127 print (advisor_response .reason )
50128
51129
52130if __name__ == "__main__" :
53131 parser = argparse .ArgumentParser ()
54132 parser .add_argument ("commit_sha" , help = "The base commit SHA for the test." )
133+ parser .add_argument ("return_code" , help = "The build's return code" , type = int )
134+ parser .add_argument ("github_token" , help = "Github authentication token" , type = str )
135+ parser .add_argument ("pr_number" , help = "The PR number" , type = int )
55136 parser .add_argument (
56137 "build_log_files" , help = "Paths to JUnit report files and ninja logs." , nargs = "*"
57138 )
@@ -62,4 +143,10 @@ def main(commit_sha: str, build_log_files: list[str]):
62143 if platform .machine () == "arm64" :
63144 sys .exit (0 )
64145
65- main (args .commit_sha , args .build_log_files )
146+ main (
147+ args .commit_sha ,
148+ args .build_log_files ,
149+ args .github_token ,
150+ args .pr_number ,
151+ args .return_code ,
152+ )
0 commit comments