fix: deploy with only sudo tee and docker
Some checks failed
Test and deploy staging / staging (push) Failing after 16s

The deploy user has passwordless sudo for tee and docker only, so the
script stopped at its first sudo install. release.env is rewritten with
tee, and the backup container creates the backup directory and sets the
file modes itself. HOST_PORT comes from the target, not release.env.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-18 22:37:50 +00:00
parent d5448d9a94
commit 6ff5fe53c5

View File

@@ -25,13 +25,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,18 +61,17 @@ 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 if [ "${FORCE_DEPLOY:-}" != 1 ] && curl --fail --silent --show-error "http://127.0.0.1:${port}/api/health" > /tmp/esports-health.json; then
python3 - <<'PY' python3 - <<'PY'
import json import json
@@ -107,20 +108,20 @@ 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" \ sudo docker run --rm --network backend --env-file "$environment" "$image" \
bun scripts/migrate.ts 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 \