From 218d32e97424850a00ea9e9f78088458a9b170b5 Mon Sep 17 00:00:00 2001 From: Junhao Liao Date: Sat, 25 Oct 2025 08:27:30 -0400 Subject: [PATCH 1/4] feat(deployment): Add `--setup-only` flag to `start-clp.sh` for setup without starting services (resolves #1475). --- .../clp_package_utils/controller.py | 147 +++++++++--------- .../clp_package_utils/scripts/start_clp.py | 11 ++ docs/src/user-docs/quick-start/clp-json.md | 5 + docs/src/user-docs/quick-start/clp-text.md | 5 + 4 files changed, 94 insertions(+), 74 deletions(-) diff --git a/components/clp-package-utils/clp_package_utils/controller.py b/components/clp-package-utils/clp_package_utils/controller.py index 740767b26f..bf9f022db7 100644 --- a/components/clp-package-utils/clp_package_utils/controller.py +++ b/components/clp-package-utils/clp_package_utils/controller.py @@ -93,16 +93,16 @@ def start(self) -> None: """ @abstractmethod - def stop(self) -> None: + def set_up_env(self) -> None: """ - Stops the components. + Sets up all components to run by preparing environment variables, directories, and + configuration files. """ @abstractmethod - def _set_up_env(self) -> None: + def stop(self) -> None: """ - Sets up all components to run by preparing environment variables, directories, and - configuration files. + Stops the components. """ def _set_up_env_for_database(self) -> EnvVarsDict: @@ -642,75 +642,7 @@ def __init__(self, clp_config: CLPConfig, instance_id: str) -> None: self._project_name = f"clp-package-{instance_id}" super().__init__(clp_config) - def start(self) -> None: - """ - Starts CLP's components using Docker Compose. - - :raise: Propagates `check_docker_dependencies`'s exceptions. - :raise: Propagates `subprocess.run`'s exceptions. - """ - check_docker_dependencies( - should_compose_project_be_running=False, project_name=self._project_name - ) - self._set_up_env() - - deployment_type = self._clp_config.get_deployment_type() - logger.info(f"Starting CLP using Docker Compose ({deployment_type} deployment)...") - - cmd = ["docker", "compose", "--project-name", self._project_name] - if deployment_type == DeploymentType.BASE: - cmd += ["--file", "docker-compose.base.yaml"] - if self._clp_config.mcp_server is not None: - cmd += ["--profile", "mcp"] - cmd += ["up", "--detach", "--wait"] - subprocess.run( - cmd, - cwd=self._clp_home, - check=True, - ) - logger.info("Started CLP.") - - def stop(self) -> None: - """ - Stops CLP components deployed via Docker Compose. - - :raise: Propagates `subprocess.run`'s exceptions. - """ - try: - check_docker_dependencies( - should_compose_project_be_running=True, project_name=self._project_name - ) - except DockerComposeProjectNotRunningError: - logger.info( - "Docker Compose project '%s' is not running. Nothing to stop.", - self._project_name, - ) - return - except DockerDependencyError as e: - logger.warning( - 'Docker dependencies check failed: "%s". Attempting to stop CLP containers ' - "anyway...", - e, - ) - else: - logger.info("Stopping all CLP containers using Docker Compose...") - - subprocess.run( - ["docker", "compose", "--project-name", self._project_name, "down"], - cwd=self._clp_home, - check=True, - ) - logger.info("Stopped CLP.") - - @staticmethod - def _get_num_workers() -> int: - """ - :return: Number of worker processes to run. - """ - # This will change when we move from single to multi-container workers. See y-scope/clp#1424 - return multiprocessing.cpu_count() // 2 - - def _set_up_env(self) -> None: + def set_up_env(self) -> None: # Generate container-specific config. container_clp_config = generate_docker_compose_container_config(self._clp_config) num_workers = self._get_num_workers() @@ -796,6 +728,73 @@ def _set_up_env(self) -> None: continue env_file.write(f"{key}={value}\n") + def start(self) -> None: + """ + Starts CLP's components using Docker Compose. + + :raise: Propagates `check_docker_dependencies`'s exceptions. + :raise: Propagates `subprocess.run`'s exceptions. + """ + check_docker_dependencies( + should_compose_project_be_running=False, project_name=self._project_name + ) + + deployment_type = self._clp_config.get_deployment_type() + logger.info(f"Starting CLP using Docker Compose ({deployment_type} deployment)...") + + cmd = ["docker", "compose", "--project-name", self._project_name] + if deployment_type == DeploymentType.BASE: + cmd += ["--file", "docker-compose.base.yaml"] + if self._clp_config.mcp_server is not None: + cmd += ["--profile", "mcp"] + cmd += ["up", "--detach", "--wait"] + subprocess.run( + cmd, + cwd=self._clp_home, + check=True, + ) + logger.info("Started CLP.") + + def stop(self) -> None: + """ + Stops CLP components deployed via Docker Compose. + + :raise: Propagates `subprocess.run`'s exceptions. + """ + try: + check_docker_dependencies( + should_compose_project_be_running=True, project_name=self._project_name + ) + except DockerComposeProjectNotRunningError: + logger.info( + "Docker Compose project '%s' is not running. Nothing to stop.", + self._project_name, + ) + return + except DockerDependencyError as e: + logger.warning( + 'Docker dependencies check failed: "%s". Attempting to stop CLP containers ' + "anyway...", + e, + ) + else: + logger.info("Stopping all CLP containers using Docker Compose...") + + subprocess.run( + ["docker", "compose", "--project-name", self._project_name, "down"], + cwd=self._clp_home, + check=True, + ) + logger.info("Stopped CLP.") + + @staticmethod + def _get_num_workers() -> int: + """ + :return: Number of worker processes to run. + """ + # This will change when we move from single to multi-container workers. See y-scope/clp#1424 + return multiprocessing.cpu_count() // 2 + def get_or_create_instance_id(clp_config: CLPConfig) -> str: """ diff --git a/components/clp-package-utils/clp_package_utils/scripts/start_clp.py b/components/clp-package-utils/clp_package_utils/scripts/start_clp.py index 89ddf2f56b..b6316f6224 100755 --- a/components/clp-package-utils/clp_package_utils/scripts/start_clp.py +++ b/components/clp-package-utils/clp_package_utils/scripts/start_clp.py @@ -37,6 +37,11 @@ def main(argv): action="store_true", help="Enable debug logging.", ) + args_parser.add_argument( + "--setup-only", + action="store_true", + help="Validate configuration and prepare directories without starting services.", + ) parsed_args = args_parser.parse_args(argv[1:]) @@ -79,6 +84,12 @@ def main(argv): try: instance_id = get_or_create_instance_id(clp_config) controller = DockerComposeController(clp_config, instance_id) + if parsed_args.setup_only: + controller.set_up_env() + logger.info( + "Completed setup. Services are not started because --setup-only was provided." + ) + return 0 controller.start() except Exception as ex: if type(ex) == ValueError: diff --git a/docs/src/user-docs/quick-start/clp-json.md b/docs/src/user-docs/quick-start/clp-json.md index 7f080a3d87..a2f0f67567 100644 --- a/docs/src/user-docs/quick-start/clp-json.md +++ b/docs/src/user-docs/quick-start/clp-json.md @@ -17,6 +17,11 @@ To start CLP, run: sbin/start-clp.sh ``` +:::{tip} +To validate configuration and prepare directories without launching services, add the +`--setup-only` flag (e.g., `sbin/start-clp.sh --setup-only`). +::: + :::{note} If CLP fails to start (e.g., due to a port conflict), try adjusting the settings in `etc/clp-config.yml` and then run the start command again. diff --git a/docs/src/user-docs/quick-start/clp-text.md b/docs/src/user-docs/quick-start/clp-text.md index 89af511003..bc5d51719e 100644 --- a/docs/src/user-docs/quick-start/clp-text.md +++ b/docs/src/user-docs/quick-start/clp-text.md @@ -19,6 +19,11 @@ To start CLP, run: sbin/start-clp.sh ``` +:::{tip} +To validate configuration and prepare directories without launching services, add the +`--setup-only` flag (e.g., `sbin/start-clp.sh --setup-only`). +::: + :::{note} If CLP fails to start (e.g., due to a port conflict), try adjusting the settings in `etc/clp-config.yml` and then run the start command again. From e2772c48556e077b4730a4073426db28ffb449c1 Mon Sep 17 00:00:00 2001 From: Junhao Liao Date: Sat, 25 Oct 2025 10:33:10 -0400 Subject: [PATCH 2/4] fix(deployment): Update `--setup-only` logic in `start-clp.sh` to ensure environment setup is always performed. --- .../clp-package-utils/clp_package_utils/scripts/start_clp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/clp-package-utils/clp_package_utils/scripts/start_clp.py b/components/clp-package-utils/clp_package_utils/scripts/start_clp.py index b6316f6224..4088d74d5f 100755 --- a/components/clp-package-utils/clp_package_utils/scripts/start_clp.py +++ b/components/clp-package-utils/clp_package_utils/scripts/start_clp.py @@ -84,8 +84,8 @@ def main(argv): try: instance_id = get_or_create_instance_id(clp_config) controller = DockerComposeController(clp_config, instance_id) + controller.set_up_env() if parsed_args.setup_only: - controller.set_up_env() logger.info( "Completed setup. Services are not started because --setup-only was provided." ) From 83d2d8029df31e00a37c3b8a5aabe6b55ab2681a Mon Sep 17 00:00:00 2001 From: Junhao Liao Date: Mon, 27 Oct 2025 02:54:58 -0400 Subject: [PATCH 3/4] Improve `--setup-only` prompt - Apply suggestions from code review Co-authored-by: kirkrodrigues <2454684+kirkrodrigues@users.noreply.github.com> --- .../clp-package-utils/clp_package_utils/scripts/start_clp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/clp-package-utils/clp_package_utils/scripts/start_clp.py b/components/clp-package-utils/clp_package_utils/scripts/start_clp.py index 4088d74d5f..15a44b7458 100755 --- a/components/clp-package-utils/clp_package_utils/scripts/start_clp.py +++ b/components/clp-package-utils/clp_package_utils/scripts/start_clp.py @@ -87,7 +87,7 @@ def main(argv): controller.set_up_env() if parsed_args.setup_only: logger.info( - "Completed setup. Services are not started because --setup-only was provided." + "Completed setup. Services not started because `--setup-only` was specified." ) return 0 controller.start() From 70b2b14c1155124a3214cd8042813f68af265282 Mon Sep 17 00:00:00 2001 From: Junhao Liao Date: Mon, 27 Oct 2025 02:57:05 -0400 Subject: [PATCH 4/4] refactor(controller): Reorder abstract methods --- .../clp-package-utils/clp_package_utils/controller.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/clp-package-utils/clp_package_utils/controller.py b/components/clp-package-utils/clp_package_utils/controller.py index bf9f022db7..b0ec72fb45 100644 --- a/components/clp-package-utils/clp_package_utils/controller.py +++ b/components/clp-package-utils/clp_package_utils/controller.py @@ -87,16 +87,16 @@ def __init__(self, clp_config: CLPConfig) -> None: self._conf_dir = self._clp_home / "etc" @abstractmethod - def start(self) -> None: + def set_up_env(self) -> None: """ - Starts the components. + Sets up all components to run by preparing environment variables, directories, and + configuration files. """ @abstractmethod - def set_up_env(self) -> None: + def start(self) -> None: """ - Sets up all components to run by preparing environment variables, directories, and - configuration files. + Starts the components. """ @abstractmethod