11import argparse
2+ import datetime
23import io
34import json
45import logging
3132 REDIS_SOCKET_TIMEOUT ,
3233 REDIS_BINS_EXPIRE_SECS ,
3334)
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+ )
3442from redis_benchmarks_specification .__common__ .package import (
3543 populate_with_poetry_data ,
3644 get_version_string ,
3745)
3846
47+ PERFORMANCE_GH_TOKEN = os .getenv ("PERFORMANCE_GH_TOKEN" , None )
48+
3949
4050class ZipFileWithPermissions (ZipFile ):
4151 def _extract_member (self , member , targetpath , pwd ):
@@ -80,6 +90,8 @@ def main():
8090 action = "store_true" ,
8191 help = "Store the docker images in redis keys." ,
8292 )
93+ parser .add_argument ("--github_token" , type = str , default = PERFORMANCE_GH_TOKEN )
94+ parser .add_argument ("--pull-request" , type = str , default = None , nargs = "?" , const = "" )
8395 args = parser .parse_args ()
8496 if args .logname is not None :
8597 print ("Writting log to {}" .format (args .logname ))
@@ -138,16 +150,18 @@ def main():
138150 build_spec_image_prefetch (builders_folder , different_build_specs )
139151
140152 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!!! =)" )
142155 previous_id = args .consumer_start_id
143156 while True :
144- previous_id , new_builds_count = builder_process_stream (
157+ previous_id , new_builds_count , _ = builder_process_stream (
145158 builders_folder ,
146159 conn ,
147160 different_build_specs ,
148161 previous_id ,
149162 args .docker_air_gap ,
150163 arch ,
164+ args .github_token ,
151165 )
152166
153167
@@ -172,15 +186,29 @@ def builder_consumer_group_create(conn, id="$"):
172186 )
173187
174188
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+
175200def builder_process_stream (
176201 builders_folder ,
177202 conn ,
178203 different_build_specs ,
179204 previous_id ,
180205 docker_air_gap = False ,
181206 arch = "amd64" ,
207+ github_token = None ,
182208):
183209 new_builds_count = 0
210+ auto_approve_github_comments = True
211+ build_stream_fields_arr = []
184212 logging .info ("Entering blocking read waiting for work." )
185213 consumer_name = "{}-proc#{}" .format (STREAM_GH_EVENTS_COMMIT_BUILDERS_CG , "1" )
186214 newTestInfo = conn .xreadgroup (
@@ -215,12 +243,58 @@ def builder_process_stream(
215243 buffer = conn .get (binary_zip_key )
216244 git_timestamp_ms = None
217245 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 ()
218252 git_branch , git_version = get_branch_version_from_test_details (testDetails )
219253 if b"use_git_timestamp" in testDetails :
220254 use_git_timestamp = bool (testDetails [b"use_git_timestamp" ])
221255 if b"git_timestamp_ms" in testDetails :
222256 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
223286
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+ )
224298 for build_spec in different_build_specs :
225299 build_config , id = get_build_config (builders_folder + "/" + build_spec )
226300 build_config_metadata = get_build_config_metadata (build_config )
@@ -306,9 +380,41 @@ def builder_process_stream(
306380 "redis-server" ,
307381 build_vars_str ,
308382 )
383+ build_start_datetime = datetime .datetime .utcnow ()
309384 logging .info (
310- "Using the following build command {}" .format (build_command )
385+ "Using the following build command {}. " .format (build_command )
311386 )
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+
312418 docker_client .containers .run (
313419 image = build_image ,
314420 volumes = {
@@ -319,6 +425,10 @@ def builder_process_stream(
319425 working_dir = "/mnt/redis/" ,
320426 command = build_command ,
321427 )
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+
322432 build_stream_fields = {
323433 "id" : id ,
324434 "git_hash" : git_hash ,
@@ -333,7 +443,13 @@ def builder_process_stream(
333443 "build_command" : build_command ,
334444 "metadata" : json .dumps (build_config_metadata ),
335445 "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 ,
336450 }
451+ if pull_request is not None :
452+ build_stream_fields ["pull_request" ] = pull_request
337453 if git_branch is not None :
338454 build_stream_fields ["git_branch" ] = git_branch
339455 if git_version is not None :
@@ -356,16 +472,61 @@ def builder_process_stream(
356472 if b"platform" in testDetails :
357473 build_stream_fields ["platform" ] = testDetails [b"platform" ]
358474 if result is True :
359- stream_id = conn .xadd (
475+ benchmark_stream_id = conn .xadd (
360476 STREAM_KEYNAME_NEW_BUILD_EVENTS , build_stream_fields
361477 )
362478 logging .info (
363479 "sucessfully built build variant {} for redis git_sha {}. Stream id: {}" .format (
364- id , git_hash , stream_id
480+ id , git_hash , benchmark_stream_id
365481 )
366482 )
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+ )
367527 shutil .rmtree (temporary_dir , ignore_errors = True )
368528 new_builds_count = new_builds_count + 1
529+ build_stream_fields_arr .append (build_stream_fields )
369530 ack_reply = conn .xack (
370531 STREAM_KEYNAME_GH_EVENTS_COMMIT ,
371532 STREAM_GH_EVENTS_COMMIT_BUILDERS_CG ,
@@ -387,7 +548,7 @@ def builder_process_stream(
387548 )
388549 else :
389550 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
391552
392553
393554def build_spec_image_prefetch (builders_folder , different_build_specs ):
0 commit comments