Run PostgreSQL and Cassandra integration tests and deploy Compose stack
Docker test deployment / test-build-deploy (push) Failing after 8m35s
Docker test deployment / test-build-deploy (push) Failing after 8m35s
This commit is contained in:
Executable
+70
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
: "${DEPLOY_IMAGE:?DEPLOY_IMAGE is required}"
|
||||
export TEST_IMAGE=${TEST_IMAGE:-$DEPLOY_IMAGE}
|
||||
mode=${1:-deploy}
|
||||
docker compose version
|
||||
if [[ "$mode" == ci ]]; then
|
||||
: "${CI_STACK_NAME:?CI_STACK_NAME is required}"
|
||||
[[ "$CI_STACK_NAME" =~ ^adcloud-ci-[a-z0-9-]+$ ]] || exit 2
|
||||
export COMPOSE_PROJECT_NAME=$CI_STACK_NAME
|
||||
export POSTGRES_PASSWORD
|
||||
POSTGRES_PASSWORD=$(python3 -c 'import secrets; print(secrets.token_urlsafe(48))')
|
||||
unset CONFIG_VOLUME CONFIG_EXTERNAL
|
||||
# Only this unique disposable CI project is removed, including its volumes.
|
||||
trap 'docker compose -f compose.yml --profile ci down --volumes --remove-orphans >/dev/null' EXIT
|
||||
docker compose -f compose.yml --profile ci run --rm integration
|
||||
exit
|
||||
fi
|
||||
[[ "$mode" == deploy ]] || { echo 'Use ci or deploy'; exit 2; }
|
||||
export DEPLOY_PORT=${DEPLOY_PORT:-18080}
|
||||
[[ "$DEPLOY_PORT" =~ ^[0-9]{1,5}$ ]] && ((10#$DEPLOY_PORT >= 1024 && 10#$DEPLOY_PORT <= 65535)) || exit 2
|
||||
export COMPOSE_PROJECT_NAME=adcloud-test
|
||||
export CONFIG_VOLUME=adcloud-server-test-config CONFIG_EXTERNAL=true
|
||||
lock=adcloud-server-test-deploy-lock
|
||||
lock_acquired=false
|
||||
legacy_stopped=false
|
||||
successful=false
|
||||
cleanup() {
|
||||
local result=$?
|
||||
trap - EXIT
|
||||
if ! $successful && $legacy_stopped; then
|
||||
docker compose -f compose.yml stop api worker >/dev/null || true
|
||||
docker start adcloud-server-test >/dev/null || true
|
||||
echo 'Compose deployment failed; legacy SQLite service restored where possible.'
|
||||
fi
|
||||
if $lock_acquired; then docker rm "$lock" >/dev/null || true; fi
|
||||
exit "$result"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
trap 'exit 130' INT
|
||||
trap 'exit 143' TERM
|
||||
for attempt in $(seq 1 60); do
|
||||
if docker create --name "$lock" --label io.entroia.adcloud.managed=true --label io.entroia.adcloud.repository=Zayden-Jung/adcloud-server --entrypoint /bin/true "$DEPLOY_IMAGE" >/dev/null 2>&1; then
|
||||
lock_acquired=true; break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
$lock_acquired || { echo 'Deployment lock unavailable'; exit 1; }
|
||||
if ! docker volume inspect "$CONFIG_VOLUME" >/dev/null 2>&1; then
|
||||
docker volume create --label io.entroia.adcloud.repository=Zayden-Jung/adcloud-server "$CONFIG_VOLUME" >/dev/null
|
||||
fi
|
||||
[[ "$(docker volume inspect --format '{{index .Labels "io.entroia.adcloud.repository"}}' "$CONFIG_VOLUME")" == Zayden-Jung/adcloud-server ]] || { echo 'Refusing unmanaged config volume'; exit 1; }
|
||||
# Capture a persistent random password in memory; never echo it or use shell tracing.
|
||||
export POSTGRES_PASSWORD
|
||||
POSTGRES_PASSWORD=$(docker run --rm --volume "$CONFIG_VOLUME:/config" --entrypoint python "$DEPLOY_IMAGE" -c 'from pathlib import Path; from adcloud_server.container_entrypoint import bootstrap; print(bootstrap(Path("/config/identity.env"))["POSTGRES_PASSWORD"])')
|
||||
# Initialize databases before switching the public API port.
|
||||
docker compose -f compose.yml up -d postgres cassandra
|
||||
docker compose -f compose.yml run --rm cassandra-init
|
||||
if docker container inspect adcloud-server-test >/dev/null 2>&1; then
|
||||
[[ "$(docker inspect --format '{{index .Config.Labels "io.entroia.adcloud.repository"}}' adcloud-server-test)" == Zayden-Jung/adcloud-server ]] || { echo 'Refusing unmanaged legacy container'; exit 1; }
|
||||
docker stop --time 20 adcloud-server-test >/dev/null
|
||||
legacy_stopped=true
|
||||
fi
|
||||
docker compose -f compose.yml up -d --wait --wait-timeout 180 api worker
|
||||
docker compose -f compose.yml --profile checks run --rm smoke
|
||||
# Verify the published host port too; config stays read-only in this probe.
|
||||
docker run --rm --network host --volume "$CONFIG_VOLUME:/config:ro" --entrypoint python "$DEPLOY_IMAGE" /app/scripts/smoke_api.py --base-url "http://127.0.0.1:$DEPLOY_PORT" --require-projection
|
||||
successful=true
|
||||
echo "PostgreSQL + Cassandra + worker deployed; public API port=$DEPLOY_PORT"
|
||||
echo 'Legacy SQLite container remains stopped; its data volume is retained (no automatic data migration).'
|
||||
Reference in New Issue
Block a user