#!/usr/bin/env bash # # rollback.sh — Roll back to the previously deployed commit. # # Usage: # rollback.sh # roll back to .last-deployed-sha # rollback.sh # roll back to a specific commit # # .env is gitignored and is never touched by git operations. It survives # updates and rollbacks unchanged. # # Must be run as root (uses runuser to build as the service user). set -euo pipefail INSTALL_DIR="${ZOPU_INSTALL_DIR:-/opt/zopu}" SERVICE_USER="${ZOPU_SERVICE_USER:-zopu}" GREEN='\033[0;32m' RED='\033[0;31m' NC='\033[0m' log() { echo -e "${GREEN}[rollback]${NC} $*"; } err() { echo -e "${RED}[rollback]${NC} $*" >&2; } run_as_service() { runuser -u "$SERVICE_USER" -- "$@" } cd "$INSTALL_DIR" # Determine target ROLLBACK_SHA="${1:-}" if [[ -z "$ROLLBACK_SHA" ]]; then LAST_SHA_FILE="${INSTALL_DIR}/.last-deployed-sha" if [[ ! -f "$LAST_SHA_FILE" ]]; then err "No previous deployment recorded in ${LAST_SHA_FILE}." err "Pass a commit SHA explicitly: rollback.sh " exit 1 fi ROLLBACK_SHA=$(cat "$LAST_SHA_FILE") fi # Validate commit exists if ! git rev-parse --verify "${ROLLBACK_SHA}^{commit}" &>/dev/null; then err "Commit ${ROLLBACK_SHA} does not exist in the local repository." exit 1 fi CURRENT_SHA=$(git rev-parse HEAD) log "Current: ${CURRENT_SHA:0:12}" log "Rolling back to: ${ROLLBACK_SHA:0:12}" # Save current state before rolling back (enables re-rollback) echo "$CURRENT_SHA" > "${INSTALL_DIR}/.pre-rollback-sha" # Checkout target git checkout "$ROLLBACK_SHA" # Restore ownership of the checkout to the service user after git operations log "Setting ownership of checkout to $SERVICE_USER..." chown -R "$SERVICE_USER":"$SERVICE_USER" "$INSTALL_DIR" # Confirm .env is intact and has correct permissions if [[ -f "${INSTALL_DIR}/.env" ]]; then log ".env preserved." chmod 600 "${INSTALL_DIR}/.env" else err ".env is missing! Restore it from backup before starting services." fi log "Running bun install..." run_as_service bun install log "Building daemon..." run_as_service bun run build:daemon log "Building agent service..." run_as_service bun run build:agents log "Restarting services..." systemctl restart zopu-daemon sleep 3 systemctl restart zopu-agent sleep 5 # Health check HEALTH_SCRIPT="${INSTALL_DIR}/deploy/zopu-runtime/scripts/health-check.sh" if [[ -x "$HEALTH_SCRIPT" ]]; then log "Running health check..." if "$HEALTH_SCRIPT"; then log "Rollback complete and healthy." else err "Health check failed after rollback!" err " journalctl -u zopu-daemon -n 50" err " journalctl -u zopu-agent -n 50" exit 1 fi fi