chore: release v1.7.46-alpha

Follow-up to v1.7.45-alpha closing the remaining tasks identified by the
resilience sweeps + the new bitcoin orphan / install-fail-vanish bugs.

User-visible:
- Health monitor: stop paging on orphaned containers from variant switches
- Install fail: card stays visible (was vanishing) with error message
- Stack pull progress: interpolate 20→70% (was stuck at 20%)
- docker.io → lfg2025 mirror: bitcoin/gitea/nextcloud/valkey

Internal:
- Resilience harness — install-wait uses expected_containers_for, ui+auth
  probes retry with 60s backoff, dep-snapshot fix
- InstallProgress gains optional `message` field (frontend renders it
  when phase is None)

binary  $(stat -c %s releases/v1.7.46-alpha/archipelago)  sha256:$(sha256sum releases/v1.7.46-alpha/archipelago | awk '{print $1}')
tarball $(stat -c %s releases/v1.7.46-alpha/archipelago-frontend-1.7.46-alpha.tar.gz)  sha256:$(sha256sum releases/v1.7.46-alpha/archipelago-frontend-1.7.46-alpha.tar.gz | awk '{print $1}')

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-04-29 14:50:33 -04:00
parent 4ec6ca98c1
commit 992b673b20
14 changed files with 137 additions and 27 deletions

View File

@@ -129,19 +129,34 @@ snapshot_containers() {
ssh_run "podman ps -a --format '{{.Names}}' | sort"
}
# Whether $app currently has any of its expected containers running. Uses
# Whether $app currently has ALL of its expected containers running. Uses
# the per-app metadata table in lib.sh (expected_containers_for) so variant
# apps (bitcoin-knots/bitcoin-core sharing slots) and stacks are detected
# correctly. Falls back to name-prefix match for apps the table doesn't know.
#
# Returns true only when every expected container is present. Earlier
# versions returned true on ANY match — that caused dep installs (e.g.
# bitcoin-knots required by btcpay) to be declared "installed" as soon as
# the backend container appeared, before the UI companion (archy-bitcoin-ui)
# was up. The before-snapshot then missed the companion, the after-snapshot
# caught it, and it leaked into the dependent app's "new containers" set,
# false-positive-FAILing stop/uninstall when the companion (correctly) did
# not respond to the dependent app's package.stop.
app_already_installed() {
local app="$1"
local snap; snap=$(snapshot_containers)
local expected
expected=$(expected_containers_for "$app")
local c
for c in $expected; do
echo "$snap" | grep -qxF "$c" && return 0
done
if [ -n "$expected" ] && [ "$expected" != "$app" ]; then
local c missing=0
for c in $expected; do
echo "$snap" | grep -qxF "$c" || missing=1
done
[ "$missing" -eq 0 ] && return 0
# Fall through to prefix match if the expected_containers list has
# gaps; a partial install still counts as "installed enough" for
# preclean purposes.
fi
# Generic prefix fallback for apps not in the expected_containers_for table.
echo "$snap" | grep -qE "^(${app}|${app}-|archy-${app}|archy-${app}-)"
}
@@ -291,8 +306,18 @@ run_app_matrix() {
fi
# ── 02 ui_probe ──────────────────────────────────────────────
# Retry with backoff — install just finished, but the app's backend
# (fedimint, immich, mempool stack) may take 30+s to be ready to serve
# HTTP. Probing immediately false-positive-FAILed those apps; pass on
# first 2xx/3xx within 60s.
local code
code=$(probe_app_proxy "$app")
local ui_deadline=$(($(date +%s) + 60))
while :; do
code=$(probe_app_proxy "$app")
[[ "$code" =~ ^(2[0-9][0-9]|3[0-9][0-9])$ ]] && break
[ "$(date +%s)" -ge "$ui_deadline" ] && break
sleep 5
done
# Accept all 2xx/3xx — proxy reaches backend, app may redirect to login,
# serve OAuth flow (307), or use 308 permanent. 401/403 still fail because
# those mean "backend reached, app rejected request" which is the
@@ -300,17 +325,27 @@ run_app_matrix() {
if [[ "$code" =~ ^(2[0-9][0-9]|3[0-9][0-9])$ ]]; then
record "$app" ui_probe PASS "HTTP $code"
else
record "$app" ui_probe FAIL "HTTP $code (expected 2xx/3xx)"
record "$app" ui_probe FAIL "HTTP $code (expected 2xx/3xx, retried 60s)"
fi
# ── 03 auth_probe (only for apps with a credentialed/data endpoint) ──
# Same backoff treatment: bitcoin-ui's nginx config bind-mount is
# picked up at start, but the bitcoin-core backend may not have
# accepted RPC connections yet on a fresh install.
local probe_code; local pass_codes
pass_codes=$(auth_probe_pass_codes "$app")
if probe_code=$(auth_probe_for "$app" 2>/dev/null) && [ -n "$probe_code" ]; then
pass_codes=$(auth_probe_pass_codes "$app")
local auth_deadline=$(($(date +%s) + 60))
while :; do
echo " $pass_codes " | grep -qF " $probe_code " && break
[ "$(date +%s)" -ge "$auth_deadline" ] && break
sleep 5
probe_code=$(auth_probe_for "$app" 2>/dev/null) || break
done
if echo " $pass_codes " | grep -qF " $probe_code "; then
record "$app" auth_probe PASS "HTTP $probe_code"
else
record "$app" auth_probe FAIL "HTTP $probe_code (expected one of: $pass_codes — credential plumbing broken)"
record "$app" auth_probe FAIL "HTTP $probe_code (expected one of: $pass_codes; retried 60s — credential plumbing broken)"
fi
else
record "$app" auth_probe SKIP "no authenticated probe defined"