--- # Git-Based Production Deployment Playbook # Uses Git to sync files, builds image, and updates services # Usage: ansible-playbook -i inventory/production.yml playbooks/deploy-complete-git.yml - name: Git-Based 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 Git-Based 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: Check if Git repository exists on production stat: path: "{{ remote_project_path }}/.git" register: git_repo - name: Initialize Git repository if not exists shell: | cd {{ remote_project_path }} git init git config user.email 'deploy@michaelschiemer.de' git config user.name 'Deploy User' when: not git_repo.stat.exists - name: Create tarball of current code (excluding unnecessary files) delegate_to: localhost shell: | cd {{ local_project_path }} tar czf /tmp/framework-deploy-{{ build_timestamp }}.tar.gz \ --exclude='.git' \ --exclude='node_modules' \ --exclude='vendor' \ --exclude='storage/logs/*' \ --exclude='storage/cache/*' \ --exclude='.env' \ --exclude='.env.*' \ --exclude='tests' \ --exclude='.deployment-backup' \ --exclude='deployment' \ . register: tarball_creation changed_when: true - name: Transfer tarball to production copy: src: "/tmp/framework-deploy-{{ build_timestamp }}.tar.gz" dest: "/tmp/framework-deploy-{{ build_timestamp }}.tar.gz" register: tarball_transfer - name: Extract tarball to production (preserving Git) shell: | cd {{ remote_project_path }} tar xzf /tmp/framework-deploy-{{ build_timestamp }}.tar.gz rm -f /tmp/framework-deploy-{{ build_timestamp }}.tar.gz register: extraction_result changed_when: true - name: Commit changes to Git repository shell: | cd {{ remote_project_path }} git add -A git commit -m "Deployment {{ build_timestamp }}" || echo "No changes to commit" git log --oneline -5 register: git_commit changed_when: true - name: Display Git status debug: msg: "{{ git_commit.stdout_lines }}" - name: Clean up local tarball delegate_to: localhost file: path: "/tmp/framework-deploy-{{ build_timestamp }}.tar.gz" state: absent - name: Build Docker image on production server shell: | cd {{ remote_project_path }} docker build \ -f docker/php/Dockerfile \ --target 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: - "✅ Git-Based Deployment Completed" - "" - "Build Timestamp: {{ build_timestamp }}" - "Image: {{ docker_registry }}/{{ docker_image_name }}:{{ docker_image_tag }}" - "" - "Git Commit Info:" - "{{ git_commit.stdout_lines }}" - "" - "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"