chore(release): stage v1.7.55-alpha

This commit is contained in:
Dorian
2026-05-13 15:09:22 -04:00
parent 3202b79e41
commit 835c525218
65 changed files with 2322 additions and 566 deletions
+53 -4
View File
@@ -10,8 +10,10 @@ required_containers=(
"bitcoin-knots"
"electrumx"
"lnd"
"archy-mempool-db"
"mempool-api"
"mempool"
"filebrowser"
"archy-bitcoin-ui"
"archy-lnd-ui"
"archy-electrs-ui"
@@ -26,6 +28,18 @@ container_running() {
podman inspect --format '{{.State.Running}}' "$name" 2>/dev/null
}
bitcoin_rpc() {
curl -fsS --max-time 60 \
--user "archipelago:$(cat /var/lib/archipelago/secrets/bitcoin-rpc-password)" \
--data-binary '{"jsonrpc":"1.0","id":"required-stack","method":"getblockchaininfo","params":[]}' \
-H 'content-type: text/plain;' \
http://127.0.0.1:8332/
}
bitcoin_json() {
python3 -c 'import json,sys; r=json.load(sys.stdin)["result"]; print(r[sys.argv[1]])' "$1"
}
@test "required containers are present" {
local names
names="$(podman_names)"
@@ -43,9 +57,29 @@ container_running() {
}
@test "bitcoin-knots RPC responds" {
run sh -lc 'podman exec bitcoin-knots bitcoin-cli -rpcuser=archipelago -rpcpassword="$(cat /var/lib/archipelago/secrets/bitcoin-rpc-password)" getblockchaininfo'
run bitcoin_rpc
[ "$status" -eq 0 ]
echo "$output" | jq -e '.chain == "main" and (.blocks >= 0)' >/dev/null
echo "$output" | python3 -c 'import json,sys; r=json.load(sys.stdin)["result"]; assert r["chain"] == "main" and r["blocks"] >= 0'
}
@test "bitcoin backend is synced archival for electrumx/lnd gate" {
run bitcoin_rpc
[ "$status" -eq 0 ]
local pruned ibd blocks headers
pruned="$(echo "$output" | bitcoin_json pruned)"
ibd="$(echo "$output" | bitcoin_json initialblockdownload)"
blocks="$(echo "$output" | bitcoin_json blocks)"
headers="$(echo "$output" | bitcoin_json headers)"
if [ "$pruned" = "True" ] || [ "$pruned" = "true" ]; then
echo "bitcoin is pruned (blocks=$blocks headers=$headers); electrumx cannot index pruned historical blocks"
return 1
fi
if [ "$ibd" = "True" ] || [ "$ibd" = "true" ]; then
echo "bitcoin is still in initial block download (blocks=$blocks headers=$headers)"
return 1
fi
}
@test "electrumx TCP port accepts connections" {
@@ -59,7 +93,17 @@ PY
}
@test "lnd CLI getinfo succeeds" {
run sh -lc 'podman exec lnd lncli --tlscertpath /root/.lnd/tls.cert --macaroonpath /root/.lnd/data/chain/bitcoin/mainnet/readonly.macaroon --rpcserver localhost:10009 getinfo >/dev/null'
run sh -lc 'timeout 60 podman exec lnd lncli --tlscertpath /root/.lnd/tls.cert --macaroonpath /root/.lnd/data/chain/bitcoin/mainnet/readonly.macaroon --rpcserver localhost:10009 getinfo >/dev/null'
[ "$status" -eq 0 ]
}
@test "lnd REST port accepts connections" {
run python3 - <<'PY'
import socket
s = socket.create_connection(("127.0.0.1", 18080), 3)
s.close()
print("ok")
PY
[ "$status" -eq 0 ]
}
@@ -79,6 +123,11 @@ PY
}
@test "lnd ui responds" {
run curl -fsS "http://127.0.0.1:8081/"
run curl -fsS "http://127.0.0.1:18083/"
[ "$status" -eq 0 ]
}
@test "filebrowser responds" {
run curl -fsS "http://127.0.0.1:8083/"
[ "$status" -eq 0 ]
}
+100 -7
View File
@@ -20,6 +20,8 @@ ARCHY_APPS="${ARCHY_APPS:-}"
ARCHY_TIMEOUT="${ARCHY_TIMEOUT:-900}"
ARCHY_STABILITY_SECONDS="${ARCHY_STABILITY_SECONDS:-5}"
ARCHY_ALLOW_BITCOIN_SWAP="${ARCHY_ALLOW_BITCOIN_SWAP:-0}"
ARCHY_APP_CATALOG="${ARCHY_APP_CATALOG:-}"
ARCHY_PRUNED_NODE="${ARCHY_PRUNED_NODE:-auto}"
if [[ -z "$ARCHY_HOST" || -z "$ARCHY_PASSWORD" ]]; then
echo "ARCHY_HOST and ARCHY_PASSWORD are required" >&2
@@ -37,6 +39,7 @@ fi
BASE_URL="${ARCHY_SCHEME}://${ARCHY_HOST}"
SESSION=""
CSRF=""
CATALOG_FILE=""
ALL_APPS=(
bitcoin-knots
@@ -65,6 +68,69 @@ ALL_APPS=(
gitea
)
ARCHIVAL_ONLY_APPS=(
electrumx
mempool
)
app_in_list() {
local needle="$1"
shift
local item
for item in "$@"; do
[[ "$item" == "$needle" ]] && return 0
done
return 1
}
fetch_catalog() {
CATALOG_FILE=$(mktemp)
if [[ -n "$ARCHY_APP_CATALOG" ]]; then
cp "$ARCHY_APP_CATALOG" "$CATALOG_FILE"
return 0
fi
if curl -skfL --connect-timeout 8 -m 30 "${BASE_URL}/api/app-catalog" -o "$CATALOG_FILE" \
&& jq -e '.apps | length > 0' "$CATALOG_FILE" >/dev/null; then
return 0
fi
curl -skfL --connect-timeout 8 -m 30 "${BASE_URL}/catalog.json" -o "$CATALOG_FILE"
jq -e '.apps | length > 0' "$CATALOG_FILE" >/dev/null
}
catalog_app_ids() {
jq -r '.apps[] | select((.dockerImage // "") != "") | .id' "$CATALOG_FILE"
}
catalog_app_json() {
local app="$1"
[[ -n "$CATALOG_FILE" && -r "$CATALOG_FILE" ]] || return 1
jq -c --arg app "$app" '
.registry as $registry
| .apps[]
| select(.id == $app)
| .dockerImage = (if ((.dockerImage // "") | contains("/")) then .dockerImage else ($registry + "/" + .dockerImage) end)
' "$CATALOG_FILE" | head -n 1
}
is_pruned_node() {
case "$ARCHY_PRUNED_NODE" in
1|true|yes) return 0 ;;
0|false|no) return 1 ;;
esac
local pass body
pass=$(ssh "${ARCHY_HOST}" 'sudo cat /var/lib/archipelago/secrets/bitcoin-rpc-password 2>/dev/null || cat /var/lib/archipelago/secrets/bitcoin-rpc-password 2>/dev/null' 2>/dev/null || true)
[[ -n "$pass" ]] || return 1
body=$(curl -fsS --max-time 20 \
--user "archipelago:${pass}" \
--data-binary '{"jsonrpc":"1.0","id":"remote-lifecycle","method":"getblockchaininfo","params":[]}' \
-H 'content-type: text/plain;' \
"http://${ARCHY_HOST}:8332/" 2>/dev/null || true)
printf '%s' "$body" | jq -e '.result.pruned == true' >/dev/null 2>&1
}
image_for() {
case "$1" in
bitcoin-knots) echo "146.59.87.168:3000/lfg2025/bitcoin-knots:latest" ;;
@@ -341,7 +407,7 @@ probe_lnd_wallet_connect() {
(.cert_base64url | type == "string" and length > 100) and
(.macaroon_base64url | type == "string" and length > 50) and
(.tor_onion | type == "string" and test("^[a-z2-7]+\\.onion$")) and
(.rest_port == 8080) and
(.rest_port == 18080) and
(.grpc_port == 10009)
' >/dev/null || {
echo "lnd connect info incomplete: $info" >&2
@@ -371,12 +437,29 @@ probe_electrum_wallet_connect() {
}
install_app() {
local app="$1" image params
image=$(image_for "$app")
params=$(jq -nc --arg id "$app" --arg img "$image" '{id:$id,dockerImage:$img,version:"latest"}')
local app="$1" app_json image params
app_json=$(catalog_app_json "$app" || true)
if [[ -n "$app_json" ]]; then
params=$(printf '%s' "$app_json" | jq -c '{id, dockerImage, version, containerConfig} | with_entries(select(.value != null))')
else
image=$(image_for "$app")
params=$(jq -nc --arg id "$app" --arg img "$image" '{id:$id,dockerImage:$img,version:"latest"}')
fi
rpc_result package.install "$params" >/dev/null
}
expect_archival_blocked_install() {
local app="$1" app_json resp err params
app_json=$(catalog_app_json "$app")
params=$(printf '%s' "$app_json" | jq -c '{id, dockerImage, version, containerConfig} | with_entries(select(.value != null))')
resp=$(rpc_call package.install "$params")
err=$(printf '%s' "$resp" | jq -r '.error.message // empty')
if [[ "$err" != *"Requires an archival Bitcoin node"* && "$err" != *"requires an archival Bitcoin node"* && "$err" != *"running pruned Bitcoin"* ]]; then
echo "expected archival Bitcoin block for $app, got: $resp" >&2
return 1
fi
}
start_app() { rpc_result package.start "$(jq -nc --arg id "$1" '{id:$id}')" >/dev/null; }
stop_app() { rpc_result package.stop "$(jq -nc --arg id "$1" '{id:$id}')" >/dev/null; }
restart_app() { rpc_result package.restart "$(jq -nc --arg id "$1" '{id:$id}')" >/dev/null; }
@@ -405,6 +488,11 @@ full_lifecycle_app() {
echo "skip bitcoin-core: set ARCHY_ALLOW_BITCOIN_SWAP=1 to test mutually-exclusive Bitcoin implementation"
return 0
fi
if app_in_list "$app" "${ARCHIVAL_ONLY_APPS[@]}" && is_pruned_node; then
echo "== $app: expect archival Bitcoin block =="
expect_archival_blocked_install "$app"
return $?
fi
echo "== $app: install =="
install_app "$app" || return 1
wait_not_installing "$app" || return 1
@@ -451,11 +539,16 @@ full_lifecycle_app() {
apps=()
if [[ -n "$ARCHY_APPS" ]]; then
IFS=',' read -r -a apps <<< "$ARCHY_APPS"
fetch_catalog || true
elif [[ "$ARCHY_FULL_LIFECYCLE" == "1" ]]; then
echo "ARCHY_FULL_LIFECYCLE=1 requires ARCHY_APPS to avoid installing unqualified catalog apps" >&2
exit 2
fetch_catalog
mapfile -t apps < <(catalog_app_ids)
else
apps=("${ALL_APPS[@]}")
if fetch_catalog; then
mapfile -t apps < <(catalog_app_ids)
else
apps=("${ALL_APPS[@]}")
fi
fi
rpc_login