From 7eb86a5bf4a06c4f29f601f4a7dd98e04ae3683b Mon Sep 17 00:00:00 2001 From: Siddhanth Gupta Date: Wed, 4 Nov 2026 12:54:15 +0530 Subject: [PATCH] fix(cli): exit non-zero when --auto-build fails The auto-build step caught CalledProcessError, printed "Build failed" and then fell through to the "Workflow ready!" panel, so the command exited 0. Print the build's stdout/stderr and re-raise, like the generation step does, so cli.py reports the error and exits 1. --- concore_cli/commands/build.py | 5 ++++- tests/test_cli.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/concore_cli/commands/build.py b/concore_cli/commands/build.py index aeb2e50..238a0f0 100644 --- a/concore_cli/commands/build.py +++ b/concore_cli/commands/build.py @@ -318,9 +318,12 @@ def build_workflow( console.print("[green]✓[/green] Build completed") except subprocess.CalledProcessError as e: progress.stop() - console.print("[yellow]Build failed[/yellow]") + console.print("[red]Build failed:[/red]") + if e.stdout: + console.print(e.stdout) if e.stderr: console.print(e.stderr) + raise run_command = "docker compose up" if compose else "./run" if exec_type == "windows": diff --git a/tests/test_cli.py b/tests/test_cli.py index b95c60d..8fbdfac 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -882,6 +882,39 @@ def test_build_command_shared_source_specialization_merges_edge_params(self): self.assertIn("PORT_NAME_B_C", content) self.assertIn("PORT_B_C", content) + def test_build_command_auto_build_failure_exits_nonzero(self): + real_run = subprocess.run + + def fake_run(cmd, *args, **kwargs): + if Path(str(cmd[0])).name in ("build", "build.bat"): + raise subprocess.CalledProcessError(1, cmd, output="", stderr="boom") + return real_run(cmd, *args, **kwargs) + + with self.runner.isolated_filesystem(temp_dir=self.temp_dir): + result = self.runner.invoke(cli, ["init", "test-project"]) + self.assertEqual(result.exit_code, 0) + + with patch.object(subprocess, "run", side_effect=fake_run): + result = self.runner.invoke( + cli, + [ + "build", + "test-project/workflow.graphml", + "--source", + "test-project/src", + "--output", + "out", + "--type", + "posix", + "--auto-build", + ], + ) + + self.assertNotEqual(result.exit_code, 0) + self.assertIn("boom", result.output) + self.assertIn("Build failed", result.output) + self.assertNotIn("Workflow ready", result.output) + def test_build_command_existing_output(self): with self.runner.isolated_filesystem(temp_dir=self.temp_dir): result = self.runner.invoke(cli, ["init", "test-project"])