#!/bin/bash set -e # Deploy Application to Production # This script deploys application updates using Ansible SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DEPLOYMENT_DIR="$(dirname "$SCRIPT_DIR")" ANSIBLE_DIR="$DEPLOYMENT_DIR/ansible" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Function to print colored messages print_success() { echo -e "${GREEN}✅ $1${NC}" } print_error() { echo -e "${RED}❌ $1${NC}" } print_warning() { echo -e "${YELLOW}⚠️ $1${NC}" } print_info() { echo -e "${BLUE}ℹ️ $1${NC}" } # Show usage usage() { echo "Usage: $0 [options]" echo "" echo "Arguments:" echo " image-tag Docker image tag to deploy (e.g., sha-abc123, v1.2.3, latest)" echo "" echo "Options:" echo " --registry-user USER Docker registry username (default: from vault)" echo " --registry-pass PASS Docker registry password (default: from vault)" echo " --commit SHA Git commit SHA (default: auto-detect)" echo " --dry-run Run in check mode without making changes" echo " --help Show this help message" echo "" echo "Examples:" echo " $0 sha-abc123" echo " $0 v1.2.3 --commit abc123def" echo " $0 latest --dry-run" exit 1 } # Parse arguments IMAGE_TAG="" REGISTRY_USER="" REGISTRY_PASS="" GIT_COMMIT="" DRY_RUN="" while [[ $# -gt 0 ]]; do case $1 in --registry-user) REGISTRY_USER="$2" shift 2 ;; --registry-pass) REGISTRY_PASS="$2" shift 2 ;; --commit) GIT_COMMIT="$2" shift 2 ;; --dry-run) DRY_RUN="--check" shift ;; --help) usage ;; *) if [ -z "$IMAGE_TAG" ]; then IMAGE_TAG="$1" shift else print_error "Unknown argument: $1" usage fi ;; esac done # Validate image tag if [ -z "$IMAGE_TAG" ]; then print_error "Image tag is required" usage fi echo "" echo "🚀 Deploy Application to Production" echo "====================================" echo "" # Check if running from correct directory if [ ! -f "$ANSIBLE_DIR/ansible.cfg" ]; then print_error "Error: Must run from deployment/scripts directory" exit 1 fi cd "$ANSIBLE_DIR" # Auto-detect git commit if not provided if [ -z "$GIT_COMMIT" ]; then if command -v git &> /dev/null && [ -d "$(git rev-parse --git-dir 2>/dev/null)" ]; then GIT_COMMIT=$(git rev-parse --short HEAD) print_info "Auto-detected git commit: $GIT_COMMIT" else GIT_COMMIT="unknown" print_warning "Could not auto-detect git commit" fi fi # Generate deployment timestamp DEPLOYMENT_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ) # Check Prerequisites echo "Checking Prerequisites..." echo "------------------------" # Check Ansible if ! command -v ansible &> /dev/null; then print_error "Ansible is not installed" exit 1 fi print_success "Ansible installed" # Check vault password if [ ! -f "$ANSIBLE_DIR/secrets/.vault_pass" ]; then print_error "Vault password file not found" exit 1 fi print_success "Vault password file found" # Check playbook if [ ! -f "$ANSIBLE_DIR/playbooks/deploy-update.yml" ]; then print_error "Deploy playbook not found" exit 1 fi print_success "Deploy playbook found" # Test connection print_info "Testing connection to production..." if ansible production -m ping > /dev/null 2>&1; then print_success "Connection successful" else print_error "Connection to production failed" exit 1 fi echo "" # Deployment Summary echo "Deployment Summary" echo "-----------------" echo " Image Tag: $IMAGE_TAG" echo " Git Commit: $GIT_COMMIT" echo " Timestamp: $DEPLOYMENT_TIMESTAMP" echo " Registry: git.michaelschiemer.de:5000" if [ -n "$DRY_RUN" ]; then echo " Mode: DRY RUN (no changes will be made)" else echo " Mode: PRODUCTION DEPLOYMENT" fi echo "" # Confirmation if [ -z "$DRY_RUN" ]; then read -p "Proceed with deployment? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then print_warning "Deployment cancelled" exit 0 fi fi echo "" # Build ansible-playbook command ANSIBLE_CMD="ansible-playbook $ANSIBLE_DIR/playbooks/deploy-update.yml" ANSIBLE_CMD="$ANSIBLE_CMD --vault-password-file $ANSIBLE_DIR/secrets/.vault_pass" ANSIBLE_CMD="$ANSIBLE_CMD -e image_tag=$IMAGE_TAG" ANSIBLE_CMD="$ANSIBLE_CMD -e git_commit_sha=$GIT_COMMIT" ANSIBLE_CMD="$ANSIBLE_CMD -e deployment_timestamp=$DEPLOYMENT_TIMESTAMP" # Add registry credentials if provided if [ -n "$REGISTRY_USER" ]; then ANSIBLE_CMD="$ANSIBLE_CMD -e docker_registry_username=$REGISTRY_USER" fi if [ -n "$REGISTRY_PASS" ]; then ANSIBLE_CMD="$ANSIBLE_CMD -e docker_registry_password=$REGISTRY_PASS" fi # Add dry-run flag if set if [ -n "$DRY_RUN" ]; then ANSIBLE_CMD="$ANSIBLE_CMD $DRY_RUN" fi # Execute deployment print_info "Starting deployment..." echo "" if eval "$ANSIBLE_CMD"; then echo "" if [ -z "$DRY_RUN" ]; then print_success "Deployment completed successfully!" else print_success "Dry run completed successfully!" fi else echo "" print_error "Deployment failed!" exit 1 fi echo "" # Post-deployment checks if [ -z "$DRY_RUN" ]; then echo "Post-Deployment Checks" echo "---------------------" SSH_KEY="$HOME/.ssh/production" # Check service status print_info "Checking service status..." ssh -i "$SSH_KEY" deploy@94.16.110.151 "docker service ls --filter name=app_" || true echo "" # Show recent logs print_info "Recent application logs:" ssh -i "$SSH_KEY" deploy@94.16.110.151 "docker service logs --tail 20 app_app" || true echo "" # Health check URL HEALTH_URL="https://michaelschiemer.de/health" print_info "Health check URL: $HEALTH_URL" echo "" # Summary echo "✅ Deployment Complete!" echo "======================" echo "" echo "Deployed:" echo " Image: git.michaelschiemer.de:5000/framework:$IMAGE_TAG" echo " Commit: $GIT_COMMIT" echo " Timestamp: $DEPLOYMENT_TIMESTAMP" echo "" echo "Next Steps:" echo "" echo "1. Monitor application:" echo " ssh -i $SSH_KEY deploy@94.16.110.151 'docker service logs -f app_app'" echo "" echo "2. Check service status:" echo " ssh -i $SSH_KEY deploy@94.16.110.151 'docker service ps app_app'" echo "" echo "3. Test application:" echo " curl $HEALTH_URL" echo "" echo "4. Rollback if needed:" echo " $SCRIPT_DIR/rollback.sh" echo "" else echo "Dry Run Summary" echo "===============" echo "" echo "This was a dry run. No changes were made to production." echo "" echo "To deploy for real, run:" echo " $0 $IMAGE_TAG" echo "" fi