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
fi
sudo install -d -m 0755 "$directory"
if [ ! -f "$directory/release.env" ]; then
printf 'IMAGE_TAG=%s\nHOST_PORT=%s\n' "$sha" "$host_port" | sudo tee "$directory/release.env" >/dev/null
fi
if ! grep -q '^HOST_PORT=' "$directory/release.env"; then
echo "HOST_PORT=$host_port" | sudo tee -a "$directory/release.env" >/dev/null
# The deploy user only has passwordless sudo for tee and docker.
if [ ! -d "$directory" ]; then
echo "$directory does not exist; create it once on the host" >&2
exit 1
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
services:
@@ -59,18 +61,17 @@ networks:
external: true
EOF
previous_tag=$(sed -n 's/^IMAGE_TAG=//p' "$directory/release.env" | head -n 1)
switched=0
rollback() {
if [ "$switched" -eq 1 ] && [ -n "$previous_tag" ]; then
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
fi
}
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
python3 - <<'PY'
import json
@@ -107,20 +108,20 @@ backup_dir=/var/backups/esports
backup_stamp=$(date -u +%Y%m%dT%H%M%SZ)
backup_name="${environment_name}-${backup_stamp}-${sha}.dump"
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" \
--mount "type=bind,source=$backup_dir,target=/backups" \
--env "BACKUP_FILE=$backup_name" "$backup_image" \
sh -eu -c 'pg_dump --format=custom --no-owner --no-acl --file="/backups/$BACKUP_FILE" "${DB_URL:-$DATABASE_URL}"'
sudo docker run --rm --mount "type=bind,source=$backup_dir,target=/backups" \
"$backup_image" pg_restore --list "/backups/$backup_name" >/dev/null
sudo chmod 0600 "$backup_dir/$backup_name"
--mount "type=bind,source=$(dirname "$backup_dir"),target=/backups" \
--env "BACKUP_FILE=$(basename "$backup_dir")/$backup_name" "$backup_image" \
sh -eu -c 'mkdir -p -m 0700 "/backups/${BACKUP_FILE%/*}"
pg_dump --format=custom --no-owner --no-acl --file="/backups/$BACKUP_FILE" "${DB_URL:-$DATABASE_URL}"
chmod 0600 "/backups/$BACKUP_FILE"
pg_restore --list "/backups/$BACKUP_FILE" >/dev/null'
echo "Verified $environment_name database backup at $backup_dir/$backup_name"
sudo docker run --rm --network backend --env-file "$environment" "$image" \
bun scripts/migrate.ts
sudo sed -i "s/^IMAGE_TAG=.*/IMAGE_TAG=$sha/" "$directory/release.env"
write_release "$sha"
switched=1
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 \