Test: Propagate update fixture failures

This commit is contained in:
Gabriel Brown
2026-08-26 22:53:39 -04:00
parent 803362ebad
commit 68b6664111
+61 -30
View File
@@ -121,7 +121,10 @@ run_install() {
# ── 1. The interview never runs on an upgrade ──────────────────────────────── # ── 1. The interview never runs on an upgrade ────────────────────────────────
build_fixture "$tmp/a" build_fixture "$tmp/a"
ran="$(run_install "$tmp/a" --upgrade)" install_status=0
ran="$(run_install "$tmp/a" --upgrade)" || install_status=$?
[[ "$install_status" -eq 0 ]] \
|| note "initial install --upgrade failed with status $install_status"
if grep -qx 'interview' <<<"$ran"; then if grep -qx 'interview' <<<"$ran"; then
note 'install --upgrade ran the interview, which is the whole regression this prevents' note 'install --upgrade ran the interview, which is the whole regression this prevents'
@@ -129,7 +132,10 @@ fi
# And the control: a real install must still ask. # And the control: a real install must still ask.
build_fixture "$tmp/b" build_fixture "$tmp/b"
ran_install="$(run_install "$tmp/b")" install_status=0
ran_install="$(run_install "$tmp/b")" || install_status=$?
[[ "$install_status" -eq 0 ]] \
|| note "plain fixture install failed with status $install_status"
if ! grep -qx 'interview' <<<"$ran_install"; then if ! grep -qx 'interview' <<<"$ran_install"; then
note 'a plain ./install no longer asks the interview, so a new machine is never configured' note 'a plain ./install no longer asks the interview, so a new machine is never configured'
fi fi
@@ -176,18 +182,27 @@ done
# ── 3. The packages hash gates the stage, and a failure does not record it ─── # ── 3. The packages hash gates the stage, and a failure does not record it ───
# Second run, nothing changed: the stage must be skipped. # Second run, nothing changed: the stage must be skipped.
ran_again="$(run_install "$tmp/a" --upgrade)" install_status=0
ran_again="$(run_install "$tmp/a" --upgrade)" || install_status=$?
[[ "$install_status" -eq 0 ]] \
|| note "repeat install --upgrade failed with status $install_status"
grep -qx 'install-packages' <<<"$ran_again" \ grep -qx 'install-packages' <<<"$ran_again" \
&& note 'install-packages ran again with the package lists unchanged' && note 'install-packages ran again with the package lists unchanged'
# --packages overrides the hash. # --packages overrides the hash.
ran_forced="$(run_install "$tmp/a" --upgrade --packages)" install_status=0
ran_forced="$(run_install "$tmp/a" --upgrade --packages)" || install_status=$?
[[ "$install_status" -eq 0 ]] \
|| note "install --upgrade --packages failed with status $install_status"
grep -qx 'install-packages' <<<"$ran_forced" \ grep -qx 'install-packages' <<<"$ran_forced" \
|| note '--packages did not force install-packages to run' || note '--packages did not force install-packages to run'
# A changed list brings the stage back. # A changed list brings the stage back.
printf 'another-package\n' >>"$tmp/a/setup/packages/base" printf 'another-package\n' >>"$tmp/a/setup/packages/base"
ran_changed="$(run_install "$tmp/a" --upgrade)" install_status=0
ran_changed="$(run_install "$tmp/a" --upgrade)" || install_status=$?
[[ "$install_status" -eq 0 ]] \
|| note "install --upgrade failed after a package-list change with status $install_status"
grep -qx 'install-packages' <<<"$ran_changed" \ grep -qx 'install-packages' <<<"$ran_changed" \
|| note 'a changed package list did not bring install-packages back' || note 'a changed package list did not bring install-packages back'
@@ -203,8 +218,14 @@ fi
# A full install always runs the stage, whatever any recorded hash says. # A full install always runs the stage, whatever any recorded hash says.
build_fixture "$tmp/d" build_fixture "$tmp/d"
run_install "$tmp/d" --upgrade >/dev/null install_status=0
ran_full="$(run_install "$tmp/d")" run_install "$tmp/d" --upgrade >/dev/null || install_status=$?
[[ "$install_status" -eq 0 ]] \
|| note "hash-seeding install --upgrade failed with status $install_status"
install_status=0
ran_full="$(run_install "$tmp/d")" || install_status=$?
[[ "$install_status" -eq 0 ]] \
|| note "full fixture reinstall failed with status $install_status"
grep -qx 'install-packages' <<<"$ran_full" \ grep -qx 'install-packages' <<<"$ran_full" \
|| note 'a full ./install skipped install-packages because of a recorded hash' || note 'a full ./install skipped install-packages because of a recorded hash'
@@ -216,42 +237,52 @@ grep -qx 'install-packages' <<<"$ran_full" \
# Each fixture has the same three repositories as a real update: a bare remote, # Each fixture has the same three repositories as a real update: a bare remote,
# a clone that publishes upstream changes, and the machine clone being updated. # a clone that publishes upstream changes, and the machine clone being updated.
build_cli_fixture() ( build_cli_fixture() (
set -e
local root="$1" local root="$1"
rm -rf "$root" rm -rf "$root" || return 1
mkdir -p "$root" mkdir -p "$root" || return 1
git init -q --bare "$root/origin.git" git init -q --bare "$root/origin.git" || return 1
git clone -q "$root/origin.git" "$root/upstream" 2>/dev/null git clone -q "$root/origin.git" "$root/upstream" 2>/dev/null || return 1
git -C "$root/upstream" config user.email contract@panama git -C "$root/upstream" config user.email contract@panama || return 1
git -C "$root/upstream" config user.name contract git -C "$root/upstream" config user.name contract || return 1
mkdir -p "$root/upstream/bin" mkdir -p "$root/upstream/bin" || return 1
cp "$panama" "$root/upstream/bin/panama" cp "$panama" "$root/upstream/bin/panama" || return 1
cat >"$root/upstream/install" <<'EOF' cat >"$root/upstream/install" <<'EOF' || return 1
#!/usr/bin/env bash #!/usr/bin/env bash
printf '%s\n' "$*" >>"${PANAMA_UPDATE_FIXTURE_LOG:?}" printf '%s\n' "$*" >>"${PANAMA_UPDATE_FIXTURE_LOG:?}"
exit "${PANAMA_UPDATE_INSTALL_RC:-0}" exit "${PANAMA_UPDATE_INSTALL_RC:-0}"
EOF EOF
chmod +x "$root/upstream/bin/panama" "$root/upstream/install" chmod +x "$root/upstream/bin/panama" "$root/upstream/install" || return 1
printf 'one\n' >"$root/upstream/f" printf 'one\n' >"$root/upstream/f" || return 1
git -C "$root/upstream" add -A git -C "$root/upstream" add -A || return 1
git -C "$root/upstream" commit -qm initial git -C "$root/upstream" commit -qm initial || return 1
git -C "$root/upstream" push -qu origin HEAD git -C "$root/upstream" push -qu origin HEAD || return 1
git clone -q "$root/origin.git" "$root/machine" git clone -q "$root/origin.git" "$root/machine" || return 1
git -C "$root/machine" config user.email contract@panama git -C "$root/machine" config user.email contract@panama || return 1
git -C "$root/machine" config user.name contract git -C "$root/machine" config user.name contract || return 1
) )
advance_upstream() ( advance_upstream() (
set -e
local root="$1" file="$2" contents="$3" local root="$1" file="$2" contents="$3"
printf '%s\n' "$contents" >"$root/upstream/$file" printf '%s\n' "$contents" >"$root/upstream/$file" || return 1
git -C "$root/upstream" add "$file" git -C "$root/upstream" add "$file" || return 1
git -C "$root/upstream" commit -qm "update $file" git -C "$root/upstream" commit -qm "update $file" || return 1
git -C "$root/upstream" push -q git -C "$root/upstream" push -q || return 1
) )
# This write fails before the later Git commands. The helper must return that
# failure rather than let a final successful push hide it.
helper_probe="$tmp/helper-failure"
if build_cli_fixture "$helper_probe"; then
if advance_upstream "$helper_probe" missing/child probe \
2>"$helper_probe/intermediate-failure.err"; then
note 'advance_upstream hid an intermediate fixture setup failure'
fi
else
note 'the fixture helper failure probe could not be built'
fi
clean="$tmp/clean-update" clean="$tmp/clean-update"
if build_cli_fixture "$clean" && advance_upstream "$clean" release new; then if build_cli_fixture "$clean" && advance_upstream "$clean" release new; then
machine_before="$(git -C "$clean/machine" rev-parse HEAD)" machine_before="$(git -C "$clean/machine" rev-parse HEAD)"