- Add deployment/ansible/templates/.env.production.j2 used by secrets playbook - Enhance deploy-update.yml to read registry creds from vault or CI - Update production-deploy workflow to pass registry credentials to Ansible - Remove obsolete GitHub-style workflows under .gitea (conflicted naming) Why: make the production pipeline executable end-to-end with Ansible and consistent secrets handling; avoid legacy CI configs interfering.
138 lines
4.7 KiB
YAML
138 lines
4.7 KiB
YAML
---
|
|
- name: Deploy Application Update
|
|
hosts: production
|
|
gather_facts: yes
|
|
become: yes
|
|
|
|
vars:
|
|
# These should be passed via -e from CI/CD
|
|
image_tag: "{{ image_tag | default('latest') }}"
|
|
git_commit_sha: "{{ git_commit_sha | default('unknown') }}"
|
|
deployment_timestamp: "{{ deployment_timestamp | default(ansible_date_time.iso8601) }}"
|
|
|
|
pre_tasks:
|
|
- name: Optionally load registry credentials from encrypted vault
|
|
include_vars:
|
|
file: "{{ playbook_dir }}/../secrets/production.vault.yml"
|
|
no_log: yes
|
|
ignore_errors: yes
|
|
delegate_to: localhost
|
|
become: no
|
|
|
|
- name: Derive docker registry credentials from vault when not provided
|
|
set_fact:
|
|
docker_registry_username: "{{ docker_registry_username | default(vault_docker_registry_username | default(omit)) }}"
|
|
docker_registry_password: "{{ docker_registry_password | default(vault_docker_registry_password | default(omit)) }}"
|
|
|
|
- name: Verify Docker is running
|
|
systemd:
|
|
name: docker
|
|
state: started
|
|
register: docker_service
|
|
|
|
- name: Fail if Docker is not running
|
|
fail:
|
|
msg: "Docker service is not running"
|
|
when: docker_service.status.ActiveState != 'active'
|
|
|
|
- name: Create backup directory
|
|
file:
|
|
path: "{{ backups_path }}/{{ deployment_timestamp | regex_replace(':', '-') }}"
|
|
state: directory
|
|
owner: "{{ ansible_user }}"
|
|
group: "{{ ansible_user }}"
|
|
mode: '0755'
|
|
|
|
tasks:
|
|
- name: Backup current deployment metadata
|
|
shell: |
|
|
docker service inspect {{ stack_name }}_app --format '{{ "{{" }}.Spec.TaskTemplate.ContainerSpec.Image{{ "}}" }}' \
|
|
> {{ backups_path }}/{{ deployment_timestamp | regex_replace(':', '-') }}/current_image.txt || true
|
|
docker stack ps {{ stack_name }} --format 'table {{ "{{" }}.Name{{ "}}" }}\t{{ "{{" }}.Image{{ "}}" }}\t{{ "{{" }}.CurrentState{{ "}}" }}' \
|
|
> {{ backups_path }}/{{ deployment_timestamp | regex_replace(':', '-') }}/stack_status.txt || true
|
|
args:
|
|
executable: /bin/bash
|
|
changed_when: false
|
|
|
|
- name: Login to Docker registry (if credentials provided)
|
|
docker_login:
|
|
registry_url: "{{ docker_registry_url }}"
|
|
username: "{{ docker_registry_username }}"
|
|
password: "{{ docker_registry_password }}"
|
|
no_log: yes
|
|
when:
|
|
- docker_registry_username is defined
|
|
- docker_registry_password is defined
|
|
|
|
- name: Pull new Docker image
|
|
docker_image:
|
|
name: "{{ app_image }}"
|
|
tag: "{{ image_tag }}"
|
|
source: pull
|
|
force_source: yes
|
|
register: image_pull
|
|
|
|
- name: Update docker-compose.prod.yml with new image tag
|
|
lineinfile:
|
|
path: "{{ compose_file }}"
|
|
regexp: '^(\s+image:\s+){{ app_image }}:.*$'
|
|
line: '\1{{ app_image }}:{{ image_tag }}'
|
|
backrefs: yes
|
|
when: compose_file is file
|
|
|
|
- name: Deploy stack update
|
|
docker_stack:
|
|
name: "{{ stack_name }}"
|
|
compose:
|
|
- "{{ compose_file }}"
|
|
state: present
|
|
prune: yes
|
|
register: stack_deploy
|
|
|
|
- name: Wait for service to be updated
|
|
command: >
|
|
docker service ps {{ stack_name }}_app
|
|
--filter "desired-state=running"
|
|
--format '{{ "{{" }}.CurrentState{{ "}}" }}'
|
|
register: service_status
|
|
until: "'Running' in service_status.stdout"
|
|
retries: 30
|
|
delay: 10
|
|
changed_when: false
|
|
|
|
- name: Get updated service info
|
|
command: docker service inspect {{ stack_name }}_app --format '{{ "{{" }}.Spec.TaskTemplate.ContainerSpec.Image{{ "}}" }}'
|
|
register: deployed_image
|
|
changed_when: false
|
|
|
|
- name: Record deployment metadata
|
|
copy:
|
|
content: |
|
|
Deployment Timestamp: {{ deployment_timestamp }}
|
|
Git Commit: {{ git_commit_sha }}
|
|
Image Tag: {{ image_tag }}
|
|
Deployed Image: {{ deployed_image.stdout }}
|
|
Stack Deploy Output: {{ stack_deploy }}
|
|
dest: "{{ backups_path }}/{{ deployment_timestamp | regex_replace(':', '-') }}/deployment_metadata.txt"
|
|
owner: "{{ ansible_user }}"
|
|
group: "{{ ansible_user }}"
|
|
mode: '0644'
|
|
|
|
- name: Cleanup old backups (keep last {{ max_rollback_versions }})
|
|
shell: |
|
|
cd {{ backups_path }}
|
|
ls -t | tail -n +{{ max_rollback_versions + 1 }} | xargs -r rm -rf
|
|
args:
|
|
executable: /bin/bash
|
|
changed_when: false
|
|
|
|
post_tasks:
|
|
- name: Display deployment summary
|
|
debug:
|
|
msg:
|
|
- "Deployment completed successfully!"
|
|
- "Image: {{ app_image }}:{{ image_tag }}"
|
|
- "Commit: {{ git_commit_sha }}"
|
|
- "Timestamp: {{ deployment_timestamp }}"
|
|
- "Health check URL: {{ health_check_url }}"
|