optimized events
Test and publish container images / test (push) Successful in 2m26s
Test and publish container images / publish (push) Failing after 3s

This commit is contained in:
BuTzZ
2026-07-28 14:36:47 +02:00
parent b98ec8bc6f
commit 593dbd5f85
42 changed files with 2405 additions and 283 deletions
+8
View File
@@ -87,6 +87,8 @@ install -d -m 0755 \
"$WATERMAPS_DATA_DIR" \
"$WATERMAPS_DATA_DIR/geofabrik" \
"$WATERMAPS_DATA_DIR/local" \
"$WATERMAPS_DATA_DIR/postgres" \
"$WATERMAPS_DATA_DIR/tmp" \
"$WATERMAPS_DATA_DIR/certbot" \
"$WATERMAPS_DATA_DIR/certbot/www" \
"$WATERMAPS_DATA_DIR/certbot/letsencrypt" \
@@ -95,6 +97,12 @@ install -d -m 0755 \
"$WATERMAPS_RUNTIME_DIR/nginx/conf.d" \
"$WATERMAPS_RUNTIME_DIR/locks"
# postgis/postgis uses the Debian postgres UID/GID 999. Keeping PGDATA on the
# mounted Hetzner volume makes event data survive image deployments and host
# reboots; the official entrypoint can still repair ownership inside PGDATA.
chown 999:999 "$WATERMAPS_DATA_DIR/postgres"
chmod 0700 "$WATERMAPS_DATA_DIR/postgres"
if [[ ! -f "$WATERMAPS_RUNTIME_DIR/nginx/conf.d/default.conf" ]]; then
install -m 0644 \
"$WM_DEPLOY_DIR/nginx/bootstrap.conf" \
+156
View File
@@ -33,6 +33,16 @@ wm_load_env() {
wm_require_safe_absolute_dir "$WATERMAPS_DATA_DIR"
wm_require_safe_absolute_dir "$WATERMAPS_RUNTIME_DIR"
wm_validate_postgres_password
}
wm_validate_postgres_password() {
local password="${WATERMAPS_POSTGRES_PASSWORD:-}"
[[ "${#password}" -ge 24 &&
"$password" != *[[:space:]]* &&
"$password" != *REPLACE* ]] ||
wm_die "WATERMAPS_POSTGRES_PASSWORD muss ein gesetztes Secret mit mindestens 24 Zeichen ohne Leerzeichen sein."
}
wm_require_safe_absolute_dir() {
@@ -162,6 +172,10 @@ wm_route_marker() {
printf '%s/local/.germany-netherlands-fairways.ready\n' "$WATERMAPS_DATA_DIR"
}
wm_marine_marker() {
printf '%s/local/.marine-features.ready\n' "$WATERMAPS_DATA_DIR"
}
wm_acquire_route_lock() {
install -d -m 0755 "$WATERMAPS_RUNTIME_DIR/locks"
exec 9>"$WATERMAPS_RUNTIME_DIR/locks/route-update.lock"
@@ -288,6 +302,107 @@ wm_route_data_files_ready() {
return 0
}
wm_geofabrik_checksum() {
local region="$1"
local checksum_file="$WATERMAPS_DATA_DIR/geofabrik/${region}-latest.osm.pbf.md5"
local checksum
[[ -s "$checksum_file" ]] || return 1
checksum="$(awk 'NR == 1 { print tolower($1) }' "$checksum_file")"
[[ "$checksum" =~ ^[0-9a-f]{32}$ ]] || return 1
printf '%s\n' "$checksum"
}
wm_postgres_query() {
local query="$1"
wm_compose exec --no-TTY postgres \
psql \
--no-psqlrc \
--username seacompass \
--dbname seacompass \
--tuples-only \
--no-align \
--field-separator '|' \
--set ON_ERROR_STOP=1 \
--command "$query"
}
wm_marine_features_ready() {
local marker germany_checksum netherlands_checksum database_counts
local total_count harbour_count lock_count bridge_count
local marker_format marker_source marker_germany marker_netherlands
local marker_total marker_harbours marker_locks marker_bridges
marker="$(wm_marine_marker)"
if [[ ! -s "$marker" ]]; then
wm_log "Bereitschaftsmarker für Marine-Features fehlt: $marker"
return 1
fi
germany_checksum="$(wm_geofabrik_checksum germany 2>/dev/null || true)"
netherlands_checksum="$(wm_geofabrik_checksum netherlands 2>/dev/null || true)"
if [[ -z "$germany_checksum" || -z "$netherlands_checksum" ]]; then
wm_log "Geofabrik-Prüfsummen für den Marine-Feature-Stand fehlen oder sind ungültig."
return 1
fi
marker_format="$(wm_marker_value "$marker" format_version 2>/dev/null || true)"
marker_source="$(wm_marker_value "$marker" source 2>/dev/null || true)"
marker_germany="$(wm_marker_value "$marker" germany_md5 2>/dev/null || true)"
marker_netherlands="$(wm_marker_value "$marker" netherlands_md5 2>/dev/null || true)"
marker_total="$(wm_marker_value "$marker" total_osm_features 2>/dev/null || true)"
marker_harbours="$(wm_marker_value "$marker" harbour_count 2>/dev/null || true)"
marker_locks="$(wm_marker_value "$marker" lock_count 2>/dev/null || true)"
marker_bridges="$(wm_marker_value "$marker" bridge_count 2>/dev/null || true)"
if [[ "$marker_format" != "1" ||
"$marker_source" != "germany+netherlands" ||
"$marker_germany" != "$germany_checksum" ||
"$marker_netherlands" != "$netherlands_checksum" ]]; then
wm_log "Marine-Feature-Marker passt nicht zu den aktuellen Deutschland-/Niederlande-Snapshots."
return 1
fi
if ! database_counts="$(
wm_postgres_query "
SELECT
count(*)::bigint,
count(*) FILTER (WHERE layer = 'harbours')::bigint,
count(*) FILTER (WHERE layer = 'locks')::bigint,
count(*) FILTER (WHERE layer = 'bridges')::bigint
FROM marine_features
WHERE source = 'osm';
"
)"; then
wm_log "Marine-Feature-Tabellen sind in PostGIS nicht abfragbar."
return 1
fi
database_counts="${database_counts//[[:space:]]/}"
IFS='|' read -r total_count harbour_count lock_count bridge_count <<<"$database_counts"
for count in "$total_count" "$harbour_count" "$lock_count" "$bridge_count"; do
if [[ ! "$count" =~ ^[1-9][0-9]*$ ]]; then
wm_log "PostGIS enthält keine vollständigen OSM-Hafen-/Schleusen-/Brückendaten."
return 1
fi
done
if [[ "$marker_total" != "$total_count" ||
"$marker_harbours" != "$harbour_count" ||
"$marker_locks" != "$lock_count" ||
"$marker_bridges" != "$bridge_count" ]]; then
wm_log "Marine-Feature-Marker stimmt nicht mit den OSM-Zeilen in PostGIS überein."
return 1
fi
return 0
}
wm_assert_marine_features() {
wm_marine_features_ready ||
wm_die "Marine-Features sind nicht vollständig in PostGIS bereit."
}
wm_wait_for_health() {
local service="$1"
local timeout_seconds="${2:-180}"
@@ -479,3 +594,44 @@ wm_smoke_test_route() {
}
'
}
wm_smoke_test_features() {
wm_compose exec --no-TTY watermaps node --input-type=module --eval '
const params = new URLSearchParams({
bbox: "7.118483884871649,53.302596677614666,7.543960668999219,53.50669706666667",
layers: "harbours,locks,bridges"
});
const response = await fetch(`http://127.0.0.1:5174/api/features?${params}`);
if (!response.ok) {
console.error("Feature-Smoke-Test", response.status, await response.text());
process.exit(1);
}
const collection = await response.json();
const features = Array.isArray(collection.features) ? collection.features : [];
const layers = new Set(features.map((feature) => feature?.properties?.layer));
const contactFeature = features.find((feature) =>
["harbours", "locks"].includes(feature?.properties?.layer)
&& typeof feature?.properties?.phone === "string"
&& feature.properties.phone.trim().length > 0
);
if (
collection?.metadata?.source !== "postgis"
|| !layers.has("harbours")
|| !layers.has("locks")
|| !layers.has("bridges")
|| !contactFeature
) {
console.error(
"PostGIS-Feature-Prüfung für die EmdenAurich-Teststrecke fehlgeschlagen.",
JSON.stringify({
source: collection?.metadata?.source,
featureCount: features.length,
layers: [...layers],
hasCallableHarbourOrLock: Boolean(contactFeature)
})
);
process.exit(1);
}
'
}
+28 -12
View File
@@ -69,12 +69,16 @@ wm_finish_deployment() {
if [[ -n "$rollback_images_file" && -f "$rollback_images_file" ]]; then
wm_log "Deployment fehlgeschlagen; vorheriges Container-Release wird wiederhergestellt."
wm_use_images_env "$rollback_images_file"
wm_compose up --detach --no-build --remove-orphans watermaps nginx
wm_compose up --detach --no-build --remove-orphans postgres watermaps nginx
wm_wait_for_health postgres 240
wm_wait_for_health watermaps 240
wm_wait_for_health nginx 120
if wm_route_data_ready; then
wm_smoke_test_route
fi
if wm_marine_features_ready; then
wm_smoke_test_features
fi
else
wm_log "Deployment fehlgeschlagen; für das erste Release existiert noch kein Rollback."
fi
@@ -99,7 +103,7 @@ requested_app_image="$(wm_env_value "$images_env_file" WATERMAPS_APP_IMAGE)"
requested_route_data_image="$(wm_env_value "$images_env_file" WATERMAPS_ROUTE_DATA_IMAGE)"
wm_log "Container-Images für Commit $revision werden aus den Registries geladen."
wm_compose --profile maintenance pull watermaps nginx certbot route-data
wm_compose --profile maintenance pull watermaps postgres nginx certbot route-data
resolved_app_image="$(wm_resolve_image_digest "$requested_app_image")"
resolved_route_data_image="$(wm_resolve_image_digest "$requested_route_data_image")"
@@ -114,30 +118,42 @@ resolved_images_file="$(
chmod 0644 "$resolved_images_file"
wm_use_images_env "$resolved_images_file"
wm_log "Commit $revision wird mit unveränderlichen Image-Digests gestartet."
wm_compose up --detach --no-build --remove-orphans watermaps nginx
wm_log "Persistentes PostGIS wird vor App und Datenimport gestartet."
wm_compose up --detach --no-build postgres
wm_wait_for_health postgres 240
wm_wait_for_health watermaps 240
wm_wait_for_health nginx 120
route_rebuild_required=false
data_update_required=false
update_args=()
if [[ "${WATERMAPS_REBUILD_ROUTE_DATA:-false}" == "true" ]]; then
route_rebuild_required=true
data_update_required=true
update_args+=(--force)
elif ! wm_route_data_ready; then
route_rebuild_required=true
data_update_required=true
fi
if [[ "${WATERMAPS_REBUILD_MARINE_DATA:-false}" == "true" ]]; then
data_update_required=true
update_args+=(--force-marine)
elif ! wm_marine_features_ready; then
data_update_required=true
fi
if [[ "$route_rebuild_required" == "true" ]]; then
wm_log "Deutschland- und Niederlande-Routingdaten werden sicher vorbereitet."
if [[ "$data_update_required" == "true" ]]; then
wm_log "Deutschland-/Niederlande-Routingdaten und Marine-Features werden sicher vorbereitet."
WATERMAPS_ROUTE_LOCK_HELD=true \
"$WM_DEPLOY_DIR/scripts/update-route-data.sh" "${update_args[@]}"
fi
wm_assert_route_data
wm_assert_marine_features
wm_log "Commit $revision wird erst mit validierten Routing- und Ereignisdaten gestartet."
wm_compose up --detach --no-build --remove-orphans postgres watermaps nginx
wm_wait_for_health postgres 240
wm_wait_for_health watermaps 240
wm_wait_for_health nginx 120
wm_smoke_test_route
wm_smoke_test_features
release_images_file="$WATERMAPS_RUNTIME_DIR/deployments/$revision.env"
install -m 0644 "$resolved_images_file" "$release_images_file"
+158
View File
@@ -0,0 +1,158 @@
#!/usr/bin/env bash
set -Eeuo pipefail
cd /workspace
database_url="${DATABASE_URL:-}"
geofabrik_dir="${WATERMAPS_GEOFABRIK_DIR:-/workspace/data/geofabrik}"
marker_file="${WATERMAPS_MARINE_MARKER_PATH:-/workspace/data/local/.marine-features.ready}"
temporary_root="${TMPDIR:-/tmp}"
pbf_paths=(
"$geofabrik_dir/germany-latest.osm.pbf"
"$geofabrik_dir/netherlands-latest.osm.pbf"
)
if [[ -z "$database_url" ]]; then
printf 'Fehler: DATABASE_URL ist für den Marine-Feature-Import erforderlich.\n' >&2
exit 1
fi
if [[ ! -x /workspace/scripts/import-geofabrik.sh ]]; then
printf 'Fehler: scripts/import-geofabrik.sh fehlt oder ist nicht ausführbar.\n' >&2
exit 1
fi
mkdir -p "$(dirname "$marker_file")" "$temporary_root"
export TMPDIR="$temporary_root"
declare -A source_checksums
for pbf_path in "${pbf_paths[@]}"; do
if [[ ! -s "$pbf_path" ]]; then
printf 'Fehler: Geofabrik-Snapshot fehlt oder ist leer: %s\n' "$pbf_path" >&2
exit 1
fi
checksum_file="${pbf_path}.md5"
if [[ ! -s "$checksum_file" ]]; then
printf 'Fehler: Geofabrik-Prüfsumme fehlt: %s\n' "$checksum_file" >&2
exit 1
fi
expected_checksum="$(awk 'NR == 1 { print tolower($1) }' "$checksum_file")"
if [[ ! "$expected_checksum" =~ ^[0-9a-f]{32}$ ]]; then
printf 'Fehler: Ungültige Geofabrik-Prüfsumme in %s\n' "$checksum_file" >&2
exit 1
fi
actual_checksum="$(md5sum "$pbf_path" | awk '{ print $1 }')"
if [[ "$actual_checksum" != "$expected_checksum" ]]; then
printf 'Fehler: Geofabrik-Snapshot stimmt nicht mit seiner Prüfsumme überein: %s\n' "$pbf_path" >&2
exit 1
fi
source_checksums["$(basename "$pbf_path" -latest.osm.pbf)"]="$actual_checksum"
done
# Every imported OSM row receives updated_at=now(). The shared database
# timestamp lets us remove disappeared OSM objects only after both regional
# imports completed and passed the sanity checks. Other sources such as EuRIS
# and facility-website enrichments are deliberately preserved.
import_started_epoch="$(
psql "$database_url" \
--no-psqlrc \
--tuples-only \
--no-align \
--set ON_ERROR_STOP=1 \
--command "SELECT extract(epoch FROM clock_timestamp());"
)"
import_started_epoch="${import_started_epoch//[[:space:]]/}"
if [[ ! "$import_started_epoch" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
printf 'Fehler: Datenbank lieferte keinen gültigen Importzeitpunkt.\n' >&2
exit 1
fi
for pbf_path in "${pbf_paths[@]}"; do
printf 'Importiere Marine-Features aus %s\n' "$(basename "$pbf_path")"
DATABASE_URL="$database_url" /workspace/scripts/import-geofabrik.sh "$pbf_path"
done
fresh_counts="$(
psql "$database_url" \
--no-psqlrc \
--tuples-only \
--no-align \
--field-separator '|' \
--set ON_ERROR_STOP=1 \
--command "
SELECT
count(*)::bigint,
count(*) FILTER (WHERE layer = 'harbours')::bigint,
count(*) FILTER (WHERE layer = 'locks')::bigint,
count(*) FILTER (WHERE layer = 'bridges')::bigint
FROM marine_features
WHERE source = 'osm'
AND updated_at >= to_timestamp($import_started_epoch);
"
)"
fresh_counts="${fresh_counts//[[:space:]]/}"
IFS='|' read -r fresh_total fresh_harbours fresh_locks fresh_bridges <<<"$fresh_counts"
for count in "$fresh_total" "$fresh_harbours" "$fresh_locks" "$fresh_bridges"; do
if [[ ! "$count" =~ ^[1-9][0-9]*$ ]]; then
printf 'Fehler: Der neue OSM-Import enthält keine vollständigen Hafen-/Schleusen-/Brückendaten.\n' >&2
exit 1
fi
done
psql "$database_url" \
--no-psqlrc \
--set ON_ERROR_STOP=1 \
--command "
BEGIN;
DELETE FROM marine_features
WHERE source = 'osm'
AND updated_at < to_timestamp($import_started_epoch);
DELETE FROM marine_fairway_edges
WHERE source = 'osm'
AND updated_at < to_timestamp($import_started_epoch);
COMMIT;
ANALYZE marine_features;
ANALYZE marine_fairway_edges;
"
final_counts="$(
psql "$database_url" \
--no-psqlrc \
--tuples-only \
--no-align \
--field-separator '|' \
--set ON_ERROR_STOP=1 \
--command "
SELECT
count(*)::bigint,
count(*) FILTER (WHERE layer = 'harbours')::bigint,
count(*) FILTER (WHERE layer = 'locks')::bigint,
count(*) FILTER (WHERE layer = 'bridges')::bigint
FROM marine_features
WHERE source = 'osm';
"
)"
final_counts="${final_counts//[[:space:]]/}"
IFS='|' read -r total_osm_features harbour_count lock_count bridge_count <<<"$final_counts"
temporary_marker="$(mktemp "$(dirname "$marker_file")/.marine-features-ready.XXXXXX")"
{
printf 'format_version=1\n'
printf 'generated_at=%s\n' "$(date --utc +%Y-%m-%dT%H:%M:%SZ)"
printf 'source=germany+netherlands\n'
printf 'germany_md5=%s\n' "${source_checksums[germany]}"
printf 'netherlands_md5=%s\n' "${source_checksums[netherlands]}"
printf 'total_osm_features=%s\n' "$total_osm_features"
printf 'harbour_count=%s\n' "$harbour_count"
printf 'lock_count=%s\n' "$lock_count"
printf 'bridge_count=%s\n' "$bridge_count"
} >"$temporary_marker"
chmod 0644 "$temporary_marker"
mv -f "$temporary_marker" "$marker_file"
printf 'Marine-Features sind bereit: %s OSM-Objekte (%s Häfen, %s Schleusen, %s Brücken)\n' \
"$total_osm_features" "$harbour_count" "$lock_count" "$bridge_count"
@@ -71,4 +71,56 @@ if wm_route_data_ready; then
exit 1
fi
printf 'Routingdaten- und Markerprüfungen: OK\n'
mkdir -p "$WATERMAPS_DATA_DIR/geofabrik"
printf '%s germany-latest.osm.pbf\n' \
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' \
>"$WATERMAPS_DATA_DIR/geofabrik/germany-latest.osm.pbf.md5"
printf '%s netherlands-latest.osm.pbf\n' \
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' \
>"$WATERMAPS_DATA_DIR/geofabrik/netherlands-latest.osm.pbf.md5"
cat >"$(wm_marine_marker)" <<'MARKER'
format_version=1
generated_at=2026-07-28T00:00:00Z
source=germany+netherlands
germany_md5=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
netherlands_md5=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
total_osm_features=100
harbour_count=10
lock_count=5
bridge_count=20
MARKER
wm_postgres_query() {
printf '100|10|5|20\n'
}
wm_marine_features_ready
wm_postgres_query() {
printf '100|10|0|20\n'
}
if wm_marine_features_ready; then
printf 'Marine-Feature-Marker wurde trotz fehlender Schleusen akzeptiert.\n' >&2
exit 1
fi
wm_postgres_query() {
printf '99|10|5|20\n'
}
if wm_marine_features_ready; then
printf 'Marine-Feature-Marker wurde trotz abweichendem Datenbankbestand akzeptiert.\n' >&2
exit 1
fi
if grep -Eq 'DATABASE_URL:[[:space:]]*""' \
"$ROOT_DIR/docker-compose.yml" \
"$ROOT_DIR/deploy/compose.production.yml"; then
printf 'Compose trennt die App weiterhin explizit von PostGIS.\n' >&2
exit 1
fi
grep -Fq 'condition: service_healthy' "$ROOT_DIR/deploy/compose.production.yml"
grep -Fq '/ready' "$ROOT_DIR/deploy/compose.production.yml"
grep -Fq 'source: ${WATERMAPS_DATA_DIR:-/srv/watermaps-data}/postgres' \
"$ROOT_DIR/deploy/compose.production.yml"
printf 'Routingdaten-, Marine-Feature- und Compose-Prüfungen: OK\n'
@@ -16,6 +16,7 @@ mkdir -p "$FAKE_BIN" "$DATA_DIR/local" "$RUNTIME_DIR"
cat >"$ENV_FILE" <<EOF
WATERMAPS_DATA_DIR=$DATA_DIR
WATERMAPS_RUNTIME_DIR=$RUNTIME_DIR
WATERMAPS_POSTGRES_PASSWORD=0123456789abcdef0123456789abcdef
EOF
cat >"$IMAGES_ENV_FILE" <<'EOF'
@@ -48,6 +49,11 @@ if [[ "${1:-}" == "inspect" ]]; then
fi
arguments=" $* "
if [[ "$arguments" == *" ps --quiet postgres "* ]]; then
printf 'postgres-test-container\n'
exit 0
fi
if [[ "$arguments" == *" ps --quiet watermaps "* ]]; then
printf 'watermaps-test-container\n'
exit 0
@@ -55,6 +61,13 @@ fi
if [[ "$arguments" == *" run "*" route-data "* ||
"$arguments" == *" run "*" route-data" ]]; then
mkdir -p "$WATERMAPS_DATA_DIR/geofabrik"
printf '%s germany-latest.osm.pbf\n' \
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' \
>"$WATERMAPS_DATA_DIR/geofabrik/germany-latest.osm.pbf.md5"
printf '%s netherlands-latest.osm.pbf\n' \
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' \
>"$WATERMAPS_DATA_DIR/geofabrik/netherlands-latest.osm.pbf.md5"
route_file="$WATERMAPS_DATA_DIR/local/.germany-netherlands-fairways.candidate.json"
marker_file="$WATERMAPS_DATA_DIR/local/.germany-netherlands-fairways.candidate.ready"
cat >"$route_file" <<JSON
@@ -86,6 +99,27 @@ JSON
exit 0
fi
if [[ "$arguments" == *" run "*" marine-data "* ||
"$arguments" == *" run "*" marine-data" ]]; then
cat >"$WATERMAPS_DATA_DIR/local/.marine-features.ready" <<'MARKER'
format_version=1
generated_at=2026-07-28T00:00:00Z
source=germany+netherlands
germany_md5=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
netherlands_md5=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
total_osm_features=100
harbour_count=10
lock_count=5
bridge_count=20
MARKER
exit 0
fi
if [[ "$arguments" == *" exec --no-TTY postgres "* ]]; then
printf '100|10|5|20\n'
exit 0
fi
if [[ "$arguments" == *" exec --no-TTY watermaps "* ]]; then
active_file="$WATERMAPS_DATA_DIR/local/germany-netherlands-fairways.json"
active_revision="$(jq --raw-output '.revision // 0' "$active_file" 2>/dev/null || true)"
+46 -10
View File
@@ -13,11 +13,22 @@ if [[ "$(id -u)" -ne 0 ]]; then
fi
force_rebuild=false
if [[ "${1:-}" == "--force" ]]; then
force_rebuild=true
shift
fi
[[ "$#" -eq 0 ]] || wm_die "Unbekannte Argumente für update-route-data.sh."
force_marine_import=false
while [[ "$#" -gt 0 ]]; do
case "$1" in
--force)
force_rebuild=true
shift
;;
--force-marine)
force_marine_import=true
shift
;;
*)
wm_die "Unbekanntes Argument für update-route-data.sh: $1"
;;
esac
done
install -d -m 0755 "$WATERMAPS_RUNTIME_DIR/locks" "$WATERMAPS_DATA_DIR/local"
if [[ "${WATERMAPS_ROUTE_LOCK_HELD:-false}" != "true" ]]; then
@@ -26,6 +37,9 @@ if [[ "${WATERMAPS_ROUTE_LOCK_HELD:-false}" != "true" ]]; then
fi
fi
wm_compose up --detach --no-build postgres
wm_wait_for_health postgres 240
route_file="$(wm_route_file)"
route_marker="$(wm_route_marker)"
route_dir="$(dirname "$route_file")"
@@ -58,6 +72,16 @@ wm_watermaps_is_running() {
[[ -n "$(wm_compose ps --quiet watermaps)" ]]
}
wm_update_marine_features() {
if [[ "$force_marine_import" == "true" ]] || ! wm_marine_features_ready; then
wm_log "Häfen, Schleusen und Brücken werden aus den verifizierten Geofabrik-Snapshots importiert."
wm_compose --profile maintenance run --rm marine-data
else
wm_log "Marine-Features in PostGIS sind bereits aktuell."
fi
wm_assert_marine_features
}
wm_restore_previous_route() {
rollback_restored_previous=false
if [[ -s "$backup_file" && -s "$backup_marker" ]] &&
@@ -78,8 +102,8 @@ wm_restore_previous_route() {
wm_restart_after_restore() {
if ! wm_watermaps_is_running; then
wm_log "Watermaps läuft nicht; wiederhergestellte Routingdaten können noch nicht getestet werden."
return 1
wm_log "Watermaps läuft noch nicht; wiederhergestellte Routingdaten werden beim App-Start getestet."
return 0
fi
wm_compose restart watermaps
@@ -156,8 +180,10 @@ if ! wm_route_data_files_ready "$candidate_file" "$candidate_marker"; then
wm_die "Der neu gebaute Routingindex oder sein Bereitschaftsmarker ist ungültig."
fi
wm_update_marine_features
if [[ "$previous_ready" == "true" ]] && cmp --silent "$candidate_file" "$route_file"; then
wm_log "Geofabrik-Snapshots und Routingindex sind unverändert."
wm_log "Geofabrik-Snapshots, Routingindex und Marine-Features sind aktuell."
rm -f "$candidate_file" "$candidate_marker"
exit 0
fi
@@ -186,8 +212,18 @@ wm_write_route_marker "$route_file" "$route_marker"
wm_route_data_ready ||
wm_die "Der aktivierte Routingindex besitzt keinen gültigen Bereitschaftsmarker."
wm_compose restart watermaps
if wm_wait_for_health watermaps 240 && wm_smoke_test_route; then
activation_valid=false
if wm_watermaps_is_running; then
wm_compose restart watermaps
if wm_wait_for_health watermaps 240 && wm_smoke_test_route; then
activation_valid=true
fi
else
wm_log "Watermaps läuft noch nicht; Routing- und Feature-API werden beim App-Start getestet."
activation_valid=true
fi
if [[ "$activation_valid" == "true" ]]; then
rm -f "$transaction_file"
transaction_active=false
rm -f "$backup_file" "$backup_marker"
+10 -2
View File
@@ -124,9 +124,9 @@ printf '[watermaps] Warte auf Cloud-init und das persistente Hetzner-Volume.\n'
ssh "${WM_SSH_OPTIONS[@]}" "$WM_SSH_TARGET" \
"cloud-init status --wait && ${remote_prefix}systemctl start watermaps-volume-setup.service && mountpoint --quiet /srv/watermaps-data"
printf '[watermaps] Übertrage Deployment-Dateien nach %s:/opt/watermaps/deploy\n' "$WM_SSH_TARGET"
printf '[watermaps] Übertrage Deployment-Dateien und Datenbankschema nach %s:/opt/watermaps\n' "$WM_SSH_TARGET"
ssh "${WM_SSH_OPTIONS[@]}" "$WM_SSH_TARGET" \
"${remote_prefix}install -d -m 0755 /opt/watermaps /opt/watermaps/deploy"
"${remote_prefix}install -d -m 0755 /opt/watermaps /opt/watermaps/deploy /opt/watermaps/database"
rsync \
--archive \
@@ -140,6 +140,14 @@ rsync \
"$WM_DEPLOY_DIR/" \
"$WM_SSH_TARGET:/opt/watermaps/deploy/"
rsync \
--archive \
--chmod=F644 \
--rsync-path="$rsync_path" \
-e "ssh ${WM_SSH_OPTIONS[*]@Q}" \
"$WM_LOCAL_ROOT_DIR/database/schema.sql" \
"$WM_SSH_TARGET:/opt/watermaps/database/schema.sql"
rsync \
--archive \
--chmod=F600 \