Skip to content

Commit 76f4c7c

Browse files
author
Build Tools
committed
lots of silent failures
1 parent 7216386 commit 76f4c7c

5 files changed

Lines changed: 101 additions & 25 deletions

File tree

bin/ci_tool/ci_fix.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ def read_container_state(container_name):
113113
try:
114114
return json.loads(result.stdout)
115115
except json.JSONDecodeError:
116+
console.print(
117+
f"[yellow]State file exists but contains invalid JSON: "
118+
f"{result.stdout[:200]}[/yellow]"
119+
)
116120
return None
117121

118122

@@ -355,23 +359,35 @@ def run_claude_streamed(container_name, prompt):
355359
"""Run Claude non-interactively with stream-json output."""
356360
escaped_prompt = prompt.replace("'", "'\\''")
357361
claude_command = (
362+
f"set -o pipefail && "
358363
f"cd /ros_ws && IS_SANDBOX=1 claude --dangerously-skip-permissions "
359364
f"-p '{escaped_prompt}' --verbose --output-format stream-json "
360365
f"2>{CLAUDE_STDERR_LOG} | ci_fix_display"
361366
)
362-
docker_exec(container_name, claude_command, tty=True, check=False, quiet=True)
367+
result = docker_exec(container_name, claude_command, tty=True, check=False, quiet=True)
368+
if result.returncode != 0:
369+
console.print(
370+
f"[yellow]Claude exited with code {result.returncode} — "
371+
f"check {CLAUDE_STDERR_LOG} inside the container for details[/yellow]"
372+
)
363373

364374

365375
def run_claude_resumed(container_name, session_id, prompt):
366376
"""Resume a Claude session with a new prompt, streaming output."""
367377
escaped_prompt = prompt.replace("'", "'\\''")
368378
claude_command = (
379+
f"set -o pipefail && "
369380
f"cd /ros_ws && IS_SANDBOX=1 claude --dangerously-skip-permissions "
370381
f"--resume '{session_id}' -p '{escaped_prompt}' "
371382
f"--verbose --output-format stream-json "
372383
f"2>{CLAUDE_STDERR_LOG} | ci_fix_display"
373384
)
374-
docker_exec(container_name, claude_command, tty=True, check=False, quiet=True)
385+
result = docker_exec(container_name, claude_command, tty=True, check=False, quiet=True)
386+
if result.returncode != 0:
387+
console.print(
388+
f"[yellow]Claude exited with code {result.returncode} — "
389+
f"check {CLAUDE_STDERR_LOG} inside the container for details[/yellow]"
390+
)
375391

376392

377393
def prompt_user_for_feedback():
@@ -431,7 +447,7 @@ def run_claude_workflow(container_name, ci_run_info):
431447

