From 942875e8d01194dde7998e0499e2c3773c038ecf Mon Sep 17 00:00:00 2001 From: syntaxbullet Date: Fri, 13 Feb 2026 14:46:30 +0100 Subject: [PATCH] fix: replace 'source .env' with safe env loader in all scripts The raw 'source .env' pattern breaks when values contain special bash characters like ) in passwords or database URLs. This caused deploy:remote to fail with 'syntax error near unexpected token )'. Changes: - Created shared/scripts/lib/load-env.sh: reads .env line-by-line with export instead of source, safely handling special characters - Updated db-backup.sh, db-restore.sh, deploy-remote.sh, remote.sh to use the shared loader - Reordered deploy-remote.sh: git pull now runs first (step 1) so the remote always has the latest scripts before running backup (step 2) --- shared/scripts/db-backup.sh | 11 ++++------ shared/scripts/db-restore.sh | 10 +++------ shared/scripts/deploy-remote.sh | 24 ++++++++++----------- shared/scripts/lib/load-env.sh | 38 +++++++++++++++++++++++++++++++++ shared/scripts/remote.sh | 10 ++++----- 5 files changed, 60 insertions(+), 33 deletions(-) create mode 100644 shared/scripts/lib/load-env.sh diff --git a/shared/scripts/db-backup.sh b/shared/scripts/db-backup.sh index d898255..d207fd0 100755 --- a/shared/scripts/db-backup.sh +++ b/shared/scripts/db-backup.sh @@ -9,14 +9,11 @@ set -e -# Load environment variables -if [ -f .env ]; then - set -a - source .env - set +a -fi - +# Load environment variables safely SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/lib/load-env.sh" +load_env + PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" BACKUP_DIR="$PROJECT_DIR/shared/db/backups" TIMESTAMP=$(date +%Y%m%d_%H%M%S) diff --git a/shared/scripts/db-restore.sh b/shared/scripts/db-restore.sh index d9d785a..6a783ee 100755 --- a/shared/scripts/db-restore.sh +++ b/shared/scripts/db-restore.sh @@ -10,14 +10,10 @@ set -e -# Load environment variables -if [ -f .env ]; then - set -a - source .env - set +a -fi - +# Load environment variables safely SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/lib/load-env.sh" +load_env # Colors GREEN='\033[0;32m' diff --git a/shared/scripts/deploy-remote.sh b/shared/scripts/deploy-remote.sh index 9a79ce9..8e81f0c 100755 --- a/shared/scripts/deploy-remote.sh +++ b/shared/scripts/deploy-remote.sh @@ -10,12 +10,10 @@ set -e -# Load environment variables -if [ -f .env ]; then - set -a - source .env - set +a -fi +# Load environment variables safely +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/lib/load-env.sh" +load_env # Colors GREEN='\033[0;32m' @@ -41,22 +39,22 @@ fi echo -e "${YELLOW}🚀 Deploying to $VPS_USER@$VPS_HOST:$REMOTE_DIR...${NC}" -# Step 1: Database backup (unless skipped) +# Step 1: Pull latest code (always first, so remote has the latest scripts) +echo -e "\n${YELLOW}⬇️ Step 1/4: Pulling latest changes...${NC}" +ssh -t "$VPS_USER@$VPS_HOST" "cd $REMOTE_DIR && git pull" + +# Step 2: Database backup (unless skipped) if [ "$SKIP_BACKUP" = false ]; then - echo -e "\n${YELLOW}💾 Step 1/4: Backing up remote database...${NC}" + echo -e "\n${YELLOW}💾 Step 2/4: Backing up remote database...${NC}" ssh -t "$VPS_USER@$VPS_HOST" "cd $REMOTE_DIR && bash shared/scripts/db-backup.sh" || { echo -e "${RED}⚠️ Backup failed. Aborting deployment.${NC}" echo "Use --skip-backup to deploy without backing up." exit 1 } else - echo -e "\n${YELLOW}⏭️ Step 1/4: Skipping database backup (--skip-backup)${NC}" + echo -e "\n${YELLOW}⏭️ Step 2/4: Skipping database backup (--skip-backup)${NC}" fi -# Step 2: Pull latest code -echo -e "\n${YELLOW}⬇️ Step 2/4: Pulling latest changes...${NC}" -ssh -t "$VPS_USER@$VPS_HOST" "cd $REMOTE_DIR && git pull" - # Step 3: Build production containers echo -e "\n${YELLOW}🏗️ Step 3/4: Building production containers...${NC}" ssh -t "$VPS_USER@$VPS_HOST" "cd $REMOTE_DIR && docker compose -f docker-compose.prod.yml build" diff --git a/shared/scripts/lib/load-env.sh b/shared/scripts/lib/load-env.sh new file mode 100644 index 0000000..f902781 --- /dev/null +++ b/shared/scripts/lib/load-env.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# ============================================================================= +# Shared .env loader for Aurora scripts +# ============================================================================= +# Safely loads .env files without using `source`, which breaks on values +# containing special bash characters like ), (, !, etc. +# +# Usage: source shared/scripts/lib/load-env.sh +# load_env # loads .env from current directory +# load_env .env.test # loads a specific file +# ============================================================================= + +load_env() { + local env_file="${1:-.env}" + + if [ ! -f "$env_file" ]; then + return 0 + fi + + while IFS= read -r line || [ -n "$line" ]; do + # Skip comments and empty lines + [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue + + # Skip lines without an = sign + [[ "$line" != *"="* ]] && continue + + # Strip leading/trailing whitespace + line="${line#"${line%%[![:space:]]*}"}" + + # Remove surrounding quotes from the value (KEY="value" → KEY=value) + local key="${line%%=*}" + local value="${line#*=}" + value="${value#\"}" ; value="${value%\"}" + value="${value#\'}" ; value="${value%\'}" + + export "$key=$value" + done < "$env_file" +} diff --git a/shared/scripts/remote.sh b/shared/scripts/remote.sh index 83b8f90..41ff655 100755 --- a/shared/scripts/remote.sh +++ b/shared/scripts/remote.sh @@ -9,12 +9,10 @@ # Usage: ./remote.sh # ============================================================================= -# Load environment variables -if [ -f .env ]; then - set -a - source .env - set +a -fi +# Load environment variables safely +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/lib/load-env.sh" +load_env if [ -z "$VPS_HOST" ] || [ -z "$VPS_USER" ]; then echo "Error: VPS_HOST and VPS_USER must be set in .env"