3
3
import settings
4
4
import difflib
5
5
import utils
6
+ import shutil
7
+ import json
8
+ import filecmp
6
9
7
10
"""
8
11
This script compares the generated CSV coverage files with the ones in the codebase.
9
12
"""
10
13
14
+ artifacts_worflow_name = "Check framework coverage changes"
15
+
11
16
12
17
def check_file_exists (file ):
13
18
if not os .path .exists (file ):
@@ -41,20 +46,27 @@ def compare_files_str(file1, file2):
41
46
return ret
42
47
43
48
44
- def comment_pr (output_file , repo , run_id ):
49
+ def write_diff_for_run (output_file , repo , run_id ):
45
50
folder1 = "out_base"
46
51
folder2 = "out_merge"
47
- utils .subprocess_run (["gh" , "run" , "download" , "--repo" , repo , "--name" ,
48
- "csv-framework-coverage-base" , "--dir" , folder1 , str (run_id )])
49
- utils .subprocess_run (["gh" , "run" , "download" , "--repo" , repo , "--name" ,
50
- "csv-framework-coverage-merge" , "--dir" , folder2 , str (run_id )])
51
- utils .subprocess_run (["gh" , "run" , "download" , "--repo" , repo , "--name" ,
52
- "pr" , "--dir" , "pr" , str (run_id )])
52
+ try :
53
+ utils .subprocess_run (["gh" , "run" , "download" , "--repo" , repo , "--name" ,
54
+ "csv-framework-coverage-base" , "--dir" , folder1 , str (run_id )])
55
+ utils .subprocess_run (["gh" , "run" , "download" , "--repo" , repo , "--name" ,
56
+ "csv-framework-coverage-merge" , "--dir" , folder2 , str (run_id )])
57
+ utils .subprocess_run (["gh" , "run" , "download" , "--repo" , repo , "--name" ,
58
+ "pr" , "--dir" , "pr" , str (run_id )])
59
+
60
+ compare_folders (folder1 , folder2 , output_file )
61
+ finally :
62
+ if os .path .isdir (folder1 ):
63
+ shutil .rmtree (folder1 )
53
64
54
- with open ( "pr/NR" ) as file :
55
- pr_number = int ( file . read () )
65
+ if os . path . isdir ( folder2 ) :
66
+ shutil . rmtree ( folder2 )
56
67
57
- compare_folders (folder1 , folder2 , output_file )
68
+
69
+ def get_comment_text (output_file , repo , run_id ):
58
70
size = os .path .getsize (output_file )
59
71
if size == 0 :
60
72
print ("No difference in the coverage reports" )
@@ -74,16 +86,60 @@ def comment_pr(output_file, repo, run_id):
74
86
comment += "The differences can be found in the " + \
75
87
output_file + " artifact of this job."
76
88
77
- # post_comment(comment, repo, pr_number)
89
+ return comment
90
+
91
+
92
+ def comment_pr (output_file , repo , run_id ):
93
+ """
94
+ Generates coverage diff produced by the changes in the current PR. If the diff is not empty, then post it as a comment.
95
+ If a workflow run produces the same diff as the directly preceeding one, then don't post a comment.
96
+ """
97
+
98
+ # Store diff for current run
99
+ write_diff_for_run (output_file , repo , run_id )
100
+
101
+ try :
102
+ with open ("pr/NR" ) as file :
103
+ pr_number = int (file .read ())
104
+ finally :
105
+ if os .path .isdir ("pr" ):
106
+ shutil .rmtree ("pr" )
107
+
108
+ # Try storing diff for previous run:
109
+ prev_output_file = "prev_" + output_file
110
+ try :
111
+ prev_run_id = get_previous_run_id (repo , run_id , pr_number )
112
+ write_diff_for_run (prev_output_file , repo , prev_run_id )
113
+
114
+ if filecmp .cmp (output_file , prev_output_file , shallow = False ):
115
+ print ("Previous run " + str (prev_run_id ) +
116
+ " resulted in the same diff, so not commenting again." )
117
+ return
118
+ else :
119
+ print ("Diff of previous run " +
120
+ str (prev_run_id ) + " differs, commenting." )
121
+ except Exception :
122
+ # this is not mecessarily a failure, it can also mean that there was no previous run yet.
123
+ print ("Couldn't generate diff for previous run:" , sys .exc_info ()[1 ])
124
+ finally :
125
+ if os .path .isfile (prev_output_file ):
126
+ os .remove (prev_output_file )
127
+
128
+ comment = get_comment_text (output_file , repo , run_id )
129
+ post_comment (comment , repo , pr_number )
78
130
79
131
80
132
def post_comment (comment , repo , pr_number ):
81
133
print ("Posting comment to PR #" + str (pr_number ))
82
- utils .subprocess_run (["gh" , "pr" , "comment" , pr_number ,
134
+ utils .subprocess_run (["gh" , "pr" , "comment" , str ( pr_number ) ,
83
135
"--repo" , repo , "--body" , comment ])
84
136
85
137
86
138
def compare_folders (folder1 , folder2 , output_file ):
139
+ """
140
+ Compares the contents of two folders and writes the differences to the output file.
141
+ """
142
+
87
143
languages = ['java' ]
88
144
89
145
return_md = ""
@@ -137,5 +193,49 @@ def compare_folders(folder1, folder2, output_file):
137
193
out .write (return_md )
138
194
139
195
140
- # comment_pr(sys.argv[1], sys.argv[2], sys.argv[3])
141
- comment_pr ("x.md" , "dsp-testing/codeql-csv-coverage-pr-commenter" , 938931471 )
196
+ def get_previous_run_id (repo , run_id , pr_number ):
197
+ """
198
+ Gets the previous run id for a given workflow run, considering that the previous workflow run needs to come from the same PR.
199
+ """
200
+
201
+ # Get branch and repo from run:
202
+ this_run = utils .subprocess_check_output (["gh" , "api" , "-X" , "GET" , "repos/" + repo + "/actions/runs/" + str (
203
+ run_id ), "--jq" , "{ head_branch: .head_branch, head_repository: .head_repository.full_name }" ])
204
+
205
+ this_run = json .loads (this_run )
206
+ pr_branch = this_run ["head_branch" ]
207
+ pr_repo = this_run ["head_repository" ]
208
+
209
+ # Get all previous runs that match branch, repo and workflow name:
210
+ ids = utils .subprocess_check_output (["gh" , "api" , "-X" , "GET" , "repos/" + repo + "/actions/runs" , "-f" , "event=pull_request" , "-f" , "status=success" , "-f" , "name=\" " + artifacts_worflow_name + "\" " , "--jq" ,
211
+ "[.workflow_runs.[] | select(.head_branch==\" " + pr_branch + "\" and .head_repository.full_name==\" " + pr_repo + "\" ) | { created_at: .created_at, run_id: .id}] | sort_by(.created_at) | reverse | [.[].run_id]" ])
212
+
213
+ ids = json .loads (ids )
214
+ if ids [0 ] != run_id :
215
+ raise Exception ("Expected to find " + str (run_id ) +
216
+ " in the list of matching runs." )
217
+
218
+ for previous_run_id in ids [1 :]:
219
+ utils .subprocess_run (["gh" , "run" , "download" , "--repo" , repo ,
220
+ "--name" , "pr" , "--dir" , "prev_run_pr" , str (previous_run_id )])
221
+
222
+ try :
223
+ with open ("prev_run_pr/NR" ) as file :
224
+ prev_pr_number = int (file .read ())
225
+ print ("PR number: " + str (prev_pr_number ))
226
+ finally :
227
+ if os .path .isdir ("prev_run_pr" ):
228
+ shutil .rmtree ("prev_run_pr" )
229
+
230
+ # the previous run needs to be coming from the same PR:
231
+ if pr_number == prev_pr_number :
232
+ return previous_run_id
233
+
234
+ raise Exception ("Couldn't find previous run." )
235
+
236
+
237
+ output_file = sys .argv [1 ]
238
+ repo = sys .argv [2 ]
239
+ run_id = sys .argv [3 ]
240
+
241
+ comment_pr (output_file , repo , run_id )
0 commit comments