Files
mtc-project-sync-script/sync-git-project.sh

426 lines
14 KiB
Bash
Executable File

#!/bin/bash
# This script is used to clone a project from a remote server
# and perform full project setup including Docker, environment,
# SSH keys, and database synchronization.
# Called by sync-project.sh with --git flag.
# Get current script real directory (follow symlinks)
SCRIPT_PATH="$(realpath "$0")"
SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
# Source shared variables
source "$SCRIPT_DIR/shared.sh"
# Arguments: SERVER_HOST SSH_PASSWORD SERVER_PROJECT_PATH LOCAL_FOLDER
SERVER_HOST="$1"
SSH_PASSWORD="$2"
SERVER_PROJECT_PATH="$3"
LOCAL_FOLDER="$4"
# Validate arguments
if [ -z "$SERVER_HOST" ] || [ -z "$SSH_PASSWORD" ] || [ -z "$SERVER_PROJECT_PATH" ] || [ -z "$LOCAL_FOLDER" ]; then
echo -e "${RED}Usage: sync-git-project.sh SERVER_HOST SSH_PASSWORD SERVER_PROJECT_PATH LOCAL_FOLDER${NC}"
exit 1
fi
# Extract username and host from SERVER_HOST
USERNAME="${SERVER_HOST%@*}"
HOST="${SERVER_HOST#*@}"
# ============================================================
# STEP 1: Clone Fork
# ============================================================
echo -e "${BLUE}=== Step 1: Cloning Repository ===${NC}"
GIT_SSH_COMMAND="sshpass -p '${SSH_PASSWORD}' ssh $SSH_OPTS" \
git clone ${SERVER_HOST}:${SERVER_PROJECT_PATH} "${LOCAL_FOLDER}"
if [ $? -ne 0 ]; then
echo -e "${RED}Failed to clone repository${NC}"
echo -e "${YELLOW}Check that:${NC}"
echo " - SSH credentials are correct"
echo " - Repository exists at ${SERVER_PROJECT_PATH}"
echo " - You have access to the server"
exit 1
fi
echo -e "${GREEN}Repository cloned successfully${NC}"
# Change into project directory
cd "${LOCAL_FOLDER}"
# Check for .npmrc
if [ ! -f ".npmrc" ]; then
pause_for_user ".npmrc file not found! Please add .npmrc file to the project root before continuing."
fi
echo -e "${GREEN}Step 1 complete${NC}"
# ============================================================
# STEP 2: Copy Docker Env File
# ============================================================
echo -e "${BLUE}=== Step 2: Copying Docker Env File ===${NC}"
if [ -f ".docker/config/.env.local" ]; then
cp ".docker/config/.env.local" ".env"
echo -e "${GREEN}.env copied from .docker/config/.env.local${NC}"
else
echo -e "${RED}.docker/config/.env.local not found!${NC}"
pause_for_user "Please ensure .docker/config/.env.local exists before continuing."
# Re-check after user resolves
if [ -f ".docker/config/.env.local" ]; then
cp ".docker/config/.env.local" ".env"
echo -e "${GREEN}.env copied from .docker/config/.env.local${NC}"
else
echo -e "${RED}Still no .docker/config/.env.local - continuing without it${NC}"
fi
fi
echo -e "${GREEN}Step 2 complete${NC}"
# ============================================================
# STEP 3: Clean Docker Volumes
# ============================================================
echo -e "${BLUE}=== Step 3: Cleaning Docker Volumes ===${NC}"
echo "Stopping all containers..."
docker stop $(docker ps -aq) 2>/dev/null || true
echo "Removing all containers..."
docker rm $(docker ps -aq) 2>/dev/null || true
echo "Removing all volumes..."
docker volume rm $(docker volume ls -q) 2>/dev/null || true
echo -e "${GREEN}Docker volumes cleaned${NC}"
echo -e "${GREEN}Step 3 complete${NC}"
# ============================================================
# STEP 4: Run docker-setup.sh
# ============================================================
echo -e "${BLUE}=== Step 4: Running docker-setup.sh ===${NC}"
if [ -f "docker-setup.sh" ]; then
echo "Running docker-setup.sh..."
sh docker-setup.sh
if [ $? -ne 0 ]; then
echo -e "${YELLOW}docker-setup.sh exited with non-zero status${NC}"
pause_for_user "Please check docker-setup.sh output and resolve any issues."
else
echo -e "${GREEN}docker-setup.sh completed successfully${NC}"
fi
else
echo -e "${YELLOW}docker-setup.sh not found in project!${NC}"
pause_for_user "No docker-setup.sh found. Please set up Docker manually if needed."
fi
echo -e "${GREEN}Step 4 complete${NC}"
# ============================================================
# STEP 5: Copy Server .env
# ============================================================
echo -e "${BLUE}=== Step 5: Copying Server .env ===${NC}"
sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS ${SERVER_HOST}:${SERVER_PROJECT_PATH}/.env .server.env
if [ $? -ne 0 ]; then
echo -e "${RED}Failed to copy server .env file${NC}"
pause_for_user "Please ensure .env exists on server at ${SERVER_PROJECT_PATH}/.env"
# Retry after user resolves
sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS ${SERVER_HOST}:${SERVER_PROJECT_PATH}/.env .server.env
if [ $? -ne 0 ]; then
echo -e "${RED}Still cannot copy server .env - continuing without it${NC}"
fi
fi
if [ -f ".server.env" ]; then
git update-index --assume-unchanged .server.env 2>/dev/null || true
echo -e "${GREEN}Server .env copied to .server.env and marked as assume-unchanged${NC}"
fi
echo -e "${GREEN}Step 5 complete${NC}"
# ============================================================
# STEP 6: Modify Local .env
# ============================================================
echo -e "${BLUE}=== Step 6: Modifying Local .env ===${NC}"
if [ -f ".server.env" ] && [ -f ".env" ]; then
# Extract values from server env
APP_NAME=$(get_env_value ".server.env" "APP_NAME")
APP_KEY=$(get_env_value ".server.env" "APP_KEY")
if [ -n "$APP_NAME" ]; then
set_env_value ".env" "APP_NAME" "$APP_NAME"
echo -e "${GREEN}Set APP_NAME=${APP_NAME}${NC}"
else
echo -e "${YELLOW}APP_NAME not found in .server.env${NC}"
fi
if [ -n "$APP_KEY" ]; then
set_env_value ".env" "APP_KEY" "$APP_KEY"
echo -e "${GREEN}Set APP_KEY${NC}"
else
echo -e "${YELLOW}APP_KEY not found in .server.env${NC}"
fi
else
echo -e "${YELLOW}Skipping .env modification - missing .server.env or .env${NC}"
fi
echo -e "${GREEN}Step 6 complete${NC}"
# ============================================================
# STEP 7: Create .env.prod.local
# ============================================================
echo -e "${BLUE}=== Step 7: Creating .env.prod.local ===${NC}"
if [ -f ".server.env" ]; then
# Extract database credentials from server env
DB_DATABASE=$(get_env_value ".server.env" "DB_DATABASE")
DB_USERNAME=$(get_env_value ".server.env" "DB_USERNAME")
DB_PASSWORD=$(get_env_value ".server.env" "DB_PASSWORD")
cat > .env.prod.local << EOF
PROD_HOST="${HOST}"
PROD_USER="${USERNAME}"
PROD_DB_NAME="${DB_DATABASE}"
PROD_DB_USER="${DB_USERNAME}"
PROD_DB_PASS="${DB_PASSWORD}"
EOF
echo -e "${GREEN}.env.prod.local created with production credentials${NC}"
else
echo -e "${YELLOW}Skipping .env.prod.local creation - .server.env not found${NC}"
fi
echo -e "${GREEN}Step 7 complete${NC}"
# ============================================================
# STEP 8: Add Helper Scripts
# ============================================================
echo -e "${BLUE}=== Step 8: Adding Helper Scripts ===${NC}"
# Define scripts to generate
scripts=("ssh.sh")
for script in "${scripts[@]}"; do
# Create script with variables header
cat > "${script}" << EOF
#!/bin/bash
set -e
# Configuration
SERVER_USER="${USERNAME}"
SERVER_HOST="${HOST}"
SERVER_PASSWORD="${SSH_PASSWORD}"
SERVER_PATH="${SERVER_PROJECT_PATH}/"
REMOTE_PROGRESS=".remote-in-progress"
EOF
# Append the template content
cat "${SCRIPT_DIR}/scripts/${script}" >> "${script}"
# Make executable
chmod +x "${script}"
echo -e "${GREEN}${script} created successfully${NC}"
# Add to .gitignore
add_to_gitignore "${script}"
done
echo -e "${GREEN}Step 8 complete${NC}"
# ============================================================
# STEP 9: Upload lazygit
# ============================================================
echo -e "${BLUE}=== Step 9: Uploading lazygit ===${NC}"
sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS "${SCRIPT_DIR}/lazygit" ${SERVER_HOST}:${SERVER_PROJECT_PATH}
if [ $? -ne 0 ]; then
echo -e "${RED}Failed to upload lazygit${NC}"
pause_for_user "Please check server connectivity and permissions."
else
echo -e "${GREEN}lazygit uploaded successfully${NC}"
# Mark lazygit as assume-unchanged on server
echo "Marking lazygit as assume-unchanged on server..."
sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} \
"cd ${SERVER_PROJECT_PATH} && git update-index --assume-unchanged lazygit"
# Pull to get lazygit locally, then mark as assume-unchanged
echo "Syncing and marking lazygit as assume-unchanged locally..."
GIT_SSH_COMMAND="sshpass -p '${SSH_PASSWORD}' ssh $SSH_OPTS" git pull
git update-index --assume-unchanged lazygit
echo -e "${GREEN}lazygit configured successfully${NC}"
fi
echo -e "${GREEN}Step 9 complete${NC}"
# ============================================================
# STEP 10: SSH Key Management
# ============================================================
echo -e "${BLUE}=== Step 10: SSH Key Management ===${NC}"
# Check server state for SSH keys
HAS_PRIVATE=$(sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} "test -f ~/.ssh/id_rsa && echo 'yes' || echo 'no'")
HAS_PUBLIC=$(sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} "test -f ~/.ssh/id_rsa.pub && echo 'yes' || echo 'no'")
echo "Server SSH key state: private=$HAS_PRIVATE, public=$HAS_PUBLIC"
if [ "$HAS_PRIVATE" = "no" ] && [ "$HAS_PUBLIC" = "yes" ]; then
# Case A: Server has ONLY public key (no private)
echo -e "${YELLOW}Case A: Server has only public key - generating new keypair${NC}"
# Generate new keypair locally
ssh-keygen -t rsa -b 4096 -f staging.key -N "" -q
# Upload both keys to server
sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS staging.key ${SERVER_HOST}:~/.ssh/id_rsa
sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS staging.key.pub ${SERVER_HOST}:~/.ssh/id_rsa.pub
# Set correct permissions on server
sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} "chmod 600 ~/.ssh/id_rsa && chmod 644 ~/.ssh/id_rsa.pub"
# Add public key to authorized_keys
sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} \
"cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
# Clean up local public key
rm -f staging.key.pub
echo -e "${GREEN}New keypair generated and uploaded to server${NC}"
elif [ "$HAS_PRIVATE" = "yes" ] && [ "$HAS_PUBLIC" = "yes" ]; then
# Case B: Server has BOTH keys
echo -e "${YELLOW}Case B: Server has both keys - downloading private key${NC}"
# Check if public key is in authorized_keys
IN_AUTH=$(sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} \
"grep -qf ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys 2>/dev/null && echo 'yes' || echo 'no'")
if [ "$IN_AUTH" = "no" ]; then
echo "Adding public key to authorized_keys..."
sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} \
"cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
fi
# Download private key
sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS ${SERVER_HOST}:~/.ssh/id_rsa staging.key
chmod 600 staging.key
echo -e "${GREEN}Private key downloaded as staging.key${NC}"
else
# Case C: Server has NEITHER key (or only private, which is unusual)
echo -e "${YELLOW}Case C: Server missing keys - generating new keypair${NC}"
# Generate new keypair locally
ssh-keygen -t rsa -b 4096 -f staging.key -N "" -q
# Create .ssh directory on server if needed
sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} "mkdir -p ~/.ssh && chmod 700 ~/.ssh"
# Upload both keys to server
sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS staging.key ${SERVER_HOST}:~/.ssh/id_rsa
sshpass -p "${SSH_PASSWORD}" scp $SSH_OPTS staging.key.pub ${SERVER_HOST}:~/.ssh/id_rsa.pub
# Set correct permissions on server
sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} "chmod 600 ~/.ssh/id_rsa && chmod 644 ~/.ssh/id_rsa.pub"
# Add public key to authorized_keys (create if doesn't exist)
sshpass -p "${SSH_PASSWORD}" ssh $SSH_OPTS ${SERVER_HOST} \
"cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
# Clean up local public key
rm -f staging.key.pub
echo -e "${GREEN}New keypair generated and uploaded to server${NC}"
fi
# Add staging.key to .gitignore and mark as assume-unchanged
if [ -f "staging.key" ]; then
add_to_gitignore "staging.key"
git update-index --assume-unchanged staging.key 2>/dev/null || true
echo -e "${GREEN}staging.key marked as assume-unchanged${NC}"
fi
echo -e "${GREEN}Step 10 complete${NC}"
# ============================================================
# STEP 11: SSH-Add
# ============================================================
echo -e "${BLUE}=== Step 11: Adding SSH Key to Agent ===${NC}"
if [ -f "staging.key" ]; then
ssh-add ./staging.key 2>/dev/null
if [ $? -ne 0 ]; then
echo -e "${YELLOW}Failed to add staging.key to SSH agent${NC}"
echo "This may happen if ssh-agent is not running."
echo "You can start it with: eval \$(ssh-agent -s)"
echo "Then run: ssh-add ./staging.key"
pause_for_user "Please ensure SSH agent is running and add the key manually if needed."
else
echo -e "${GREEN}staging.key added to SSH agent${NC}"
fi
else
echo -e "${YELLOW}staging.key not found - skipping ssh-add${NC}"
fi
echo -e "${GREEN}Step 11 complete${NC}"
# ============================================================
# STEP 12: Database Setup
# ============================================================
echo -e "${BLUE}=== Step 12: Database Setup ===${NC}"
# Wipe local database
echo "Wiping local database..."
docker exec mtc-pharmacy-web php artisan db:wipe
if [ $? -ne 0 ]; then
echo -e "${YELLOW}Failed to wipe database${NC}"
echo "This may happen if Docker container is not running."
pause_for_user "Please ensure mtc-pharmacy-web container is running."
# Retry
docker exec mtc-pharmacy-web php artisan db:wipe
fi
# Sync database from staging
echo "Syncing database from staging..."
make db-sync
if [ $? -ne 0 ]; then
echo -e "${YELLOW}make db-sync failed${NC}"
pause_for_user "Please check Makefile and database connection settings."
else
echo -e "${GREEN}Database synced successfully${NC}"
fi
echo -e "${GREEN}Step 12 complete${NC}"
# ============================================================
# COMPLETE
# ============================================================
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Project Setup Complete!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo "Project cloned to: ${LOCAL_FOLDER}"
echo "SSH key: ./staging.key"
echo ""
echo "Available commands:"
echo " ./ssh.sh - SSH into server"
echo " ./ssh.sh --git - Run lazygit on server"
echo " ./ssh.sh --db - Forward database port"
echo ""
exit 0