Track HiveGrid Cloud planning reference
This commit is contained in:
1 parent
b3d5ea6764
commit
e341c5938a
5784 files changed
+1104929
-3
No files matched your search
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
IMAGE="${1:-toolctrl-worker:smoke}"
|
||||
CONTAINER_NAME="${DOCKER_WORKER_SMOKE_CONTAINER:-toolctrl-worker-runtime-smoke-$$}"
|
||||
DB_CONTAINER_NAME="${DOCKER_WORKER_SMOKE_DB_CONTAINER:-toolctrl-worker-runtime-smoke-db-$$}"
|
||||
REDIS_CONTAINER_NAME="${DOCKER_WORKER_SMOKE_REDIS_CONTAINER:-toolctrl-worker-runtime-smoke-redis-$$}"
|
||||
NETWORK_NAME="${DOCKER_WORKER_SMOKE_NETWORK:-toolctrl-worker-runtime-smoke-$$}"
|
||||
SMOKE_REVISION="${DOCKER_WORKER_SMOKE_REVISION:-}"
|
||||
DB_PASSWORD="toolctrl"
|
||||
DB_NAME="toolctrl"
|
||||
DB_USER="toolctrl"
|
||||
|
||||
cleanup() {
|
||||
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
|
||||
docker rm -f "$DB_CONTAINER_NAME" >/dev/null 2>&1 || true
|
||||
docker rm -f "$REDIS_CONTAINER_NAME" >/dev/null 2>&1 || true
|
||||
docker network rm "$NETWORK_NAME" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
resolve_smoke_revision() {
|
||||
if [[ -n "$SMOKE_REVISION" ]]; then
|
||||
printf "%s" "$SMOKE_REVISION"
|
||||
return
|
||||
fi
|
||||
|
||||
docker image inspect -f '{{ index .Config.Labels "org.opencontainers.image.revision" }}' "$IMAGE"
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
cleanup
|
||||
SMOKE_REVISION="$(resolve_smoke_revision)"
|
||||
if [[ -z "$SMOKE_REVISION" || "$SMOKE_REVISION" == "<no value>" || "$SMOKE_REVISION" == "unknown" ]]; then
|
||||
echo "Image ${IMAGE} does not expose a concrete org.opencontainers.image.revision; build with --build-arg APP_REVISION or set DOCKER_WORKER_SMOKE_REVISION explicitly" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
worker_env=(
|
||||
-e NODE_ENV=production
|
||||
-e APP_NAME=ToolCTRL
|
||||
-e APP_BASE_DOMAIN=localhost
|
||||
)
|
||||
|
||||
expect_worker_health() {
|
||||
local output="$1"
|
||||
local expected_status="$2"
|
||||
local expected_enabled="$3"
|
||||
local expected_group="${4:-}"
|
||||
local expected_queue="${5:-}"
|
||||
|
||||
node -e '
|
||||
const [raw, expectedStatus, expectedEnabled, expectedRevision, expectedGroup, expectedQueue] = process.argv.slice(1);
|
||||
const report = JSON.parse(raw);
|
||||
if (report.status !== expectedStatus) {
|
||||
console.error(`Expected worker status ${expectedStatus}, got ${report.status}`);
|
||||
process.exit(1);
|
||||
}
|
||||
if (String(report.workerEnabled) !== expectedEnabled) {
|
||||
console.error(`Expected workerEnabled ${expectedEnabled}, got ${report.workerEnabled}`);
|
||||
process.exit(1);
|
||||
}
|
||||
if (report.revision !== expectedRevision) {
|
||||
console.error(`Expected revision ${expectedRevision}, got ${report.revision || "<empty>"}`);
|
||||
process.exit(1);
|
||||
}
|
||||
if (expectedGroup && report.workerGroup !== expectedGroup) {
|
||||
console.error(`Expected workerGroup ${expectedGroup}, got ${report.workerGroup || "<empty>"}`);
|
||||
process.exit(1);
|
||||
}
|
||||
if (expectedQueue && !Array.isArray(report.queues)) {
|
||||
console.error("Expected worker health queues to be an array");
|
||||
process.exit(1);
|
||||
}
|
||||
if (expectedQueue && !report.queues.includes(expectedQueue)) {
|
||||
console.error(`Expected worker queues to include ${expectedQueue}, got ${report.queues?.join(",") || "<empty>"}`);
|
||||
process.exit(1);
|
||||
}
|
||||
if (expectedStatus === "ready" && (report.databaseStatus !== "ready" || report.redisStatus !== "ready")) {
|
||||
console.error(`Expected ready DB/Redis, got database=${report.databaseStatus} redis=${report.redisStatus}`);
|
||||
process.exit(1);
|
||||
}
|
||||
' "$output" "$expected_status" "$expected_enabled" "$SMOKE_REVISION" "$expected_group" "$expected_queue"
|
||||
}
|
||||
|
||||
docker network create "$NETWORK_NAME" >/dev/null
|
||||
|
||||
health_output="$(
|
||||
docker run --rm \
|
||||
"${worker_env[@]}" \
|
||||
-e WORKER_ENABLED=false \
|
||||
"$IMAGE" node apps/worker/dist/health.js
|
||||
)"
|
||||
|
||||
expect_worker_health "$health_output" disabled false
|
||||
|
||||
docker run -d --name "$DB_CONTAINER_NAME" --network "$NETWORK_NAME" --network-alias db \
|
||||
-e POSTGRES_USER="$DB_USER" \
|
||||
-e POSTGRES_PASSWORD="$DB_PASSWORD" \
|
||||
-e POSTGRES_DB="$DB_NAME" \
|
||||
postgres:16-alpine >/dev/null
|
||||
|
||||
docker run -d --name "$REDIS_CONTAINER_NAME" --network "$NETWORK_NAME" --network-alias redis redis:7-alpine >/dev/null
|
||||
|
||||
CONTAINER_DATABASE_URL="postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}?schema=public"
|
||||
CONTAINER_REDIS_URL="redis://redis:6379/0"
|
||||
|
||||
for attempt in $(seq 1 30); do
|
||||
if docker exec "$DB_CONTAINER_NAME" pg_isready -U "$DB_USER" -d "$DB_NAME" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
|
||||
if [[ "$attempt" == "30" ]]; then
|
||||
echo "Postgres smoke database did not become ready" >&2
|
||||
docker logs "$DB_CONTAINER_NAME" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
|
||||
for attempt in $(seq 1 30); do
|
||||
if docker exec "$REDIS_CONTAINER_NAME" redis-cli ping >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
|
||||
if [[ "$attempt" == "30" ]]; then
|
||||
echo "Redis smoke broker did not become ready" >&2
|
||||
docker logs "$REDIS_CONTAINER_NAME" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
|
||||
docker run --rm --network "$NETWORK_NAME" \
|
||||
-e NODE_ENV=production \
|
||||
-e DATABASE_URL="$CONTAINER_DATABASE_URL" \
|
||||
--entrypoint /bin/sh \
|
||||
"$IMAGE" -lc 'cd /myapp && pnpm exec prisma migrate deploy --config prisma.config.ts' >/dev/null
|
||||
|
||||
enabled_health_output="$(
|
||||
docker run --rm --network "$NETWORK_NAME" \
|
||||
"${worker_env[@]}" \
|
||||
-e WORKER_ENABLED=true \
|
||||
-e WORKER_QUEUE_GROUP=general \
|
||||
-e DATABASE_URL="$CONTAINER_DATABASE_URL" \
|
||||
-e BULLMQ_REDIS_URL="$CONTAINER_REDIS_URL" \
|
||||
"$IMAGE" node apps/worker/dist/health.js
|
||||
)"
|
||||
expect_worker_health "$enabled_health_output" ready true general toolctrl.notifications
|
||||
|
||||
mail_health_output="$(
|
||||
docker run --rm --network "$NETWORK_NAME" \
|
||||
"${worker_env[@]}" \
|
||||
-e WORKER_ENABLED=true \
|
||||
-e WORKER_QUEUE_GROUP=mail \
|
||||
-e DATABASE_URL="$CONTAINER_DATABASE_URL" \
|
||||
-e BULLMQ_REDIS_URL="$CONTAINER_REDIS_URL" \
|
||||
"$IMAGE" node apps/worker/dist/health.js
|
||||
)"
|
||||
expect_worker_health "$mail_health_output" ready true mail toolctrl.email
|
||||
|
||||
docker run -d --name "$CONTAINER_NAME" --network "$NETWORK_NAME" \
|
||||
"${worker_env[@]}" \
|
||||
-e WORKER_ENABLED=true \
|
||||
-e WORKER_QUEUE_GROUP=general \
|
||||
-e DATABASE_URL="$CONTAINER_DATABASE_URL" \
|
||||
-e BULLMQ_REDIS_URL="$CONTAINER_REDIS_URL" \
|
||||
"$IMAGE" >/tmp/toolctrl-worker-runtime-smoke.log
|
||||
|
||||
for attempt in $(seq 1 10); do
|
||||
if [[ "$(docker inspect -f '{{.State.Running}}' "$CONTAINER_NAME" 2>/dev/null || true)" == "true" ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
if [[ "$attempt" == "10" ]]; then
|
||||
echo "Worker container did not stay running" >&2
|
||||
docker logs "$CONTAINER_NAME" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
|
||||
running_health_output="$(
|
||||
docker exec "$CONTAINER_NAME" node apps/worker/dist/health.js
|
||||
)"
|
||||
expect_worker_health "$running_health_output" ready true general toolctrl.notifications
|
||||
|
||||
echo "Docker worker runtime smoke passed for ${IMAGE}"
|
||||
Reference in new issue
Block a user