#!/bin/bash # Gitea Webhook Deployment Script # This script is triggered by Gitea webhook on push events # Configure in Gitea: Repository -> Settings -> Webhooks -> Add Webhook set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration PROJECT_DIR="/path/to/cloud-mcp" # Update this to your project path CONTAINER_NAME="cloud-mcp" COMPOSE_FILE="docker-compose.yml" BRANCH="main" # or "master" # Log file LOG_FILE="${PROJECT_DIR}/deploy.log" # Functions log() { local level=$1 shift local message="$@" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') echo -e "${timestamp} [${level}] ${message}" | tee -a "$LOG_FILE" } log_info() { log "INFO" "${GREEN}$@${NC}" } log_warn() { log "WARN" "${YELLOW}$@${NC}" } log_error() { log "ERROR" "${RED}$@${NC}" } # Check if running in correct directory check_directory() { if [ ! -f "$PROJECT_DIR/docker-compose.yml" ]; then log_error "Project directory not found: $PROJECT_DIR" exit 1 fi cd "$PROJECT_DIR" log_info "Working directory: $(pwd)" } # Check if Docker is running check_docker() { if ! docker info > /dev/null 2>&1; then log_error "Docker is not running" exit 1 fi log_info "Docker is running" } # Pull latest code pull_latest() { log_info "Pulling latest code from repository..." # Fetch latest changes git fetch origin "$BRANCH" || { log_error "Failed to fetch from repository" exit 1 } # Check if there are updates LOCAL=$(git rev-parse @) REMOTE=$(git rev-parse "origin/${BRANCH}") BASE=$(git merge-base @ "origin/${BRANCH}") if [ "$LOCAL" = "$REMOTE" ]; then log_info "Already up to date" return 1 elif [ "$LOCAL" = "$BASE" ]; then log_info "New commits found, pulling..." git pull origin "$BRANCH" || { log_error "Failed to pull from repository" exit 1 } return 0 else log_warn "Local branch is ahead or diverged. Resetting to remote..." git reset --hard "origin/${BRANCH}" || { log_error "Failed to reset branch" exit 1 } return 0 fi } # Build Docker image build_image() { log_info "Building Docker image..." docker-compose -f "$COMPOSE_FILE" build --no-cache || { log_error "Failed to build Docker image" exit 1 } log_info "Docker image built successfully" } # Stop existing container stop_container() { log_info "Stopping existing container..." docker-compose -f "$COMPOSE_FILE" down || { log_warn "Failed to stop container (might not exist)" } log_info "Container stopped" } # Start container start_container() { log_info "Starting container..." docker-compose -f "$COMPOSE_FILE" up -d || { log_error "Failed to start container" exit 1 } log_info "Container started" } # Verify deployment verify_deployment() { log_info "Verifying deployment..." sleep 3 if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then log_info "Container is running" # Check container health local status=$(docker inspect --format='{{.State.Status}}' "$CONTAINER_NAME" 2>/dev/null) if [ "$status" = "running" ]; then log_info "Deployment successful!" return 0 else log_error "Container is not running (status: $status)" return 1 fi else log_error "Container not found" return 1 fi } # Show container logs show_logs() { log_info "Recent container logs:" docker logs --tail 30 "$CONTAINER_NAME" 2>&1 || log_warn "Could not fetch logs" } # Cleanup old images (optional) cleanup_images() { log_info "Cleaning up unused Docker images..." docker image prune -f || log_warn "Failed to cleanup images" } # Main deployment flow main() { log_info "=========================================" log_info "Starting deployment process" log_info "=========================================" check_directory check_docker # Pull latest code if ! pull_latest; then log_info "No updates to deploy" exit 0 fi # Build and deploy build_image stop_container start_container # Verify if verify_deployment; then show_logs cleanup_images log_info "=========================================" log_info "Deployment completed successfully!" log_info "=========================================" else log_error "Deployment verification failed" show_logs exit 1 fi } # Handle script arguments case "${1:-}" in --pull-only) check_directory pull_latest ;; --rebuild) check_directory check_docker build_image stop_container start_container verify_deployment ;; --status) check_directory docker ps --filter "name=${CONTAINER_NAME}" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" show_logs ;; --logs) check_directory docker logs -f "$CONTAINER_NAME" ;; --stop) check_directory stop_container ;; --start) check_directory start_container ;; --restart) check_directory stop_container start_container ;; *) main ;; esac