285 lines
7.0 KiB
Bash
Executable File
285 lines
7.0 KiB
Bash
Executable File
#!/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 <image-tag> [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
|