#!/bin/sh set -eu deployment_directory=${1:-/opt/shd-build-stage} source_directory=${2:-} candidate_image=${3:-} if [ -z "$source_directory" ] || [ ! -f "$source_directory/Dockerfile" ] || [ -z "$candidate_image" ]; then echo "Usage: deploy-staging.sh " >&2 exit 2 fi compose_file="$deployment_directory/compose.staging.yml" deploy_environment="$deployment_directory/.env.deploy" compose() { docker compose --env-file "$deploy_environment" -f "$compose_file" "$@" } echo "Building the candidate image while the current staging service remains online." docker build --label org.opencontainers.image.title=shd-build -t "$candidate_image" "$source_directory" echo "Stopping SHD staging processes before accessing the embedded database." compose stop scheduler app || true echo "Creating a timestamped database backup when a staging database exists." compose run --rm --no-deps app sh -c \ 'if [ -f "$TDR_DATABASE_PATH" ]; then node scripts/db-backup.mjs; else echo "No staging database exists yet; skipping backup."; fi' echo "Applying additive schema migrations." compose run --rm --no-deps app node scripts/db-migrate.mjs echo "Starting the application and notification scheduler." compose up -d --no-build --remove-orphans app scheduler container_id=$(compose ps -q app) attempt=0 while [ "$attempt" -lt 30 ]; do status=$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$container_id") if [ "$status" = "healthy" ]; then echo "SHD staging deployment is healthy." exit 0 fi if [ "$status" = "unhealthy" ] || [ "$status" = "exited" ] || [ "$status" = "dead" ]; then break fi attempt=$((attempt + 1)) sleep 2 done echo "SHD staging failed its health check." compose logs --tail=150 app exit 1