1
1
import argparse
2
+ import datetime
2
3
import io
3
4
import json
4
5
import logging
31
32
REDIS_SOCKET_TIMEOUT ,
32
33
REDIS_BINS_EXPIRE_SECS ,
33
34
)
35
+ from redis_benchmarks_specification .__common__ .github import (
36
+ check_github_available_and_actionable ,
37
+ generate_build_finished_pr_comment ,
38
+ update_comment_if_needed ,
39
+ create_new_pr_comment ,
40
+ generate_build_started_pr_comment ,
41
+ )
34
42
from redis_benchmarks_specification .__common__ .package import (
35
43
populate_with_poetry_data ,
36
44
get_version_string ,
37
45
)
38
46
47
+ PERFORMANCE_GH_TOKEN = os .getenv ("PERFORMANCE_GH_TOKEN" , None )
48
+
39
49
40
50
class ZipFileWithPermissions (ZipFile ):
41
51
def _extract_member (self , member , targetpath , pwd ):
@@ -80,6 +90,8 @@ def main():
80
90
action = "store_true" ,
81
91
help = "Store the docker images in redis keys." ,
82
92
)
93
+ parser .add_argument ("--github_token" , type = str , default = PERFORMANCE_GH_TOKEN )
94
+ parser .add_argument ("--pull-request" , type = str , default = None , nargs = "?" , const = "" )
83
95
args = parser .parse_args ()
84
96
if args .logname is not None :
85
97
print ("Writting log to {}" .format (args .logname ))
@@ -138,16 +150,18 @@ def main():
138
150
build_spec_image_prefetch (builders_folder , different_build_specs )
139
151
140
152
builder_consumer_group_create (conn )
141
-
153
+ if args .github_token is not None :
154
+ logging .info ("detected a github token. will update as much as possible!!! =)" )
142
155
previous_id = args .consumer_start_id
143
156
while True :
144
- previous_id , new_builds_count = builder_process_stream (
157
+ previous_id , new_builds_count , _ = builder_process_stream (
145
158
builders_folder ,
146
159
conn ,
147
160
different_build_specs ,
148
161
previous_id ,
149
162
args .docker_air_gap ,
150
163
arch ,
164
+ args .github_token ,
151
165
)
152
166
153
167
@@ -172,15 +186,29 @@ def builder_consumer_group_create(conn, id="$"):
172
186
)
173
187
174
188
189
+ def check_benchmark_build_comment (comments ):
190
+ res = False
191
+ pos = - 1
192
+ for n , comment in enumerate (comments ):
193
+ body = comment .body
194
+ if "CE Performance Automation : step 1 of 2" in body :
195
+ res = True
196
+ pos = n
197
+ return res , pos
198
+
199
+
175
200
def builder_process_stream (
176
201
builders_folder ,
177
202
conn ,
178
203
different_build_specs ,
179
204
previous_id ,
180
205
docker_air_gap = False ,
181
206
arch = "amd64" ,
207
+ github_token = None ,
182
208
):
183
209
new_builds_count = 0
210
+ auto_approve_github_comments = True
211
+ build_stream_fields_arr = []
184
212
logging .info ("Entering blocking read waiting for work." )
185
213
consumer_name = "{}-proc#{}" .format (STREAM_GH_EVENTS_COMMIT_BUILDERS_CG , "1" )
186
214
newTestInfo = conn .xreadgroup (
@@ -215,12 +243,58 @@ def builder_process_stream(
215
243
buffer = conn .get (binary_zip_key )
216
244
git_timestamp_ms = None
217
245
use_git_timestamp = False
246
+ commit_datetime = "n/a"
247
+ if b"commit_datetime" in testDetails :
248
+ commit_datetime = testDetails [b"commit_datetime" ].decode ()
249
+ commit_summary = "n/a"
250
+ if b"commit_summary" in testDetails :
251
+ commit_summary = testDetails [b"commit_summary" ].decode ()
218
252
git_branch , git_version = get_branch_version_from_test_details (testDetails )
219
253
if b"use_git_timestamp" in testDetails :
220
254
use_git_timestamp = bool (testDetails [b"use_git_timestamp" ])
221
255
if b"git_timestamp_ms" in testDetails :
222
256
git_timestamp_ms = int (testDetails [b"git_timestamp_ms" ].decode ())
257
+ tests_regexp = ".*"
258
+ if b"tests_regexp" in testDetails :
259
+ tests_regexp = testDetails [b"tests_regexp" ].decode ()
260
+ tests_priority_upper_limit = 10000
261
+ if b"tests_priority_upper_limit" in testDetails :
262
+ tests_priority_upper_limit = int (
263
+ testDetails [b"tests_priority_upper_limit" ].decode ()
264
+ )
265
+ tests_priority_lower_limit = 0
266
+ if b"tests_priority_lower_limit" in testDetails :
267
+ tests_priority_lower_limit = int (
268
+ testDetails [b"tests_priority_lower_limit" ].decode ()
269
+ )
270
+ tests_groups_regexp = ".*"
271
+ if b"tests_groups_regexp" in testDetails :
272
+ tests_groups_regexp = testDetails [b"tests_groups_regexp" ].decode ()
273
+
274
+ # github updates
275
+ is_actionable_pr = False
276
+ contains_regression_comment = False
277
+ github_pr = None
278
+ old_regression_comment_body = ""
279
+ pr_link = ""
280
+ regression_comment = ""
281
+ pull_request = None
282
+ if b"pull_request" in testDetails :
283
+ pull_request = testDetails [b"pull_request" ].decode ()
284
+ logging .info (f"Detected PR info in builder. PR: { pull_request } " )
285
+ verbose = True
223
286
287
+ fn = check_benchmark_build_comment
288
+ (
289
+ contains_regression_comment ,
290
+ github_pr ,
291
+ is_actionable_pr ,
292
+ old_regression_comment_body ,
293
+ pr_link ,
294
+ regression_comment ,
295
+ ) = check_github_available_and_actionable (
296
+ fn , github_token , pull_request , "redis" , "redis" , verbose
297
+ )
224
298
for build_spec in different_build_specs :
225
299
build_config , id = get_build_config (builders_folder + "/" + build_spec )
226
300
build_config_metadata = get_build_config_metadata (build_config )
@@ -306,9 +380,41 @@ def builder_process_stream(
306
380
"redis-server" ,
307
381
build_vars_str ,
308
382
)
383
+ build_start_datetime = datetime .datetime .utcnow ()
309
384
logging .info (
310
- "Using the following build command {}" .format (build_command )
385
+ "Using the following build command {}. " .format (build_command )
311
386
)
387
+ if is_actionable_pr :
388
+ logging .info (
389
+ f"updating on github we'll start the build at { build_start_datetime } "
390
+ )
391
+ comment_body = generate_build_started_pr_comment (
392
+ build_start_datetime ,
393
+ commit_datetime ,
394
+ commit_summary ,
395
+ git_branch ,
396
+ git_hash ,
397
+ tests_groups_regexp ,
398
+ tests_priority_lower_limit ,
399
+ tests_priority_upper_limit ,
400
+ tests_regexp ,
401
+ )
402
+ if contains_regression_comment :
403
+ update_comment_if_needed (
404
+ auto_approve_github_comments ,
405
+ comment_body ,
406
+ old_regression_comment_body ,
407
+ regression_comment ,
408
+ verbose ,
409
+ )
410
+ else :
411
+ regression_comment = create_new_pr_comment (
412
+ auto_approve_github_comments ,
413
+ comment_body ,
414
+ github_pr ,
415
+ pr_link ,
416
+ )
417
+
312
418
docker_client .containers .run (
313
419
image = build_image ,
314
420
volumes = {
@@ -319,6 +425,10 @@ def builder_process_stream(
319
425
working_dir = "/mnt/redis/" ,
320
426
command = build_command ,
321
427
)
428
+ build_end_datetime = datetime .datetime .utcnow ()
429
+ build_duration = build_end_datetime - build_start_datetime
430
+ build_duration_secs = build_duration .total_seconds ()
431
+
322
432
build_stream_fields = {
323
433
"id" : id ,
324
434
"git_hash" : git_hash ,
@@ -333,7 +443,13 @@ def builder_process_stream(
333
443
"build_command" : build_command ,
334
444
"metadata" : json .dumps (build_config_metadata ),
335
445
"build_artifacts" : "," .join (build_artifacts ),
446
+ "tests_regexp" : tests_regexp ,
447
+ "tests_priority_upper_limit" : tests_priority_upper_limit ,
448
+ "tests_priority_lower_limit" : tests_priority_lower_limit ,
449
+ "tests_groups_regexp" : tests_groups_regexp ,
336
450
}
451
+ if pull_request is not None :
452
+ build_stream_fields ["pull_request" ] = pull_request
337
453
if git_branch is not None :
338
454
build_stream_fields ["git_branch" ] = git_branch
339
455
if git_version is not None :
@@ -356,16 +472,61 @@ def builder_process_stream(
356
472
if b"platform" in testDetails :
357
473
build_stream_fields ["platform" ] = testDetails [b"platform" ]
358
474
if result is True :
359
- stream_id = conn .xadd (
475
+ benchmark_stream_id = conn .xadd (
360
476
STREAM_KEYNAME_NEW_BUILD_EVENTS , build_stream_fields
361
477
)
362
478
logging .info (
363
479
"sucessfully built build variant {} for redis git_sha {}. Stream id: {}" .format (
364
- id , git_hash , stream_id
480
+ id , git_hash , benchmark_stream_id
365
481
)
366
482
)
483
+ streamId_decoded = streamId .decode ()
484
+ benchmark_stream_id_decoded = benchmark_stream_id .decode ()
485
+ builder_list_completed = (
486
+ f"builder:{ streamId_decoded } :builds_completed"
487
+ )
488
+ conn .lpush (builder_list_completed , benchmark_stream_id_decoded )
489
+ conn .expire (builder_list_completed , REDIS_BINS_EXPIRE_SECS )
490
+ logging .info (
491
+ f"Adding information of build->benchmark stream info in list { builder_list_completed } . Adding benchmark stream id: { benchmark_stream_id_decoded } "
492
+ )
493
+ benchmark_stream_ids = [benchmark_stream_id_decoded ]
494
+
495
+ if is_actionable_pr :
496
+ logging .info (
497
+ f"updating on github that the build finished after { build_duration_secs } seconds"
498
+ )
499
+ comment_body = generate_build_finished_pr_comment (
500
+ benchmark_stream_ids ,
501
+ commit_datetime ,
502
+ commit_summary ,
503
+ git_branch ,
504
+ git_hash ,
505
+ tests_groups_regexp ,
506
+ tests_priority_lower_limit ,
507
+ tests_priority_upper_limit ,
508
+ tests_regexp ,
509
+ build_start_datetime ,
510
+ build_duration_secs ,
511
+ )
512
+ if contains_regression_comment :
513
+ update_comment_if_needed (
514
+ auto_approve_github_comments ,
515
+ comment_body ,
516
+ old_regression_comment_body ,
517
+ regression_comment ,
518
+ verbose ,
519
+ )
520
+ else :
521
+ create_new_pr_comment (
522
+ auto_approve_github_comments ,
523
+ comment_body ,
524
+ github_pr ,
525
+ pr_link ,
526
+ )
367
527
shutil .rmtree (temporary_dir , ignore_errors = True )
368
528
new_builds_count = new_builds_count + 1
529
+ build_stream_fields_arr .append (build_stream_fields )
369
530
ack_reply = conn .xack (
370
531
STREAM_KEYNAME_GH_EVENTS_COMMIT ,
371
532
STREAM_GH_EVENTS_COMMIT_BUILDERS_CG ,
@@ -387,7 +548,7 @@ def builder_process_stream(
387
548
)
388
549
else :
389
550
logging .error ("Missing commit information within received message." )
390
- return previous_id , new_builds_count
551
+ return previous_id , new_builds_count , build_stream_fields_arr
391
552
392
553
393
554
def build_spec_image_prefetch (builders_folder , different_build_specs ):
0 commit comments