Files
michaelschiemer/deployment/infrastructure/playbooks/rollback-git-based.yml
Michael Schiemer 3b623e7afb feat(Deployment): Integrate Ansible deployment via PHP deployment pipeline
- Create AnsibleDeployStage using framework's Process module for secure command execution
- Integrate AnsibleDeployStage into DeploymentPipelineCommands for production deployments
- Add force_deploy flag support in Ansible playbook to override stale locks
- Use PHP deployment module as orchestrator (php console.php deploy:production)
- Fix ErrorAggregationInitializer to use Environment class instead of $_ENV superglobal

Architecture:
- BuildStage → AnsibleDeployStage → HealthCheckStage for production
- Process module provides timeout, error handling, and output capture
- Ansible playbook supports rollback via rollback-git-based.yml
- Zero-downtime deployments with health checks
2025-10-26 14:08:07 +01:00

143 lines
4.1 KiB
YAML

---
# Git-based Rollback Playbook
# Rolls back to the previous release by switching the symlink
#
# Usage:
# ansible-playbook -i inventories/production/hosts.yml playbooks/rollback-git-based.yml
# ansible-playbook -i inventories/production/hosts.yml playbooks/rollback-git-based.yml --extra-vars "rollback_to=20241025123456"
- name: Rollback Custom PHP Framework (Git-based)
hosts: web_servers
become: true
vars:
app_name: michaelschiemer
app_user: deploy
app_group: deploy
app_base_path: "/var/www/{{ app_name }}"
releases_path: "{{ app_base_path }}/releases"
current_path: "{{ app_base_path }}/current"
pre_tasks:
- name: Check if deployment lock exists
stat:
path: "{{ app_base_path }}/.deploy.lock"
register: deploy_lock
- name: Fail if deployment is in progress
fail:
msg: "Cannot rollback - deployment in progress"
when: deploy_lock.stat.exists
- name: Create rollback lock
file:
path: "{{ app_base_path }}/.rollback.lock"
state: touch
owner: "{{ app_user }}"
group: "{{ app_group }}"
tasks:
- name: Get current release
stat:
path: "{{ current_path }}"
register: current_release
- name: Fail if no current release exists
fail:
msg: "No current release found at {{ current_path }}"
when: not current_release.stat.exists
- name: Get list of all releases
find:
paths: "{{ releases_path }}"
file_type: directory
register: all_releases
- name: Sort releases by creation time (newest first)
set_fact:
sorted_releases: "{{ all_releases.files | sort(attribute='ctime', reverse=true) }}"
- name: Determine target release for rollback
set_fact:
target_release: "{{ rollback_to if rollback_to is defined else sorted_releases[1].path }}"
- name: Verify target release exists
stat:
path: "{{ target_release }}"
register: target_release_stat
- name: Fail if target release doesn't exist
fail:
msg: "Target release not found: {{ target_release }}"
when: not target_release_stat.stat.exists
- name: Display rollback information
debug:
msg:
- "Current release: {{ current_release.stat.lnk_source }}"
- "Rolling back to: {{ target_release }}"
- name: Switch symlink to previous release
file:
src: "{{ target_release }}"
dest: "{{ current_path }}"
state: link
owner: "{{ app_user }}"
group: "{{ app_group }}"
force: yes
- name: Wait for application to be ready
wait_for:
timeout: 5
delegate_to: localhost
- name: Health check after rollback
uri:
url: "http://{{ ansible_host }}/health/summary"
method: GET
return_content: yes
status_code: 200
register: health_check
retries: 3
delay: 5
until: health_check.status == 200
ignore_errors: yes
- name: Log rollback
lineinfile:
path: "{{ app_base_path }}/deploy.log"
line: "[{{ ansible_date_time.iso8601 }}] ROLLBACK: {{ current_release.stat.lnk_source }} -> {{ target_release }} - Health: {{ health_check.status | default('FAILED') }}"
create: yes
- name: Display rollback result
debug:
msg:
- "=========================================="
- "Rollback completed"
- "Previous: {{ current_release.stat.lnk_source }}"
- "Current: {{ target_release }}"
- "Health check: {{ health_check.status | default('FAILED') }}"
- "=========================================="
post_tasks:
- name: Remove rollback lock
file:
path: "{{ app_base_path }}/.rollback.lock"
state: absent
rescue:
- name: Remove rollback lock on failure
file:
path: "{{ app_base_path }}/.rollback.lock"
state: absent
- name: Log rollback failure
lineinfile:
path: "{{ app_base_path }}/deploy.log"
line: "[{{ ansible_date_time.iso8601 }}] ROLLBACK FAILED"
create: yes
- name: Fail with error message
fail:
msg: "Rollback failed"