From 9e43ffa1c1aa0d8ab594df99507bdc2dac43cf9d Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Thu, 19 Feb 2026 21:45:56 -0600 Subject: [PATCH] feat: add local deploy script for production deploys Automates the SSH-to-akamai deploy workflow: pulls latest image, restarts the container, and verifies health. Includes pre-deploy checks (dirty git warning, confirmation prompt) and prints a rollback command if the image changed. Co-Authored-By: Claude Opus 4.6 --- .scripts/deploy.sh | 80 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100755 .scripts/deploy.sh diff --git a/.scripts/deploy.sh b/.scripts/deploy.sh new file mode 100755 index 0000000..a099692 --- /dev/null +++ b/.scripts/deploy.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# Deploy Discord Bot v2 to production (akamai) +# Pulls latest Docker image and restarts the container. +# +# Usage: .scripts/deploy.sh [-y] +# -y Skip confirmation prompt + +set -euo pipefail + +SSH_CMD="ssh -i ~/.ssh/cloud_servers_rsa root@akamai" +REMOTE_DIR="/root/container-data/major-domo" +SERVICE="discord-app" +CONTAINER="major-domo-discord-app-1" +IMAGE="manticorum67/major-domo-discordapp:latest" + +SKIP_CONFIRM=false +[[ "${1:-}" == "-y" ]] && SKIP_CONFIRM=true + +# --- Pre-deploy checks --- + +if [[ -n "$(git status --porcelain 2>/dev/null)" ]]; then + echo "WARNING: You have uncommitted changes." + git status --short + echo "" +fi + +BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown") +COMMIT=$(git log -1 --format='%h %s' 2>/dev/null || echo "unknown") +echo "Branch: ${BRANCH}" +echo "Latest: ${COMMIT}" +echo "Target: akamai (${IMAGE})" +echo "" + +if [[ "$SKIP_CONFIRM" != true ]]; then + read -rp "Deploy to production? [y/N] " answer + [[ "$answer" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 0; } + echo "" +fi + +# --- Save previous image for rollback --- + +PREV_DIGEST=$($SSH_CMD "docker inspect --format='{{index .RepoDigests 0}}' ${IMAGE} 2>/dev/null" || echo "unknown") + +# --- Deploy --- + +echo "==> Pulling latest image for ${SERVICE}..." +$SSH_CMD "cd ${REMOTE_DIR} && docker compose pull ${SERVICE}" + +echo "==> Restarting ${SERVICE}..." +$SSH_CMD "cd ${REMOTE_DIR} && docker compose up -d ${SERVICE}" + +echo "==> Waiting 5s for container to start..." +sleep 5 + +echo "==> Container status:" +$SSH_CMD "docker ps --filter name=${CONTAINER} --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}'" + +echo "" +echo "==> Last 10 log lines:" +$SSH_CMD "docker logs --tail 10 ${CONTAINER}" + +NEW_DIGEST=$($SSH_CMD "docker inspect --format='{{index .RepoDigests 0}}' ${IMAGE} 2>/dev/null || docker inspect --format='{{.Image}}' ${CONTAINER}") +echo "" +echo "==> Image digest: ${NEW_DIGEST}" + +if [[ "$PREV_DIGEST" == "$NEW_DIGEST" ]]; then + echo " (unchanged from previous deploy)" +fi + +# --- Rollback command --- + +if [[ "$PREV_DIGEST" != "unknown" && "$PREV_DIGEST" != "$NEW_DIGEST" ]]; then + echo "" + echo "==> To rollback:" + echo " ssh -i ~/.ssh/cloud_servers_rsa root@akamai \\" + echo " \"cd ${REMOTE_DIR} && docker pull ${PREV_DIGEST} && docker tag ${PREV_DIGEST} ${IMAGE} && docker compose up -d ${SERVICE}\"" +fi + +echo "" +echo "Deploy complete." -- 2.25.1