Files
mwitnessing/_deploy/webhook-deploy.sh
2025-04-10 03:02:30 +03:00

152 lines
5.4 KiB
Bash

#!/bin/bash
# Webhook deployment script
# This script is triggered by the webhook receiver when a push event is received
set -e
# Configuration
APP_DIR="/app" # Application directory
REPO_URL="https://git.d-popov.com/popov/mwitnessing.git" # Git repository URL
GIT_USERNAME="${GIT_USERNAME:-deploy}" # Git username
GIT_PASSWORD="${GIT_PASSWORD:-}" # Git password
DOCKER_COMPOSE_FILE="${DOCKER_COMPOSE_FILE:-_deploy/standard-docker-compose.yml}" # Docker Compose file
LOG_FILE="${LOG_FILE:-/app/logs/webhook-deploy.log}" # Log file
# Create log directory if it doesn't exist
mkdir -p "$(dirname "$LOG_FILE")"
# Function to log messages
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Get the branch name from the first argument or use main as default
BRANCH="${1:-main}"
log "Starting deployment for branch: $BRANCH"
# Create a temporary directory for the Git clone
TEMP_DIR=$(mktemp -d)
log "Using temporary directory: $TEMP_DIR"
# Clean up function to remove the temporary directory on exit
cleanup() {
log "Cleaning up temporary directory"
rm -rf "$TEMP_DIR"
}
trap cleanup EXIT
# Clone the repository
log "Cloning repository: $REPO_URL (branch: $BRANCH)"
if [ -n "$GIT_PASSWORD" ]; then
# Use authentication with username and password
AUTH_URL="${REPO_URL/https:\/\//https:\/\/$GIT_USERNAME:$GIT_PASSWORD@}"
git clone -b "$BRANCH" --depth 1 "$AUTH_URL" "$TEMP_DIR"
else
# Use authentication with SSH keys
git clone -b "$BRANCH" --depth 1 "$REPO_URL" "$TEMP_DIR"
fi
# Navigate to the cloned repository
cd "$TEMP_DIR"
# Backup important directories
log "Backing up important directories"
mkdir -p "/tmp/webhook_backup/permits" "/tmp/webhook_backup/uploads"
if [ -d "$APP_DIR/public/content/permits" ]; then
cp -r "$APP_DIR/public/content/permits/." "/tmp/webhook_backup/permits/"
log "Permits directory backed up"
fi
if [ -d "$APP_DIR/public/content/uploads" ]; then
cp -r "$APP_DIR/public/content/uploads/." "/tmp/webhook_backup/uploads/"
log "Uploads directory backed up"
fi
# Check if we should rebuild the Docker image
REBUILD=0
if [ -f "$TEMP_DIR/package.json" ] && [ -f "$APP_DIR/package.json" ]; then
if ! cmp -s "$TEMP_DIR/package.json" "$APP_DIR/package.json"; then
log "package.json has changed, triggering full rebuild"
REBUILD=1
elif [ -f "$TEMP_DIR/package-lock.json" ] && [ -f "$APP_DIR/package-lock.json" ]; then
if ! cmp -s "$TEMP_DIR/package-lock.json" "$APP_DIR/package-lock.json"; then
log "package-lock.json has changed, triggering full rebuild"
REBUILD=1
fi
fi
fi
# Check if the Dockerfile or docker-compose file has changed
if [ -f "$TEMP_DIR/_deploy/standard.Dockerfile" ] && [ -f "$APP_DIR/_deploy/standard.Dockerfile" ]; then
if ! cmp -s "$TEMP_DIR/_deploy/standard.Dockerfile" "$APP_DIR/_deploy/standard.Dockerfile"; then
log "Dockerfile has changed, triggering full rebuild"
REBUILD=1
fi
fi
if [ -f "$TEMP_DIR/$DOCKER_COMPOSE_FILE" ] && [ -f "$APP_DIR/$DOCKER_COMPOSE_FILE" ]; then
if ! cmp -s "$TEMP_DIR/$DOCKER_COMPOSE_FILE" "$APP_DIR/$DOCKER_COMPOSE_FILE"; then
log "Docker Compose file has changed, triggering full rebuild"
REBUILD=1
fi
fi
# Deploy the application
if [ "$REBUILD" -eq 1 ]; then
log "Performing full rebuild and restart"
# Copy new code to application directory
rsync -av --exclude 'node_modules' --exclude '.git' --exclude 'public/content/permits' --exclude 'public/content/uploads' "$TEMP_DIR/" "$APP_DIR/"
# Rebuild and restart using Docker Compose
cd "$APP_DIR"
docker-compose -f "$DOCKER_COMPOSE_FILE" up -d --build
else
log "Performing code update without rebuild"
# Copy new code to application directory, preserving special directories
rsync -av --exclude 'node_modules' --exclude '.git' --exclude 'public/content/permits' --exclude 'public/content/uploads' "$TEMP_DIR/" "$APP_DIR/"
# Find container ID for the Next.js app
CONTAINER_ID=$(docker ps -qf "name=nextjs-app")
if [ -n "$CONTAINER_ID" ]; then
log "Restarting Next.js container: $CONTAINER_ID"
docker restart "$CONTAINER_ID"
else
log "Next.js container not found, starting with Docker Compose"
cd "$APP_DIR"
docker-compose -f "$DOCKER_COMPOSE_FILE" up -d
fi
fi
# Restore backed up directories and merge with new content from Git
log "Restoring and merging backed up directories"
# Create permits directory if it doesn't exist
mkdir -p "$APP_DIR/public/content/permits"
# Merge Git permits (if any) with backed up permits
if [ -d "$TEMP_DIR/public/content/permits" ] && [ "$(ls -A "$TEMP_DIR/public/content/permits")" ]; then
log "Copying permits from Git repository"
cp -r "$TEMP_DIR/public/content/permits/." "$APP_DIR/public/content/permits/"
fi
# Restore backed up permits (these will take precedence over Git permits)
if [ -d "/tmp/webhook_backup/permits" ] && [ "$(ls -A "/tmp/webhook_backup/permits")" ]; then
log "Restoring backed up permits"
cp -r "/tmp/webhook_backup/permits/." "$APP_DIR/public/content/permits/"
fi
# Restore uploads (these should only come from the backup, not Git)
if [ -d "/tmp/webhook_backup/uploads" ] && [ "$(ls -A "/tmp/webhook_backup/uploads")" ]; then
log "Restoring backed up uploads"
mkdir -p "$APP_DIR/public/content/uploads"
cp -r "/tmp/webhook_backup/uploads/." "$APP_DIR/public/content/uploads/"
fi
# Clean up backup
rm -rf "/tmp/webhook_backup"
log "Deployment completed successfully"