#!/bin/sh # Deploy only the image produced after the remote database checks succeed. set -eu cd "$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)" test "$(id -u)" -eq 0 || { echo "Deployment requires root on ces-control" >&2; exit 1; } release_sha=${ASTER_RELEASE_SHA:?ASTER_RELEASE_SHA is required} case "$release_sha" in *[!0-9a-f]*|'') echo "Invalid release SHA" >&2; exit 1;; esac test "${#release_sha}" -eq 40 image="endorphin-aster-vm:$release_sha" docker image inspect "$image" >/dev/null umask 077 root=/opt/endorphin-aster-vm config=/etc/endorphin-aster-vm/production.env release="$root/releases/$release_sha" mkdir -p "$release" /etc/endorphin-aster-vm /var/lib/endorphin-aster-vm/postgres /var/lib/endorphin-aster-vm/host chown 10001:10001 /var/lib/endorphin-aster-vm/host chmod 700 /var/lib/endorphin-aster-vm/host exec 9>/var/lock/endorphin-aster-vm-deploy.lock flock 9 if [ ! -f "$config" ]; then password=$(openssl rand -hex 24) printf 'POSTGRES_PASSWORD=%s\nASTER_PORT=18081\n' "$password" > "$config" unset password fi chmod 600 "$config" cp docker-compose.ces-control.yml "$release/compose.yml" printf 'ASTER_IMAGE=%s\n' "$image" > "$release/release.env" previous=$(readlink -f "$root/current" 2>/dev/null || true) legacy_export= cleanup_export() { if [ -n "$legacy_export" ]; then rm -f "$legacy_export"; fi } trap cleanup_export EXIT compose_at() { location=$1 shift docker compose -p endorphin-aster-vm --env-file "$config" \ --env-file "$location/release.env" -f "$location/compose.yml" "$@" } rollback() { echo "Deployment failed; application data has been retained" >&2 if [ -n "$previous" ] && [ "$previous" != "$release" ] && [ -f "$previous/compose.yml" ]; then echo "Restoring the previously healthy release" >&2 compose_at "$previous" up -d --no-build --wait --wait-timeout 180 || true fi } if ! compose_at "$release" up -d --no-build --wait --wait-timeout 180; then rollback exit 1 fi if ! health=$(compose_at "$release" exec -T aster curl --fail --silent http://127.0.0.1:8080/health); then rollback exit 1 fi printf '%s' "$health" | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d == {"status":"ok"}' || { rollback exit 1 } if ! bootstrap=$(compose_at "$release" exec -T aster cli bootstrap); then rollback exit 1 fi printf '%s' "$bootstrap" | python3 -c 'import sys; s=sys.stdin.read(); assert "runtime=EndorObject type_system=disabled" in s; assert "released heap_objects=0" in s' || { rollback exit 1 } # Import legacy basic information once, without changing database records. # Files are authoritative; cli import only creates records that are missing. if [ ! -f /var/lib/endorphin-aster-vm/host/.legacy-imported ]; then if ! has_legacy=$(compose_at "$release" exec -T postgres env PGCLIENTENCODING=UTF8 psql -X -U aster -d aster -A -t -v ON_ERROR_STOP=1 \ -c "SELECT to_regclass('public.aster_metadata') IS NOT NULL"); then rollback exit 1 fi if [ "$has_legacy" = t ]; then legacy_export=$(mktemp) if ! compose_at "$release" exec -T postgres env PGCLIENTENCODING=UTF8 psql -X -U aster -d aster -A -t -v ON_ERROR_STOP=1 \ -c "SELECT COALESCE(json_agg(json_build_object('key', key, 'value', value)), '[]'::json) FROM public.aster_metadata" > "$legacy_export"; then rollback exit 1 fi if ! compose_at "$release" exec -T aster cli metadata import < "$legacy_export"; then rollback exit 1 fi rm -f "$legacy_export" legacy_export= elif [ "$has_legacy" != f ]; then echo "Cannot determine legacy information schema" >&2 rollback exit 1 fi if ! touch /var/lib/endorphin-aster-vm/host/.legacy-imported; then rollback exit 1 fi fi # File-backed host information; no SQL table or database write. if ! compose_at "$release" exec -T aster cli metadata put deployment.release "$release_sha"; then rollback exit 1 fi if ! actual=$(compose_at "$release" exec -T aster cli metadata get deployment.release); then rollback exit 1 fi if [ "$actual" != "$release_sha" ]; then rollback exit 1 fi ln -sfn "$release" "$root/current.next" mv -Tf "$root/current.next" "$root/current" compose_at "$release" ps echo "Deployed release=$release_sha postgres=provisioned endpoint=127.0.0.1:18081" echo "Persistent PostgreSQL data: /var/lib/endorphin-aster-vm/postgres"