--- # Complete Production Deployment Playbook # Syncs files, builds image, and updates services # Usage: ansible-playbook -i inventory/production.yml playbooks/deploy-complete.yml - name: Complete Production Deployment hosts: production_server become: no vars: # Calculate project root: playbook is in deployment/ansible/playbooks/, go up 3 levels local_project_path: "{{ playbook_dir }}/../../.." remote_project_path: /home/deploy/framework-app docker_registry: localhost:5000 docker_image_name: framework docker_image_tag: latest docker_stack_name: framework build_timestamp: "{{ ansible_date_time.epoch }}" tasks: - name: Display deployment information debug: msg: - "🚀 Starting Complete Deployment" - "Local Path: {{ local_project_path }}" - "Remote Path: {{ remote_project_path }}" - "Image: {{ docker_registry }}/{{ docker_image_name }}:{{ docker_image_tag }}" - "Timestamp: {{ build_timestamp }}" - name: Create remote project directory file: path: "{{ remote_project_path }}" state: directory mode: '0755' - name: Sync project files to production server synchronize: src: "{{ local_project_path }}/" dest: "{{ remote_project_path }}/" delete: no rsync_opts: - "--exclude=.git" - "--exclude=.gitignore" - "--exclude=node_modules" - "--exclude=vendor" - "--exclude=storage/logs/*" - "--exclude=storage/cache/*" - "--exclude=.env" - "--exclude=.env.*" - "--exclude=tests" - "--exclude=.deployment-backup" - "--exclude=deployment" register: sync_result - name: Display sync results debug: msg: "Files synced: {{ sync_result.changed }}" - name: Build Docker image on production server shell: | cd {{ remote_project_path }} docker build \ -f Dockerfile.production \ -t {{ docker_registry }}/{{ docker_image_name }}:{{ docker_image_tag }} \ -t {{ docker_registry }}/{{ docker_image_name }}:{{ build_timestamp }} \ --no-cache \ --progress=plain \ . register: build_result changed_when: true - name: Display build output (last 20 lines) debug: msg: "{{ build_result.stdout_lines[-20:] }}" - name: Update web service with rolling update shell: | docker service update \ --image {{ docker_registry }}/{{ docker_image_name }}:{{ docker_image_tag }} \ --force \ --update-parallelism 1 \ --update-delay 10s \ {{ docker_stack_name }}_web register: web_update changed_when: true - name: Update queue-worker service shell: | docker service update \ --image {{ docker_registry }}/{{ docker_image_name }}:{{ docker_image_tag }} \ --force \ {{ docker_stack_name }}_queue-worker register: worker_update changed_when: true - name: Wait for services to stabilize (30 seconds) pause: seconds: 30 prompt: "Waiting for services to stabilize..." - name: Check service status shell: docker stack services {{ docker_stack_name }} --format "table {{`{{.Name}}\t{{.Replicas}}\t{{.Image}}`}}" register: service_status changed_when: false - name: Check website availability shell: curl -k -s -o /dev/null -w '%{http_code}' https://michaelschiemer.de/ register: website_check changed_when: false failed_when: false - name: Get recent web service logs shell: docker service logs {{ docker_stack_name }}_web --tail 10 --no-trunc 2>&1 | tail -20 register: web_logs changed_when: false failed_when: false - name: Display deployment summary debug: msg: - "✅ Deployment Completed" - "" - "Build Timestamp: {{ build_timestamp }}" - "Image: {{ docker_registry }}/{{ docker_image_name }}:{{ docker_image_tag }}" - "" - "Service Status:" - "{{ service_status.stdout_lines }}" - "" - "Website HTTP Status: {{ website_check.stdout }}" - "" - "Recent Logs:" - "{{ web_logs.stdout_lines }}" - "" - "🌐 Website: https://michaelschiemer.de" - "📊 Portainer: https://michaelschiemer.de:9000" - "📈 Grafana: https://michaelschiemer.de:3000"