Files
archy/tests/cloud/run-immich-disposable.sh
T

117 lines
6.2 KiB
Bash

#!/usr/bin/env bash
# Actual Immich API fixture only. Never installed-node or Rust/browser acceptance.
set -euo pipefail
repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
server=${ARCHY_CLOUD_IMMICH_IMAGE:?Immutable Immich 2.7.4 image required}
db=${ARCHY_CLOUD_IMMICH_DB_IMAGE:?Immutable compatible Postgres image required}
redis=${ARCHY_CLOUD_IMMICH_REDIS_IMAGE:?Immutable Redis image required}
if [[ ${ARCHY_CLOUD_BROWSER_QUALIFY:-0} == 1 ]]; then
: "${ARCHY_TEST_REUSE_ARTIFACT:?Compile and bind the artifact before starting Immich}"
: "${ARCHY_TEST_CLOUD_RUNTIME_IMAGE:?Exact browser runtime required}"
fi
for image in "$server" "$db" "$redis"; do
[[ "$image" =~ ^(sha256:)?[a-f0-9]{64}$ ]] || { echo 'Full immutable image IDs required' >&2; exit 2; }
podman image exists "$image"
done
work=$(mktemp -d /tmp/archy-immich.XXXXXXXX)
name="archy-cloud-immich-${work##*.}"
containers=()
cleanup() {
result=$?
trap - EXIT
for ((i=${#containers[@]}-1; i>=0; i--)); do
c=${containers[$i]}
if ! podman container exists "$c"; then continue; fi
if [[ "$result" != 0 ]]; then
timeout 5 podman inspect "$c" --format '{{json .State}}' || true
timeout 5 podman exec "$c" /bin/sh -c 'grep . /sys/fs/cgroup/memory.events /sys/fs/cgroup/memory.peak /sys/fs/cgroup/memory.max /sys/fs/cgroup/memory.swap.max' || true
timeout 5 podman logs --tail 200 "$c" 2>&1 || true
fi
timeout --kill-after=2s 20 podman rm -f --volumes --time 0 "$c" >/dev/null 2>&1 || true
if podman container exists "$c"; then echo "Cleanup failed: $c" >&2; result=1; fi
done
rm -rf -- "$work"
exit "$result"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
: > "$work/resolv.conf"
# No host inventory; upstream workers still need standard loopback resolution.
printf '127.0.0.1 localhost\n::1 localhost\n' > "$work/hosts"
common=(--pull=never --image-volume=ignore --read-only --pid=private --ipc=private --http-proxy=false
--no-hosts --cap-drop=all --security-opt=no-new-privileges --cpus=1
--pids-limit=128 --timeout=420 --log-driver=k8s-file --log-opt=max-size=4mb
--label org.archipelago.cloud-fixture=immich274-v1
--volume "$work/resolv.conf:/etc/resolv.conf:ro"
--volume "$work/hosts:/etc/hosts:ro"
--tmpfs /tmp:rw,notmpcopyup,nosuid,nodev,size=64m)
# The database owns a network-none namespace; no infra image or published ports.
containers+=("$name-db")
podman run -d --name "$name-db" "${common[@]}" --network=none \
--memory=1g --memory-swap=1g --cap-add=chown,dac_override,fowner,setuid,setgid \
--tmpfs /var/lib/postgresql/data:rw,nosuid,nodev,size=768m \
--tmpfs /run/postgresql:rw,nosuid,nodev,size=16m \
--tmpfs /etc/postgresql:rw,nosuid,nodev,size=8m \
--env POSTGRES_PASSWORD=Synthetic-Immich-DB-Only-2026! \
--env POSTGRES_USER=postgres --env POSTGRES_DB=immich "$db" >/dev/null
common+=(--network="container:$name-db")
containers+=("$name-redis")
podman run -d --name "$name-redis" "${common[@]}" --memory=128m --memory-swap=128m \
--cap-add=chown,setuid,setgid --tmpfs /data:rw,nosuid,nodev,size=64m \
"$redis" redis-server --save '' --appendonly no >/dev/null
ready=0
for _ in $(seq 1 60); do
if timeout --kill-after=2s 3 podman exec "$name-db" pg_isready -U postgres -d immich >/dev/null 2>&1; then ready=1; break; fi
sleep 1
done
[[ "$ready" == 1 ]] || { echo 'Database readiness failed' >&2; exit 1; }
containers+=("$name-server")
podman run -d --name "$name-server" "${common[@]}" --cpus=2 \
--memory=2g --memory-swap=2g --pids-limit=256 \
--tmpfs /usr/src/app/upload:rw,nosuid,nodev,size=256m \
--env DB_HOSTNAME=127.0.0.1 --env DB_USERNAME=postgres --env DB_DATABASE_NAME=immich \
--env DB_PASSWORD=Synthetic-Immich-DB-Only-2026! --env REDIS_HOSTNAME=127.0.0.1 \
--env UPLOAD_LOCATION=/usr/src/app/upload --env IMMICH_MACHINE_LEARNING_ENABLED=false \
--volume "$repo/tests/cloud/immich-upstream-contract.mjs:/contract.mjs:ro" \
--volume "$repo/tests/cloud/immich-fixture.png:/fixture.png:ro" "$server" >/dev/null
ready=0
for _ in $(seq 1 90); do
if timeout --kill-after=2s 3 podman exec "$name-server" node -e \
'fetch("http://127.0.0.1:2283/api/server/ping",{signal:AbortSignal.timeout(1500)}).then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))' >/dev/null 2>&1; then ready=1; break; fi
sleep 2
done
[[ "$ready" == 1 ]] || { echo 'Immich readiness failed' >&2; exit 1; }
# /server/ping is ready before the separate worker finishes its fresh geodata
# import. Do not spend the thumbnail assertion's budget waiting for bootstrap.
ready=0
for _ in $(seq 1 90); do
logs=$(timeout --kill-after=2s 10 podman logs --tail 80 "$name-server" 2>&1) || { echo 'Worker log readiness probe timed out' >&2; continue; }
if [[ "$logs" == *'Immich Microservices is running'* ]]; then ready=1; break; fi
sleep 2
done
[[ "$ready" == 1 ]] || { echo 'Immich worker readiness failed' >&2; exit 1; }
podman inspect "$name-db" "$name-redis" "$name-server" |
python3 "$repo/scripts/validate-immich-test-fixture.py" "$name" "$db" "$redis" "$server" >/dev/null
if [[ ${ARCHY_CLOUD_BROWSER_QUALIFY:-0} == 1 ]]; then
: "${ARCHY_TEST_REUSE_ARTIFACT:?Compile and bind the artifact before starting Immich}"
: "${ARCHY_TEST_CLOUD_RUNTIME_IMAGE:?Exact browser runtime required}"
run_bound_tests() {
ARCHY_TEST_ISOLATOR=podman ARCHY_TEST_CLOUD_UPSTREAM=immich274 \
ARCHY_TEST_CLOUD_FIXTURE_CONTAINER="$name-db" ARCHY_TEST_CLOUD_FIXTURE_IMAGE="$db" \
ARCHY_TEST_IMMICH_SERVER_IMAGE="$server" ARCHY_TEST_IMMICH_REDIS_IMAGE="$redis" \
bash "$repo/scripts/test-backend-isolated.sh" "$@"
}
# Matching focused source tests and actual browser share one retained binary.
# Ignored real-Nextcloud tests are not selected by the normal unit filter.
run_bound_tests cloud_sources:: --nocapture
run_bound_tests --ignored --exact api::handler::cloud_browser_tests::immich_browser_rpc_without_filebrowser --nocapture
else
timeout --kill-after=5s 120 podman exec "$name-server" node /contract.mjs
fi
if [[ ${ARCHY_CLOUD_BROWSER_QUALIFY:-0} == 1 ]]; then
echo 'PASS isolated Immich source and production browser/RPC batch; synthetic session/runtime binding, not installed lifecycle or native identity acceptance.'
else
echo 'PASS portable isolated Immich protocol; not Rust/browser, installed lifecycle or native identity acceptance.'
fi