432448
# Fix phase (resume session)
433449
state = read_container_state(container_name)
434-
session_id = state["session_id"] if state else None
450+
session_id = state.get("session_id") if state else None
435451
if session_id:
436452
console.print(
437453
"\n[bold cyan]Resuming Claude "
@@ -540,13 +556,17 @@ def fix_ci(_args):
540556
console.print(
541557
"[dim]You are now in an interactive Claude session[/dim]\n"
542558
)
543-
docker_exec(
559+
result = docker_exec(
544560
container_name,
545561
"cd /ros_ws && IS_SANDBOX=1 claude "
546562
"--dangerously-skip-permissions "
547563
f'--resume "{resume_session_id}"',
548564
interactive=True, check=False,
549565
)
566+
if result.returncode != 0:
567+
console.print(
568+
f"[yellow]Claude exited with code {result.returncode}[/yellow]"
569+
)
550570
else:
551571
run_claude_workflow(
552572
container_name, session.get("ci_run_info")

bin/ci_tool/ci_reproduce.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,20 @@ def _docker_create_and_start(
199199
console.print(f" [green]\u2713[/green] Container '{container_name}' started")
200200

201201

202+
def _container_path_exists(container_name, path):
203+
"""Check if a path exists inside a container."""
204+
result = subprocess.run(
205+
["docker", "exec", container_name, "test", "-e", path],
206+
check=False,
207+
)
208+
return result.returncode == 0
209+
210+
202211
def _docker_exec_workspace_setup(container_name):
203212
"""Run ci_workspace_setup.sh inside the container.
204213
205-
Handles KeyboardInterrupt gracefully by letting the container keep running.
214+
Raises RuntimeError if setup fails before the build completes.
215+
Warns (but continues) if tests fail after a successful build.
206216
"""
207217
console.print("\n Running CI workspace setup inside container...")
208218
try:
@@ -215,14 +225,27 @@ def _docker_exec_workspace_setup(container_name):
215225
"\n[yellow]Interrupted during workspace setup "
216226
"-- container is still running with partial setup[/yellow]"
217227
)
228+
raise
229+
230+
if result.returncode == 0:
218231
return
219232

220-
if result.returncode != 0:
221-
console.print(
222-
f"\n[yellow]Workspace setup exited with code {result.returncode} "
223-
f"(expected if tests failed)[/yellow]"
233+
# Non-zero exit: distinguish setup failure from test failure by checking
234+
# whether the build actually completed (/ros_ws/install only exists after
235+
# a successful colcon build).
236+
build_completed = _container_path_exists(container_name, "/ros_ws/install")
237+
238+
if not build_completed:
239+
raise RuntimeError(
240+
f"Workspace setup failed (exit code {result.returncode}). "
241+
f"The build did not complete — check the output above for errors."
224242
)
225243

244+
console.print(
245+
f"\n[yellow]Tests exited with code {result.returncode} "
246+
f"(build succeeded, test failures are expected)[/yellow]"
247+
)
248+
226249

227250
def prompt_for_repo_and_branch():
228251
"""Ask user for repository URL and branch name interactively.

bin/ci_tool/claude_setup.py

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ def install_claude_in_container(container_name):
3434

3535

3636
def install_fzf_in_container(container_name):
37-
"""Install fzf in the container."""
37+
"""Install fzf in the container (non-critical)."""
3838
console.print("[cyan]Installing fzf in container...[/cyan]")
39-
docker_exec(container_name, "apt-get update && apt-get install -y fzf", check=False)
39+
result = docker_exec(container_name, "apt-get update && apt-get install -y fzf", check=False)
40+
if result.returncode != 0:
41+
console.print("[yellow]fzf installation failed (non-critical) — continuing[/yellow]")
4042

4143

4244
def install_python_deps_in_container(container_name):
@@ -187,7 +189,10 @@ def save_package_list(container_name):
187189
quiet=True,
188190
)
189191
if result.returncode != 0:
190-
console.print("[yellow]Could not save package list (colcon list failed)[/yellow]")
192+
console.print(
193+
"[yellow]Could not save package list (colcon list failed). "
194+
"The 'rerun_tests' helper will not work.[/yellow]"
195+
)
191196

192197

193198
def inject_rerun_tests_function(container_name):
@@ -267,7 +272,7 @@ def get_host_git_config(key):
267272

268273
def configure_git_in_container(container_name):
269274
"""Set up git identity, token-based auth, and gh CLI auth in the container."""
270-
gh_token = os.environ.get("GH_TOKEN", "")
275+
gh_token = os.environ.get("GH_TOKEN") or os.environ.get("ER_SETUP_TOKEN") or ""
271276

272277
git_user_name = get_host_git_config("user.name")
273278
git_user_email = get_host_git_config("user.email")
@@ -276,20 +281,26 @@ def configure_git_in_container(container_name):
276281
docker_exec(container_name, f'git config --global user.name "{git_user_name}"')
277282
docker_exec(container_name, f'git config --global user.email "{git_user_email}"')
278283

279-
if gh_token:
280-
docker_exec(
281-
container_name,
282-
f'git config --global url."https://{gh_token}@github.com/"'
283-
f'.insteadOf "https://github.com/"',
284-
quiet=True,
284+
if not gh_token:
285+
console.print(
286+
"[yellow]No GH_TOKEN or ER_SETUP_TOKEN found — "
287+
"git auth and gh CLI will not be configured in container[/yellow]"
285288
)
286-
install_and_auth_gh_cli(container_name, gh_token)
289+
return
290+
291+
docker_exec(
292+
container_name,
293+
f'git config --global url."https://{gh_token}@github.com/"'
294+
f'.insteadOf "https://github.com/"',
295+
quiet=True,
296+
)
297+
install_and_auth_gh_cli(container_name, gh_token)
287298

288299

289300
def install_and_auth_gh_cli(container_name, gh_token):
290301
"""Install gh CLI and authenticate with the provided token."""
291302
console.print("[cyan]Installing gh CLI in container...[/cyan]")
292-
docker_exec(container_name, (
303+
install_result = docker_exec(container_name, (
293304
"type gh >/dev/null 2>&1 || ("
294305
"curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg "
295306
"| dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg "
@@ -300,13 +311,25 @@ def install_and_auth_gh_cli(container_name, gh_token):
300311
"| tee /etc/apt/sources.list.d/github-cli-stable.list > /dev/null "
301312
"&& apt-get update && apt-get install -y gh)"
302313
), check=False)
314+
if install_result.returncode != 0:
315+
console.print(
316+
"[yellow]gh CLI installation failed — "
317+
"Claude will not be able to interact with GitHub from inside the container[/yellow]"
318+
)
319+
return
320+
303321
console.print("[cyan]Authenticating gh CLI...[/cyan]")
304-
docker_exec(
322+
auth_result = docker_exec(
305323
container_name,
306324
f'echo "{gh_token}" | gh auth login --with-token',
307325
check=False,
308326
quiet=True,
309327
)
328+
if auth_result.returncode != 0:
329+
console.print(
330+
"[yellow]gh CLI authentication failed — "
331+
"Claude will not be able to interact with GitHub from inside the container[/yellow]"
332+
)
310333

311334

312335
def is_claude_installed_in_container(container_name):

bin/ci_tool/containers.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ def container_exists(container_name=DEFAULT_CONTAINER_NAME):
3535
["docker", "ps", "-a", "--filter", f"name=^{container_name}$", "--format", "{{.Names}}"],
3636
capture_output=True, text=True, check=False,
3737
)
38+
if result.returncode != 0:
39+
raise RuntimeError(f"docker ps failed: {result.stderr.strip()}")
3840
return container_name in result.stdout.strip()
3941

4042

@@ -44,6 +46,8 @@ def container_is_running(container_name=DEFAULT_CONTAINER_NAME):
4446
["docker", "ps", "--filter", f"name=^{container_name}$", "--format", "{{.Names}}"],
4547
capture_output=True, text=True, check=False,
4648
)
49+
if result.returncode != 0:
50+
raise RuntimeError(f"docker ps failed: {result.stderr.strip()}")
4751
return container_name in result.stdout.strip()
4852

4953

@@ -65,6 +69,8 @@ def list_ci_containers():
6569
"--format", "{{.Names}}\t{{.Status}}"],
6670
capture_output=True, text=True, check=False,
6771
)
72+
if result.returncode != 0:
73+
raise RuntimeError(f"docker ps failed: {result.stderr.strip()}")
6874
if not result.stdout.strip():
6975
return []
7076
containers = []

bin/ci_tool/display_progress.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ def read_existing_attempt_count():
5252
try:
5353
with open(STATE_FILE, encoding="utf-8") as state_file:
5454
return json.load(state_file).get("attempt_count", 0)
55-
except (FileNotFoundError, json.JSONDecodeError, KeyError):
55+
except FileNotFoundError:
56+
return 0
57+
except (json.JSONDecodeError, KeyError) as error:
58+
console.print(f"[yellow]State file corrupt, resetting attempt count: {error}[/yellow]")
5659
return 0
5760

5861

@@ -120,7 +123,7 @@ def print_session_summary(session_id, start_time):
120123
console.print("[yellow]Claude stderr output:[/yellow]")
121124
console.print(stderr_content)
122125
except FileNotFoundError:
123-
pass
126+
console.print(f"[dim]No stderr log at {CLAUDE_STDERR_LOG}[/dim]")
124127

125128

126129
def main():
@@ -145,6 +148,7 @@ def main():
145148
try:
146149
event = json.loads(line)
147150
except json.JSONDecodeError:
151+
sys.stderr.write(f" {line}\n")
148152
continue
149153

150154
event_session_id = handle_event(event, start_time)
@@ -155,7 +159,7 @@ def main():
155159

156160
except KeyboardInterrupt:
157161
phase = "interrupted"
158-
except Exception: # pylint: disable=broad-except
162+
except (IOError, ValueError, UnicodeDecodeError):
159163
console.print(
160164
f"\n[red]Display processor error:[/red]\n{traceback.format_exc()}"
161165
)

0 commit comments

Comments
 (0)