#!/usr/bin/env bats # tests/lifecycle/bats/immich.bats # # Lifecycle tests for the immich stack (manifest-driven: immich + immich-postgres # + immich-redis, installed via the orchestrator — NOT the legacy install_immich_stack). # # Tiers: # - Read-only (always): presence + valid state of all 3 members # - Destructive (ARCHY_ALLOW_DESTRUCTIVE=1): stop → start → restart the server # - Cascade (ARCHY_ALLOW_CASCADE_DESTRUCTIVE=1): uninstall → reinstall the stack # (preserve_data so the photo library + DB survive) # # All checks are RPC-based so the suite is correct whether run on the host or # against a remote ARCHY_HOST. load '../lib/rpc.bash' IMMICH_IMAGE="146.59.87.168:3000/lfg2025/immich-server:release" setup_file() { : "${ARCHY_PASSWORD:?Set ARCHY_PASSWORD env var to the UI password}" export ARCHY_FORCE_LOGIN=1 rpc_login unset ARCHY_FORCE_LOGIN } teardown_file() { rpc_logout_local } container_state() { rpc_result container-list | jq -r --arg n "$1" '.[] | select(.name == $n) | .state' } # ──────────────────────────────────────────────────────────────────── # Read-only tier # ──────────────────────────────────────────────────────────────────── @test "container-list includes the immich stack members" { run rpc_result container-list [ "$status" -eq 0 ] echo "$output" | jq -e '.[] | select(.name == "immich")' >/dev/null echo "$output" | jq -e '.[] | select(.name == "immich-postgres")' >/dev/null echo "$output" | jq -e '.[] | select(.name == "immich-redis")' >/dev/null } @test "immich stack members report valid states" { for c in immich immich-postgres immich-redis; do local state state=$(container_state "$c") [[ "$state" =~ ^(running|stopped|exited|created|paused)$ ]] || { echo "unexpected state for $c: $state"; return 1 } done } @test "no legacy underscore immich containers (immich_postgres/_redis/_server)" { # The legacy install_immich_stack named members with underscores. The # manifest-driven stack uses hyphenated app_id names. Underscore containers # mean a botched migration (or a fallback to the legacy installer). run rpc_result container-list [ "$status" -eq 0 ] echo "$output" | jq -e '[.[] | select(.name | test("^immich_"))] | length == 0' >/dev/null } # ──────────────────────────────────────────────────────────────────── # Destructive tier (stop → start → restart the server) # ──────────────────────────────────────────────────────────────────── @test "package.stop transitions immich to stopped" { [[ "${ARCHY_ALLOW_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_DESTRUCTIVE not set" run rpc_result package.stop '{"id":"immich"}' [ "$status" -eq 0 ] run wait_for_container_status immich stopped 60 [ "$status" -eq 0 ] } @test "package.start brings immich back to running" { [[ "${ARCHY_ALLOW_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_DESTRUCTIVE not set" run rpc_result package.start '{"id":"immich"}' [ "$status" -eq 0 ] run wait_for_container_status immich running 120 [ "$status" -eq 0 ] } @test "package.restart leaves immich in running state" { [[ "${ARCHY_ALLOW_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_DESTRUCTIVE not set" run rpc_result package.restart '{"id":"immich"}' [ "$status" -eq 0 ] run wait_for_container_status immich running 120 [ "$status" -eq 0 ] } @test "postgres + redis stay running across an immich server restart" { [[ "${ARCHY_ALLOW_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_DESTRUCTIVE not set" [ "$(container_state immich-postgres)" == "running" ] [ "$(container_state immich-redis)" == "running" ] } # ──────────────────────────────────────────────────────────────────── # Cascade tier (uninstall + reinstall the stack) # ──────────────────────────────────────────────────────────────────── @test "package.uninstall removes the immich stack (data preserved)" { [[ "${ARCHY_ALLOW_CASCADE_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_CASCADE_DESTRUCTIVE not set" run rpc_result package.uninstall '{"id":"immich","preserve_data":true}' [ "$status" -eq 0 ] run wait_for_container_status immich absent 120 [ "$status" -eq 0 ] } @test "package.install immich brings the whole stack back to running" { [[ "${ARCHY_ALLOW_CASCADE_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_CASCADE_DESTRUCTIVE not set" run rpc_result package.install "{\"id\":\"immich\",\"dockerImage\":\"${IMMICH_IMAGE}\"}" [ "$status" -eq 0 ] run wait_for_container_status immich running 180 [ "$status" -eq 0 ] run wait_for_container_status immich-postgres running 120 [ "$status" -eq 0 ] run wait_for_container_status immich-redis running 120 [ "$status" -eq 0 ] }