From 09eba4b057ae053ee8b30314e5a0773d50f8a1a9 Mon Sep 17 00:00:00 2001 From: Rudy Celekli Date: Mon, 28 Sep 2026 01:00:07 -0400 Subject: [PATCH] fix(convert): surface parallel failures and clean buffered logs --- scripts/convert.sh | 18 +++++++++--- scripts/test-convert-parallel-failure.sh | 35 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 scripts/test-convert-parallel-failure.sh diff --git a/scripts/convert.sh b/scripts/convert.sh index d810d4c8..d3df05cb 100755 --- a/scripts/convert.sh +++ b/scripts/convert.sh @@ -599,7 +599,8 @@ HEREDOC # then write at the end. AIDER_TMP="$(mktemp)" WINDSURF_TMP="$(mktemp)" -trap 'rm -f "$AIDER_TMP" "$WINDSURF_TMP"' EXIT +PARALLEL_OUT_DIR="" +trap 'rm -f "$AIDER_TMP" "$WINDSURF_TMP"; [[ -z "$PARALLEL_OUT_DIR" ]] || rm -rf "$PARALLEL_OUT_DIR"' EXIT # Write Aider/Windsurf headers once cat > "$AIDER_TMP" <<'HEREDOC' @@ -796,16 +797,25 @@ main() { # Tools that write to separate dirs can run in parallel; buffer output so each tool's output stays together local parallel_tools=(antigravity gemini-cli opencode cursor openclaw qwen zcode kimi codex osaurus hermes vibe dsh) local parallel_out_dir - parallel_out_dir="$(mktemp -d)" + parallel_out_dir="$(mktemp -d "${TMPDIR:-/tmp}/agency-convert-parallel.XXXXXX")" + PARALLEL_OUT_DIR="$parallel_out_dir" info "Converting: ${#parallel_tools[@]}/${n_tools} tools in parallel (output buffered per tool)..." export AGENCY_CONVERT_OUT_DIR="$parallel_out_dir" export AGENCY_CONVERT_SCRIPT="$SCRIPT_DIR/convert.sh" export AGENCY_CONVERT_OUT="$OUT_DIR" - printf '%s\n' "${parallel_tools[@]}" | xargs -P "$parallel_jobs" -I {} sh -c '"$AGENCY_CONVERT_SCRIPT" --tool "{}" --out "$AGENCY_CONVERT_OUT" > "$AGENCY_CONVERT_OUT_DIR/{}" 2>&1' + local parallel_status=0 + printf '%s\n' "${parallel_tools[@]}" | xargs -P "$parallel_jobs" -I {} sh -c '"$AGENCY_CONVERT_SCRIPT" --tool "{}" --out "$AGENCY_CONVERT_OUT" > "$AGENCY_CONVERT_OUT_DIR/{}" 2>&1' || parallel_status=$? for t in "${parallel_tools[@]}"; do - [[ -f "$parallel_out_dir/$t" ]] && cat "$parallel_out_dir/$t" + if [[ -f "$parallel_out_dir/$t" ]]; then + cat "$parallel_out_dir/$t" + fi done rm -rf "$parallel_out_dir" + PARALLEL_OUT_DIR="" + if (( parallel_status != 0 )); then + error "Parallel conversion failed (xargs exit $parallel_status); see tool output above." + return "$parallel_status" + fi local idx=$(( ${#parallel_tools[@]} + 1 )) for t in aider windsurf; do progress_bar "$idx" "$n_tools" diff --git a/scripts/test-convert-parallel-failure.sh b/scripts/test-convert-parallel-failure.sh new file mode 100644 index 00000000..196d7aab --- /dev/null +++ b/scripts/test-convert-parallel-failure.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# A failed parallel converter must expose its buffered error and clean up. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +FIXTURE="$(mktemp -d "${TMPDIR:-/tmp}/agency-convert-failure.XXXXXX")" +trap 'rm -rf "$FIXTURE"' EXIT + +# An empty roster makes this fast. Hermes intentionally lacks its builder. +mkdir -p "$FIXTURE/repo/scripts" +cp "$SCRIPT_DIR/convert.sh" "$SCRIPT_DIR/lib.sh" "$FIXTURE/repo/scripts/" + +status=0 +TMPDIR="$FIXTURE" "$FIXTURE/repo/scripts/convert.sh" \ + --tool all --parallel --jobs 2 --out "$FIXTURE/output" \ + > "$FIXTURE/run.log" 2>&1 || status=$? + +[[ "$status" -ne 0 ]] || { echo "parallel conversion unexpectedly succeeded" >&2; exit 1; } +grep -Fq 'build-hermes-plugin.py' "$FIXTURE/run.log" || { + echo "parallel converter error was hidden in its buffered output" >&2 + exit 1 +} +if find "$FIXTURE" -mindepth 1 -maxdepth 1 -type d -name 'agency-convert-parallel.*' | grep -q .; then + echo "parallel conversion left its buffered output directory behind" >&2 + exit 1 +fi + +# The same empty-roster fixture succeeds once its one missing converter exists. +printf 'import sys\n' > "$FIXTURE/repo/scripts/build-hermes-plugin.py" +TMPDIR="$FIXTURE" "$FIXTURE/repo/scripts/convert.sh" \ + --tool all --parallel --jobs 2 --out "$FIXTURE/output" \ + > "$FIXTURE/success.log" 2>&1 +grep -Fq 'Done. 15 tools' "$FIXTURE/success.log" + +echo "PASS: parallel converter reports failure and cleans buffered logs"