From ade0f286d3d31107ba3a94ec080be7d5c2f689f9 Mon Sep 17 00:00:00 2001 From: openhands Date: Tue, 11 Aug 2026 19:49:00 +0200 Subject: [PATCH] fix: preserve real exit code in EXIT trap and fold parallel job state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The EXIT trap ended with '[ $ec -ne 0 ] && cleanup_notify_failure ...', so its last command returned 1 on success and the notify status on failure — every run exited with code 1 regardless of the actual result. Rewrite cleanup_on_exit to return the real status. Parallel jobs run in subshells, so HAD_UPDATES/UPDATED_REPOS/NITRO_BUILT set inside update_renderer/update_client were lost. Persist per-job deltas to a temp state dir and re-source them in parallel_wait so the summary reflects renderer/client updates. Also keep the per-repo yarn cache between updates (only removed on explicit Clean) and drop the dead clean_node_modules helper. --- update-Nitrov3.sh | 53 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/update-Nitrov3.sh b/update-Nitrov3.sh index 3b13047433..282e0b784b 100755 --- a/update-Nitrov3.sh +++ b/update-Nitrov3.sh @@ -860,7 +860,13 @@ cleanup_on_exit() { fi restore_binaries fi - [ $ec -ne 0 ] && cleanup_notify_failure "Exit code $ec" + # Preserve the real exit status: the last command in an EXIT trap defines + # the script's exit code, so never let a guard/notify call overwrite it. + if [ $ec -ne 0 ]; then + cleanup_notify_failure "Exit code $ec" + return $ec + fi + return 0 } trap cleanup_on_exit EXIT trap 'release_lock; cursor_show; exit 1' SIGINT SIGTERM @@ -924,14 +930,6 @@ git_update() { ) } -clean_node_modules() { - if [ ! -f "package.json" ]; then - warn "clean_node_modules: no package.json found, skipping" - return - fi - rm -rf "node_modules" 2>/dev/null || sudo rm -rf "$(pwd)/node_modules" 2>/dev/null || true -} - # yarn install scoped to a per-repo cache folder. Parallel installs (renderer + # client) must never share a cache — yarn 1 corrupts the shared cache, leaving # node_modules incomplete (vite/pixi.js missing) while still exiting 0. @@ -965,11 +963,35 @@ PARALLEL_NAMES=() PARALLEL_FAILED=() PARALLEL_RESULTS=() +# Each parallel job runs in a subshell, so variable changes (HAD_UPDATES, +# UPDATED_REPOS, NITRO_BUILT) made inside update_renderer/update_client would +# otherwise be lost. Jobs persist their state to a per-job file which +# parallel_wait re-reads back into the parent shell. +PARALLEL_STATE_DIR="${TMPDIR:-/tmp}/nitro-parallel-$$" +mkdir -p "$PARALLEL_STATE_DIR" 2>/dev/null || true + parallel_run() { local name="$1"; shift PARALLEL_NAMES+=("$name") ( + # Snapshot inherited state so we only persist the delta back: the + # emulator (run before the parallel phase) may already be in + # UPDATED_REPOS, so emitting the full array would duplicate it. + local _orig="${UPDATED_REPOS[*]:-}" "$@" >/dev/null 2>&1 + local rc=$? + { + # Note: exit status is captured via `wait`; only fold state vars back. + echo "HAD_UPDATES=$HAD_UPDATES" + echo "NITRO_BUILT=$NITRO_BUILT" + for r in "${UPDATED_REPOS[@]:-}"; do + case " $_orig " in + *" $r "*) ;; + *) printf 'UPDATED_REPOS+=(\047%s\047)\n' "$r" ;; + esac + done + } > "$PARALLEL_STATE_DIR/$name" + exit $rc ) & PARALLEL_PIDS+=($!) } @@ -987,10 +1009,17 @@ parallel_wait() { PARALLEL_RESULTS+=("__PARALLEL_FAIL__${name}") PARALLEL_FAILED+=("$name") fi + # Fold the job's persisted state back into the parent shell so the + # summary reflects renderer/client updates, not just the emulator. + if [ -f "$PARALLEL_STATE_DIR/$name" ]; then + . "$PARALLEL_STATE_DIR/$name" + rm -f "$PARALLEL_STATE_DIR/$name" + fi i=$((i+1)) done PARALLEL_PIDS=() PARALLEL_NAMES=() + rm -rf "$PARALLEL_STATE_DIR" 2>/dev/null || true } parallel_failed() { @@ -1327,10 +1356,10 @@ do_cleanup() { ok "Old config backups pruned" fi [ -d "$BACKUP_DIR" ] && find "$BACKUP_DIR" -maxdepth 1 -name '*.sql' -printf '%T@ %p\n' 2>/dev/null | sort -rn | tail -n +6 | sed 's/^[0-9.]* //' | xargs -r rm -f || true - # Clean both the global yarn cache and the per-repo caches used by the - # parallel renderer/client installs. + # NOTE: the per-repo yarn cache ($YARN_CACHE_DIR) is intentionally kept + # between updates — it is what makes parallel installs fast and reliable. + # It is only removed on an explicit "Clean" (menu) action. yarn cache clean 2>/dev/null || true - rm -rf "$YARN_CACHE_DIR" 2>/dev/null || true rm -rf /tmp/nitro-* /tmp/epicnext-* 2>/dev/null || true # Clean old Maven build artifacts (older than 7 days) find "$EMULATOR_MODULE" -maxdepth 3 -name '*.jar' -mtime +7 2>/dev/null -exec rm -f {} \; || true