426 lines
14 KiB
Bash
Executable File
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
|