Menu
Public repository / master
AkurAI-Drive / backend/deploy.sh
Latest change d63e826eb482cb963477774b04fe8a84f23f0e45 - deploy: in-place swaps matching live units with health-checked rollback; no unit rewrites by AkurAI Agent
#!/usr/bin/env bash
# Deploy rules of conduct:
# - Read AGENTS.md and canonical Notes/docs before changing or deploying.
# - Never print, commit, or copy secrets; use passvault/env files only.
# - Preserve env files, service users, user data, and databases; snapshot state before risky swaps.
# - Verify ports, DNS, TLS, and systemd unit names before changing routes or services.
# - Use managed services only (systemd/pm2); no nohup, background shells, or ad hoc daemons.
# - Run gates and health checks; if deploy fails, stop and roll back rather than improvising.
#
# Live layout (systemd unit akurai-drive-api, owned by the host, NOT managed here):
# binary /opt/akurai-drive-api/bin/akurai-drive-api (User=drive)
# env /etc/akurai-drive-api.env (never read or written here)
# Swaps the binary in place (previous kept as .prev), restarts, health-checks
# /api/health and rolls back on failure.
set -euo pipefail
SSH_HOST="${AKURAI_MAIL_SSH:-akurai-ec2}"
SERVICE="akurai-drive-api"
TARGET="x86_64-unknown-linux-musl"
PORT="${DRIVE_PORT:-8096}"
log() { echo "[deploy] $*"; }
step() { echo; echo "── $* ──"; }
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
BINARY_PATH="${DRIVE_API_BINARY:-}"
while (($#)); do
case "$1" in
--binary)
BINARY_PATH="${2:?--binary requires a path}"
shift 2
;;
*)
echo "usage: $0 [--binary PATH]" >&2
exit 2
;;
esac
done
if [[ -n "$BINARY_PATH" && "$BINARY_PATH" != /* ]]; then
BINARY_PATH="$ROOT_DIR/$BINARY_PATH"
fi
if [[ -n "$BINARY_PATH" ]]; then
BINARY="$BINARY_PATH"
else
step "Build (musl static)"
(cd "$SCRIPT_DIR" && CC_x86_64_unknown_linux_musl=musl-gcc cargo build --release --target "$TARGET")
BINARY="$SCRIPT_DIR/target/$TARGET/release/akurai-drive-api"
fi
test -x "$BINARY"
log "Binary: $(du -sh "$BINARY" | cut -f1)"
STAGE="/tmp/akurai-drive-api-$(date +%Y%m%d%H%M%S)"
step "Upload"
scp -q "$BINARY" "$SSH_HOST:$STAGE"
step "Swap, restart, health-check (rollback on failure)"
ssh "$SSH_HOST" "sudo bash -s -- '$STAGE' '$PORT'" <<'REMOTE'
set -euo pipefail
stage="$1"; port="$2"
bin=/opt/akurai-drive-api/bin/akurai-drive-api
service=akurai-drive-api
healthy() {
for _ in $(seq 1 20); do
curl -fsS -o /dev/null "http://127.0.0.1:$port/api/health" && return 0
sleep 1
done
return 1
}
test -x "$bin"
cp -a "$bin" "$bin.prev"
install -m 755 "$stage" "$bin.new"
mv -f "$bin.new" "$bin"
rm -f "$stage"
systemctl restart "$service"
if healthy; then
echo " [ok] $service healthy"
exit 0
fi
echo " [FAIL] health check failed; rolling back" >&2
cp -a "$bin.prev" "$bin"
systemctl restart "$service"
if healthy; then echo " [rollback] previous binary healthy" >&2; else echo " [rollback] STILL UNHEALTHY" >&2; fi
exit 1
REMOTE
log "Deployed $SERVICE to $SSH_HOST (port $PORT; previous at bin/akurai-drive-api.prev)"