From acd589669dddbc1882c08dde92f3c79797d7218e Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Tue, 21 Jan 2025 15:32:27 +0900 Subject: [PATCH 1/6] Introduce non-blocking mode in subset command --- launchable/commands/subset.py | 40 +++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/launchable/commands/subset.py b/launchable/commands/subset.py index e25d3b184..b40420846 100644 --- a/launchable/commands/subset.py +++ b/launchable/commands/subset.py @@ -3,6 +3,7 @@ import os import pathlib import sys +from multiprocessing import Process from os.path import join from typing import Any, Callable, Dict, List, Optional, Sequence, TextIO, Tuple, Union @@ -131,10 +132,19 @@ help="outputs the exclude test list. Switch the subset and rest.", is_flag=True, ) +@click.option( + "--non-blocking", + "is_non_blocking", + help=""" + Do not wait for subset requests in observation mode. + Please note that the CLI does not output a subset list if you specify this option. + """, + is_flag=True, +) @click.option( "--ignore-flaky-tests-above", "ignore_flaky_tests_above", - help='Ignore flaky tests above the value set by this option.You can confirm flaky scores in WebApp', + help='Ignore flaky tests above the value set by this option. You can confirm flaky scores in WebApp', type=click.FloatRange(min=0, max=1.0), ) @click.option( @@ -198,6 +208,7 @@ def subset( is_observation: bool, is_get_tests_from_previous_sessions: bool, is_output_exclusion_rules: bool, + is_non_blocking: bool, ignore_flaky_tests_above: Optional[float], links: Sequence[Tuple[str, str]] = (), is_no_build: bool = False, @@ -223,6 +234,20 @@ def subset( ) sys.exit(1) + if (not is_observation) and is_non_blocking: + msg = "You have to specify --observation option to use non-blocking mode" + click.echo( + click.style( + msg, + fg="red"), + err=True, + ) + tracking_client.send_error_event( + event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR, + stack_trace=msg, + ) + sys.exit(1) + if is_observation and is_output_exclusion_rules: msg = ( "WARNING: --observation and --output-exclusion-rules are set. " @@ -493,7 +518,14 @@ def run(self): timeout = (5, 300) payload = self.get_payload(session_id, target, duration, test_runner) - res = client.request("post", "subset", timeout=timeout, payload=payload, compress=True) + if is_non_blocking: + # Create a new process for requesting a subset. + process = Process(target=subset_request, args=(client, timeout, payload)) + process.start() + click.echo("The subset was requested in non-blocking mode.") + return + + res = subset_request(client=client, timeout=timeout, payload=payload) # The status code 422 is returned when validation error of the test mapping file occurs. if res.status_code == 422: @@ -600,3 +632,7 @@ def run(self): err=True) context.obj = Optimize(app=context.obj) + + +def subset_request(client: LaunchableClient, timeout: Tuple[int, int], payload: dict[str, Any]): + return client.request("post", "subset", timeout=timeout, payload=payload, compress=True) From 21a56d4c75f89480f760ba5a01b66013944b4cb1 Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Tue, 21 Jan 2025 15:47:43 +0900 Subject: [PATCH 2/6] Fix typing --- launchable/commands/subset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launchable/commands/subset.py b/launchable/commands/subset.py index b40420846..96694d3e8 100644 --- a/launchable/commands/subset.py +++ b/launchable/commands/subset.py @@ -634,5 +634,5 @@ def run(self): context.obj = Optimize(app=context.obj) -def subset_request(client: LaunchableClient, timeout: Tuple[int, int], payload: dict[str, Any]): +def subset_request(client: LaunchableClient, timeout: Tuple[int, int], payload: Dict[str, Any]): return client.request("post", "subset", timeout=timeout, payload=payload, compress=True) From a15901455830a97af3e328d3854f7055369f3d5c Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Tue, 21 Jan 2025 16:10:13 +0900 Subject: [PATCH 3/6] Fix based on reviews --- launchable/commands/subset.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/launchable/commands/subset.py b/launchable/commands/subset.py index 96694d3e8..28eb7cb04 100644 --- a/launchable/commands/subset.py +++ b/launchable/commands/subset.py @@ -135,11 +135,9 @@ @click.option( "--non-blocking", "is_non_blocking", - help=""" - Do not wait for subset requests in observation mode. - Please note that the CLI does not output a subset list if you specify this option. - """, + help="Do not wait for subset requests in observation mode.", is_flag=True, + hidden=True, ) @click.option( "--ignore-flaky-tests-above", @@ -523,6 +521,7 @@ def run(self): process = Process(target=subset_request, args=(client, timeout, payload)) process.start() click.echo("The subset was requested in non-blocking mode.") + self.output_handler(self.test_paths, []) return res = subset_request(client=client, timeout=timeout, payload=payload) From f4cbddd25340e02a6feb3fac0d5d531f79074e48 Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Tue, 21 Jan 2025 16:32:13 +0900 Subject: [PATCH 4/6] Fix based on reviews --- launchable/commands/subset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launchable/commands/subset.py b/launchable/commands/subset.py index 28eb7cb04..29f5f4f22 100644 --- a/launchable/commands/subset.py +++ b/launchable/commands/subset.py @@ -520,7 +520,7 @@ def run(self): # Create a new process for requesting a subset. process = Process(target=subset_request, args=(client, timeout, payload)) process.start() - click.echo("The subset was requested in non-blocking mode.") + click.echo("The subset was requested in non-blocking mode.", err=True) self.output_handler(self.test_paths, []) return From 296aaf00d462e4c44b0d28a6f3e51f206869e338 Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Tue, 21 Jan 2025 17:01:09 +0900 Subject: [PATCH 5/6] Stop the validation --- launchable/commands/subset.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/launchable/commands/subset.py b/launchable/commands/subset.py index 29f5f4f22..2c31b24fe 100644 --- a/launchable/commands/subset.py +++ b/launchable/commands/subset.py @@ -232,20 +232,6 @@ def subset( ) sys.exit(1) - if (not is_observation) and is_non_blocking: - msg = "You have to specify --observation option to use non-blocking mode" - click.echo( - click.style( - msg, - fg="red"), - err=True, - ) - tracking_client.send_error_event( - event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR, - stack_trace=msg, - ) - sys.exit(1) - if is_observation and is_output_exclusion_rules: msg = ( "WARNING: --observation and --output-exclusion-rules are set. " From 5fc6322fd2a0d0a6d06df235cc8c4f064996a206 Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Wed, 22 Jan 2025 15:48:22 +0900 Subject: [PATCH 6/6] Validate non-blocking option --- launchable/commands/subset.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/launchable/commands/subset.py b/launchable/commands/subset.py index 2c31b24fe..ffb7d7c56 100644 --- a/launchable/commands/subset.py +++ b/launchable/commands/subset.py @@ -300,6 +300,34 @@ def subset( else: click.echo(ignorable_error(e), err=True) + if is_non_blocking: + if (not is_observation) and session_id: + try: + client = LaunchableClient( + app=app, + tracking_client=tracking_client) + res = client.request("get", session_id) + is_observation_in_recorded_session = res.json().get("isObservation", False) + if not is_observation_in_recorded_session: + msg = "You have to specify --observation option to use non-blocking mode" + click.echo( + click.style( + msg, + fg="red"), + err=True, + ) + tracking_client.send_error_event( + event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR, + stack_trace=msg, + ) + sys.exit(1) + except Exception as e: + tracking_client.send_error_event( + event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR, + stack_trace=str(e), + ) + click.echo(ignorable_error(e), err=True) + file_path_normalizer = FilePathNormalizer(base_path, no_base_path_inference=no_base_path_inference) # TODO: placed here to minimize invasion in this PR to reduce the likelihood of