diff --git a/scripts/redeploy-fleetd.sh b/scripts/redeploy-fleetd.sh index 2c7f0b3..a9067b9 100755 --- a/scripts/redeploy-fleetd.sh +++ b/scripts/redeploy-fleetd.sh @@ -615,8 +615,9 @@ if [ -n "$OLD_PID" ] && [ "$ASSUME_YES" = 0 ]; then # than before this run started, even though the running daemon itself was never touched. if [ "$DO_BUILD" = 1 ] && [ -f "$JAR_STAGED" ]; then die "aborted — the running daemon was NOT touched, but the freshly built jar is sitting at - $JAR_STAGED, not yet swapped into $JAR. Rerun (with or without --no-build) to finish the - restart, or remove $JAR_STAGED by hand if you want to discard this build." + $JAR_STAGED, not yet swapped into $JAR. Rerun WITHOUT --no-build to finish the restart — + the freshly built jar is no longer at the live path that --no-build requires — or + remove $JAR_STAGED by hand if you want to discard this build." fi die "aborted — nothing changed" fi diff --git a/scripts/test-redeploy-fleetd.sh b/scripts/test-redeploy-fleetd.sh index 0fbc420..dff94bb 100755 --- a/scripts/test-redeploy-fleetd.sh +++ b/scripts/test-redeploy-fleetd.sh @@ -206,6 +206,28 @@ test_assert_single_daemon_rejects_two_pids() { printf '%s' "$output" | grep -qF '4343' || fail "refusal message does not list the pids it found" } +# fleetd #511 — jar_id()'s no-argument default was unpinned by any test: nothing proved it reports +# $JAR (the live path) rather than $JAR_STAGED. Both halves matter, so this pins both: the bare call +# must hash the live jar, and an explicit path argument must hash THAT file, not fall back to $JAR. +# Two files with different content, so a default pointed at the wrong one reports the wrong hash +# rather than accidentally matching. +test_jar_id_defaults_to_live_and_reports_explicit_path() { + local dir saved_jar="$JAR" saved_staged="$JAR_STAGED" + local live_hash staged_hash default_result explicit_result + dir="$TMP/jar-id"; mkdir -p "$dir" + JAR="$dir/fleetd.jar"; JAR_STAGED="$dir/fleetd-new.jar" + printf 'live jar bytes' > "$JAR" + printf 'staged jar bytes, not the same content' > "$JAR_STAGED" + live_hash="$(shasum -a 256 "$JAR" | cut -c1-12)" + staged_hash="$(shasum -a 256 "$JAR_STAGED" | cut -c1-12)" + default_result="$(jar_id)" + explicit_result="$(jar_id "$JAR_STAGED")" + JAR="$saved_jar"; JAR_STAGED="$saved_staged" + [ "$live_hash" != "$staged_hash" ] || fail "test fixture error: live and staged jars hashed the same" + assert_equals "$live_hash" "$default_result" "jar_id with no arguments must report the hash of \$JAR" + assert_equals "$staged_hash" "$explicit_result" "jar_id \"\$JAR_STAGED\" must report the hash of the staged jar, not fall back to \$JAR" +} + # fleetd #493 — never build into the path a running process holds. stage_built_jar/swap_staged_jar # are exercised directly against real files on disk (not stubs), because the whole point is file # behavior (does the content move, does the source disappear, does a failure leave both sides @@ -344,6 +366,26 @@ test_swap_ordered_after_wait_and_before_start() { || fail "swap_staged_jar (line $swap_line) is not before the start section (line $start_line)" } +# fleetd #511: the drain-gate abort message (fired when a build has staged a jar but the operator +# declines the drain confirmation) used to tell the operator to "Rerun (with or without --no-build)" +# to finish the restart. That is wrong — by the time this message can fire, stage_built_jar has +# already moved the jar off $JAR, so a rerun WITH --no-build hits require_no_build_jar's own refusal +# ("no jar at $JAR — run without --no-build"). Like test_swap_ordered_after_wait_and_before_start +# above, this code path is never reached by sourcing (the SOURCED guard stops before the main flow), +# so the only way to pin its exact wording is to read the source. +test_drain_gate_abort_message_says_no_no_build() { + local src="$ROOT/scripts/redeploy-fleetd.sh" msg + msg="$(grep -A3 -F 'aborted — the running daemon was NOT touched, but the freshly built jar is sitting at' "$src")" + [ -n "$msg" ] || fail "could not find the drain-gate staged-jar abort message in redeploy-fleetd.sh" + if printf '%s' "$msg" | grep -qF 'with or without --no-build'; then + fail "abort message still claims a rerun WITH --no-build can finish the restart" + fi + printf '%s' "$msg" | grep -qF 'WITHOUT --no-build' \ + || fail "abort message does not tell the operator to rerun without --no-build" + printf '%s' "$msg" | grep -qF 'no longer at the live path' \ + || fail "abort message does not say why --no-build cannot finish the restart" +} + test_no_errors() { cat > "$TMP/no-errors.log" <<'LOG' 2026-09-05 12:00:00 INFO fleetd listening @@ -555,6 +597,7 @@ test_require_drivable_supervisor_accepts_known_kinds test_count_daemon_pids test_assert_single_daemon_accepts_one_pid test_assert_single_daemon_rejects_two_pids +test_jar_id_defaults_to_live_and_reports_explicit_path test_stage_built_jar_moves_off_live_path test_stage_built_jar_dies_when_build_produced_nothing test_swap_staged_jar_moves_staged_onto_live @@ -565,6 +608,7 @@ test_require_no_build_jar_accepts_present_jar test_wait_for_daemon_exit_returns_true_once_pid_clears test_wait_for_daemon_exit_times_out_if_pid_never_clears test_swap_ordered_after_wait_and_before_start +test_drain_gate_abort_message_says_no_no_build test_no_errors test_recovery_patterns_match_source test_attributed_recovered_connection_error