aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/test-install.sh26
-rw-r--r--tests/unit/test_test_install.bats42
2 files changed, 68 insertions, 0 deletions
diff --git a/scripts/test-install.sh b/scripts/test-install.sh
index cbca9b3..7a7f991 100755
--- a/scripts/test-install.sh
+++ b/scripts/test-install.sh
@@ -587,6 +587,30 @@ ssh_cmd() {
-p "$SSH_PORT" root@localhost "$@" 2>/dev/null
}
+# Keep a failed attempt's install log under its own name. The retry loop
+# refetches the guest's newest /tmp/archangel-*.log after every failed
+# attempt, and the final *-install.log only ever holds the last one — so
+# the failure that triggered a retry used to be gone by the time anyone
+# read test-logs/ (2026-09-12: attempt 2's "Disk in use" was all that
+# survived of a pacstrap stall). Pure: takes the captured text, never
+# talks to the guest. An empty capture writes an empty file, so "attempt ran,
+# log was empty" stays distinguishable from "attempt never ran". Returns 1
+# on a write failure; the caller treats that as non-fatal.
+#
+# Usage: save_attempt_log <log_dir> <config_name> <attempt> <log_text>
+save_attempt_log() {
+ local log_dir="$1" config_name="$2" attempt="$3" log_text="$4"
+ local file="$log_dir/${config_name}-install-attempt${attempt}.log"
+ # 2>/dev/null goes before the output redirect so it also silences the
+ # redirect's own "Permission denied"; the caller prints its own warning.
+ if [[ -n "$log_text" ]]; then
+ printf '%s\n' "$log_text" 2>/dev/null > "$file" || return 1
+ else
+ : 2>/dev/null > "$file" || return 1
+ fi
+ return 0
+}
+
# Decide whether a failed install is a transient pacstrap/network flake
# (worth retrying) or a deterministic regression (fail fast). Returns 0
# only when the install log shows BOTH pacstrap's own base-install
@@ -1159,6 +1183,8 @@ run_test() {
# pacstrap's failure text survives. Read just the latest log —
# a retry leaves a second timestamped log behind.
install_log=$(ssh_cmd "cat \"\$(ls -t /tmp/archangel-*.log 2>/dev/null | head -1)\"" 2>/dev/null) || true
+ save_attempt_log "$LOG_DIR" "$config_name" "$attempt" "$install_log" \
+ || warn "Could not save attempt $attempt's install log to $LOG_DIR"
if [[ "$attempt" -lt 3 ]] && is_transient_install_failure "$install_log"; then
warn "Install attempt $attempt hit a transient pacstrap flake — retrying ($((attempt + 1))/3)"
continue
diff --git a/tests/unit/test_test_install.bats b/tests/unit/test_test_install.bats
index 52ea037..3fb7c19 100644
--- a/tests/unit/test_test_install.bats
+++ b/tests/unit/test_test_install.bats
@@ -15,6 +15,48 @@ setup() {
}
#############################
+# save_attempt_log
+#############################
+# The retry loop refetches the guest's newest /tmp/archangel-*.log on
+# every failed attempt, so a retried install used to keep only the last
+# attempt's log — the failure that triggered the retry was gone by the
+# time anyone read test-logs/. save_attempt_log keeps each one.
+
+# Normal: a failed attempt's log lands under its own attempt-numbered name.
+@test "save_attempt_log writes the attempt's log under an attempt-numbered name" {
+ local dir="$BATS_TEST_TMPDIR/logs"
+ mkdir -p "$dir"
+ run save_attempt_log "$dir" zfs-encrypt 1 $'line one\nline two'
+ [ "$status" -eq 0 ]
+ [ -f "$dir/zfs-encrypt-install-attempt1.log" ]
+ [ "$(cat "$dir/zfs-encrypt-install-attempt1.log")" = $'line one\nline two' ]
+}
+
+# Boundary: an empty capture still writes a file, so "attempt ran, log
+# was empty" stays distinguishable from "attempt never happened".
+@test "save_attempt_log writes an empty file for an empty capture" {
+ local dir="$BATS_TEST_TMPDIR/logs"
+ mkdir -p "$dir"
+ run save_attempt_log "$dir" mirror 2 ""
+ [ "$status" -eq 0 ]
+ [ -f "$dir/mirror-install-attempt2.log" ]
+ [ ! -s "$dir/mirror-install-attempt2.log" ]
+}
+
+# Error: an unwritable log dir fails the save without aborting the caller.
+@test "save_attempt_log returns non-zero when the log dir is unwritable" {
+ [ "$EUID" -ne 0 ] || skip "running as root"
+ local dir="$BATS_TEST_TMPDIR/logs"
+ mkdir -p "$dir"
+ chmod 000 "$dir"
+ run save_attempt_log "$dir" mirror 1 "content"
+ chmod 755 "$dir"
+ [ "$status" -eq 1 ]
+ [ -z "$output" ]
+ [ ! -f "$dir/mirror-install-attempt1.log" ]
+}
+
+#############################
# is_transient_install_failure
#############################