Deploy / validate-dispatch (push) Successful in 43s
Deploy / scheduled-rebuild-dev (push) Skipped
Deploy / scheduled-rebuild-master (push) Skipped
Deploy / rollback-dev (push) Skipped
Deploy / rollback-master (push) Skipped
Deploy / changes (push) Successful in 13s
Deploy / secret-scan (push) Successful in 9s
Deploy / app-quality (push) Successful in 11m21s
Deploy / security-deps (push) Successful in 14s
Deploy / context (push) Failing after 1s
Deploy / app-image (push) Skipped
Deploy / deploy-dev (push) Skipped
Deploy / deploy-master (push) Skipped
44 lines
1.9 KiB
Bash
Executable File
44 lines
1.9 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
previous_image=""
|
|
app_container_id=""
|
|
|
|
wait_for_health() {
|
|
attempt=1
|
|
while [ "$attempt" -le 40 ]; do
|
|
status="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "$app_container_id" 2>/dev/null || echo unknown)"
|
|
[ "$status" = healthy ] && return 0
|
|
[ "$status" = unhealthy ] && return 1
|
|
sleep 3
|
|
attempt=$((attempt + 1))
|
|
done
|
|
return 1
|
|
}
|
|
|
|
verify_routes() {
|
|
docker exec -i "$app_container_id" node --input-type=module - <<'NODE'
|
|
const request = (path, init) => fetch(`http://127.0.0.1:3000${path}`, { signal: AbortSignal.timeout(20000), ...init });
|
|
for (const [path, text] of [["/", "Bereit für Ihre neue Website"], ["/kalender/", "Kalender"], ["/robots.txt", "Sitemap:"]]) {
|
|
const response = await request(path);
|
|
if (!response.ok || !(await response.text()).includes(text)) throw new Error(`${path} failed`);
|
|
}
|
|
const events = await request("/api/events");
|
|
const etag = events.headers.get("etag");
|
|
if (!events.ok || !etag || !Array.isArray(await events.json())) throw new Error("events failed");
|
|
if ((await request("/api/events", { headers: { "If-None-Match": etag } })).status !== 304) throw new Error("ETag failed");
|
|
for (const path of ["/health/live", "/health/ready"]) if (!(await request(path)).ok) throw new Error(`${path} failed`);
|
|
NODE
|
|
}
|
|
|
|
current_id="$(docker compose ps -q app 2>/dev/null || true)"
|
|
if [ -n "$current_id" ]; then previous_image="$(docker inspect --format '{{.Config.Image}}' "$current_id" 2>/dev/null || true)"; fi
|
|
if ! docker compose up -d --no-build --remove-orphans app; then exit 1; fi
|
|
app_container_id="$(docker compose ps -q app)"
|
|
if ! wait_for_health || ! verify_routes; then
|
|
docker compose ps || true
|
|
docker compose logs app || true
|
|
if [ -n "$previous_image" ]; then APP_IMAGE_NAME="$previous_image" docker compose up -d --no-build --remove-orphans app; fi
|
|
exit 1
|
|
fi
|