#!/bin/bash set -euo pipefail # Main deployment script with versioned releases # Usage: ./deploy-to-server.sh # Source retry function SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/retry.sh" # Required environment variables (should be set by GitHub Actions) : "${DOCKER_HOST:?Error: DOCKER_HOST not set}" : "${REPO_PROJECT_PATH:?Error: REPO_PROJECT_PATH not set}" : "${REPO_NAME_ONLY:?Error: REPO_NAME_ONLY not set}" : "${IMAGE_TAR:?Error: IMAGE_TAR not set}" : "${ENV_FILE_BASE64:?Error: ENV_FILE_BASE64 not set}" : "${CF_PEM_CERT:?Error: CF_PEM_CERT not set}" : "${CF_PEM_CA:?Error: CF_PEM_CA not set}" : "${PROD:?Error: PROD not set}" echo "โš™๏ธ Docker host: $DOCKER_HOST" # Generate deployment timestamp DEPLOYMENT_TIMESTAMP=$(date +%Y%m%d_%H%M%S) RELEASES_PATH="${REPO_PROJECT_PATH}/releases" NEW_RELEASE_PATH="${RELEASES_PATH}/${DEPLOYMENT_TIMESTAMP}" CURRENT_LINK_PATH="${REPO_PROJECT_PATH}/current" echo "๐Ÿ“… Deployment version: ${DEPLOYMENT_TIMESTAMP}" echo "๐Ÿš€ Enable and start docker service" retry ssh deploy "sudo systemctl enable --now docker.service" echo "๐Ÿ’พ Load the new docker image ($IMAGE_TAR)" if [ ! -f "$IMAGE_TAR" ]; then echo "Error: Docker image tar file not found: $IMAGE_TAR" exit 1 fi retry docker load -i "$IMAGE_TAR" echo "๐Ÿ“ Create versioned release directory" ssh deploy "mkdir -p '${NEW_RELEASE_PATH}'" echo "๐Ÿ’พ Copy new files to server" # Check if server directory exists before copying if [ -d "./server" ]; then retry scp -pr ./server/* "deploy:${NEW_RELEASE_PATH}/" else echo "โš ๏ธ No server directory found, error" exit 1 fi echo "๐Ÿ“ Create new .env file" printf "%s" "${ENV_FILE_BASE64}" | base64 -d | ssh deploy "cat > '${NEW_RELEASE_PATH}/.env' && chmod 600 '${NEW_RELEASE_PATH}/.env'" echo "๐Ÿ”‘ Set up certs" ssh deploy "mkdir -p '${NEW_RELEASE_PATH}/certs' && chmod 550 '${NEW_RELEASE_PATH}/certs' && chown 99:root '${NEW_RELEASE_PATH}/certs'" printf "%s" "$CF_PEM_CERT" | ssh deploy "cat > '${NEW_RELEASE_PATH}/certs/crt.pem' && chmod 440 '${NEW_RELEASE_PATH}/certs/crt.pem' && chown 99:root '${NEW_RELEASE_PATH}/certs/crt.pem'" printf "%s" "$CF_PEM_CA" | ssh deploy "cat > '${NEW_RELEASE_PATH}/certs/ca.pem' && chmod 440 '${NEW_RELEASE_PATH}/certs/ca.pem' && chown 99:root '${NEW_RELEASE_PATH}/certs/ca.pem'" echo "๐Ÿ”„ Prepare deployment (stop current containers)" # Copy script to remote and execute with parameters scp "${SCRIPT_DIR}/prepare-deployment.sh" deploy:/tmp/ ssh deploy "chmod +x /tmp/prepare-deployment.sh && /tmp/prepare-deployment.sh '${REPO_PROJECT_PATH}' '${PROD}' '${CURRENT_LINK_PATH}'" ssh deploy "rm -f /tmp/prepare-deployment.sh" echo "๐Ÿ“ Save deployment metadata" ssh deploy "echo '${DEPLOYMENT_TIMESTAMP}' > '${NEW_RELEASE_PATH}/.deployment_version'" ssh deploy "echo '${PROD}' > '${NEW_RELEASE_PATH}/.deployment_env'" # Save previous version info for potential rollback ssh deploy "if [ -L '${CURRENT_LINK_PATH}' ]; then readlink -f '${CURRENT_LINK_PATH}' > '${NEW_RELEASE_PATH}/.previous_version'; fi" echo "๐Ÿ”— Update current symlink to new release" ssh deploy "ln -sfn '${NEW_RELEASE_PATH}' '${CURRENT_LINK_PATH}'" # TODO: implement zero-downtime deployment # echo "๐Ÿš€ Start the new containers, zero-downtime" # if [ "${PROD}" = true ]; then # ssh deploy </dev/null | tail -n +6 | xargs -r rm -rf || true" echo "โœ… Deployment completed. Version: ${DEPLOYMENT_TIMESTAMP}"