Compare commits
2 Commits
d5448d9a94
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 331507ee40 | |||
| 6ff5fe53c5 |
@@ -10,9 +10,11 @@ esac
|
|||||||
case "$directory:$origin" in
|
case "$directory:$origin" in
|
||||||
/opt/esports:https://esports.vash.software)
|
/opt/esports:https://esports.vash.software)
|
||||||
environment=/etc/esports/prod.env
|
environment=/etc/esports/prod.env
|
||||||
|
migration_environment=/etc/esports/prod-migrations.env
|
||||||
host_port=3100 ;;
|
host_port=3100 ;;
|
||||||
/opt/esports-staging:https://esports-staging.vash.software)
|
/opt/esports-staging:https://esports-staging.vash.software)
|
||||||
environment=/etc/esports-staging/staging.env
|
environment=/etc/esports-staging/staging.env
|
||||||
|
migration_environment=/etc/esports/staging-migrations.env
|
||||||
host_port=3101 ;;
|
host_port=3101 ;;
|
||||||
*) echo 'Unrecognized deployment target' >&2; exit 2 ;;
|
*) echo 'Unrecognized deployment target' >&2; exit 2 ;;
|
||||||
esac
|
esac
|
||||||
@@ -25,13 +27,15 @@ else
|
|||||||
environment_name=production
|
environment_name=production
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sudo install -d -m 0755 "$directory"
|
# The deploy user only has passwordless sudo for tee and docker.
|
||||||
if [ ! -f "$directory/release.env" ]; then
|
if [ ! -d "$directory" ]; then
|
||||||
printf 'IMAGE_TAG=%s\nHOST_PORT=%s\n' "$sha" "$host_port" | sudo tee "$directory/release.env" >/dev/null
|
echo "$directory does not exist; create it once on the host" >&2
|
||||||
fi
|
exit 1
|
||||||
if ! grep -q '^HOST_PORT=' "$directory/release.env"; then
|
|
||||||
echo "HOST_PORT=$host_port" | sudo tee -a "$directory/release.env" >/dev/null
|
|
||||||
fi
|
fi
|
||||||
|
previous_tag=$(sed -n 's/^IMAGE_TAG=//p' "$directory/release.env" 2>/dev/null | head -n 1 || true)
|
||||||
|
write_release() {
|
||||||
|
printf 'IMAGE_TAG=%s\nHOST_PORT=%s\n' "$1" "$host_port" | sudo tee "$directory/release.env" >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
sudo tee "$compose" >/dev/null <<EOF
|
sudo tee "$compose" >/dev/null <<EOF
|
||||||
services:
|
services:
|
||||||
@@ -59,22 +63,22 @@ networks:
|
|||||||
external: true
|
external: true
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
previous_tag=$(sed -n 's/^IMAGE_TAG=//p' "$directory/release.env" | head -n 1)
|
|
||||||
switched=0
|
switched=0
|
||||||
rollback() {
|
rollback() {
|
||||||
if [ "$switched" -eq 1 ] && [ -n "$previous_tag" ]; then
|
if [ "$switched" -eq 1 ] && [ -n "$previous_tag" ]; then
|
||||||
echo "Health check failed; restoring prior image tag $previous_tag" >&2
|
echo "Health check failed; restoring prior image tag $previous_tag" >&2
|
||||||
sudo sed -i "s/^IMAGE_TAG=.*/IMAGE_TAG=$previous_tag/" "$directory/release.env"
|
write_release "$previous_tag"
|
||||||
sudo docker compose --env-file "$directory/release.env" -f "$compose" up -d
|
sudo docker compose --env-file "$directory/release.env" -f "$compose" up -d
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
trap rollback ERR
|
trap rollback ERR
|
||||||
|
|
||||||
port=$(sed -n 's/^HOST_PORT=//p' "$directory/release.env" | head -n 1)
|
port=$host_port
|
||||||
if [ "${FORCE_DEPLOY:-}" != 1 ] && curl --fail --silent --show-error "http://127.0.0.1:${port}/api/health" > /tmp/esports-health.json; then
|
health=$(mktemp)
|
||||||
python3 - <<'PY'
|
if [ "${FORCE_DEPLOY:-}" != 1 ] && curl --fail --silent --show-error "http://127.0.0.1:${port}/api/health" > "$health"; then
|
||||||
import json
|
HEALTH_FILE=$health python3 - <<'PY'
|
||||||
data = json.load(open("/tmp/esports-health.json"))
|
import json, os
|
||||||
|
data = json.load(open(os.environ["HEALTH_FILE"]))
|
||||||
active = int(data.get("activeMatches") or data.get("irc", {}).get("activeLobbies") or 0)
|
active = int(data.get("activeMatches") or data.get("irc", {}).get("activeLobbies") or 0)
|
||||||
if active:
|
if active:
|
||||||
raise SystemExit(f"{active} matches are still live. Drain them from the admin page, or set FORCE_DEPLOY=1.")
|
raise SystemExit(f"{active} matches are still live. Drain them from the admin page, or set FORCE_DEPLOY=1.")
|
||||||
@@ -107,20 +111,22 @@ backup_dir=/var/backups/esports
|
|||||||
backup_stamp=$(date -u +%Y%m%dT%H%M%SZ)
|
backup_stamp=$(date -u +%Y%m%dT%H%M%SZ)
|
||||||
backup_name="${environment_name}-${backup_stamp}-${sha}.dump"
|
backup_name="${environment_name}-${backup_stamp}-${sha}.dump"
|
||||||
sudo docker pull "$backup_image"
|
sudo docker pull "$backup_image"
|
||||||
sudo install -d -m 0700 "$backup_dir"
|
# The container runs as root, so it creates the directory and sets the modes.
|
||||||
sudo docker run --rm --network backend --env-file "$environment" \
|
sudo docker run --rm --network backend --env-file "$environment" \
|
||||||
--mount "type=bind,source=$backup_dir,target=/backups" \
|
--mount "type=bind,source=$(dirname "$backup_dir"),target=/backups" \
|
||||||
--env "BACKUP_FILE=$backup_name" "$backup_image" \
|
--env "BACKUP_FILE=$(basename "$backup_dir")/$backup_name" "$backup_image" \
|
||||||
sh -eu -c 'pg_dump --format=custom --no-owner --no-acl --file="/backups/$BACKUP_FILE" "${DB_URL:-$DATABASE_URL}"'
|
sh -eu -c 'mkdir -p -m 0700 "/backups/${BACKUP_FILE%/*}"
|
||||||
sudo docker run --rm --mount "type=bind,source=$backup_dir,target=/backups" \
|
pg_dump --format=custom --no-owner --no-acl --file="/backups/$BACKUP_FILE" "${DB_URL:-$DATABASE_URL}"
|
||||||
"$backup_image" pg_restore --list "/backups/$backup_name" >/dev/null
|
chmod 0600 "/backups/$BACKUP_FILE"
|
||||||
sudo chmod 0600 "$backup_dir/$backup_name"
|
pg_restore --list "/backups/$BACKUP_FILE" >/dev/null'
|
||||||
echo "Verified $environment_name database backup at $backup_dir/$backup_name"
|
echo "Verified $environment_name database backup at $backup_dir/$backup_name"
|
||||||
|
|
||||||
sudo docker run --rm --network backend --env-file "$environment" "$image" \
|
# The app's database role cannot create tables; the migrations file overrides
|
||||||
bun scripts/migrate.ts
|
# DATABASE_URL with the owner role and keeps the rest (ROOT_ADMIN_USER_ID).
|
||||||
|
sudo docker run --rm --network backend --env-file "$environment" \
|
||||||
|
--env-file "$migration_environment" "$image" bun scripts/migrate.ts
|
||||||
|
|
||||||
sudo sed -i "s/^IMAGE_TAG=.*/IMAGE_TAG=$sha/" "$directory/release.env"
|
write_release "$sha"
|
||||||
switched=1
|
switched=1
|
||||||
sudo docker compose --env-file "$directory/release.env" -f "$compose" up -d
|
sudo docker compose --env-file "$directory/release.env" -f "$compose" up -d
|
||||||
curl --retry 12 --retry-delay 2 --retry-all-errors --fail --silent --show-error \
|
curl --retry 12 --retry-delay 2 --retry-all-errors --fail --silent --show-error \
|
||||||
|
|||||||
Reference in New Issue
Block a user