- Add QUICKSTART.md and SETUP_REPOSITORY.md for Semaphore stack - Add playbooks directory for Semaphore deployment - Update Semaphore docker-compose.yml, env.example, and README - Add Traefik local configuration files - Disable semaphore.yml in Traefik dynamic config - Update docker-compose.local.yml and build-image workflow
130 lines
4.4 KiB
YAML
130 lines
4.4 KiB
YAML
---
|
|
# Production Deployment Playbook f?r Semaphore
|
|
# Deployed die Anwendung auf Production-Server
|
|
|
|
- name: Deploy to Production
|
|
hosts: production
|
|
gather_facts: yes
|
|
become: yes
|
|
vars:
|
|
registry_url: "{{ registry_url | default('registry.michaelschiemer.de') }}"
|
|
image_name: "{{ image_name | default('framework') }}"
|
|
image_tag: "{{ image_tag | default('latest') }}"
|
|
registry_user: "{{ registry_user | default('admin') }}"
|
|
registry_password: "{{ registry_password | required }}"
|
|
deployment_path: "{{ deployment_path | default('~/deployment/stacks/application') }}"
|
|
repo_url: "{{ repo_url | default('https://git.michaelschiemer.de/michael/michaelschiemer.git') }}"
|
|
|
|
tasks:
|
|
- name: Display deployment info
|
|
debug:
|
|
msg:
|
|
- "?? Starting production deployment..."
|
|
- "Host: {{ inventory_hostname }}"
|
|
- "Registry: {{ registry_url }}"
|
|
- "Image: {{ image_name }}:{{ image_tag }}"
|
|
- "Path: {{ deployment_path }}"
|
|
|
|
- name: Ensure deployment directory exists
|
|
file:
|
|
path: "{{ deployment_path }}"
|
|
state: directory
|
|
mode: '0755'
|
|
|
|
- name: Login to Docker registry
|
|
docker_login:
|
|
username: "{{ registry_user }}"
|
|
password: "{{ registry_password }}"
|
|
registry_url: "{{ registry_url }}"
|
|
|
|
- name: Pull Docker image
|
|
docker_image:
|
|
name: "{{ registry_url }}/{{ image_name }}:{{ image_tag }}"
|
|
source: pull
|
|
|
|
- name: Check if docker-compose files exist
|
|
stat:
|
|
path: "{{ deployment_path }}/docker-compose.base.yml"
|
|
register: base_compose_exists
|
|
|
|
- name: Check if docker-compose.production.yml exists
|
|
stat:
|
|
path: "{{ deployment_path }}/docker-compose.production.yml"
|
|
register: production_compose_exists
|
|
|
|
- name: Copy docker-compose files if missing
|
|
copy:
|
|
src: "{{ item.src }}"
|
|
dest: "{{ deployment_path }}/{{ item.dest }}"
|
|
mode: '0644'
|
|
loop:
|
|
- { src: "docker-compose.base.yml", dest: "docker-compose.base.yml" }
|
|
- { src: "docker-compose.production.yml", dest: "docker-compose.production.yml" }
|
|
when: not (item.dest == "docker-compose.base.yml" and base_compose_exists.stat.exists) or
|
|
not (item.dest == "docker-compose.production.yml" and production_compose_exists.stat.exists)
|
|
delegate_to: localhost
|
|
become: no
|
|
|
|
- name: Update docker-compose.production.yml with new image
|
|
replace:
|
|
path: "{{ deployment_path }}/docker-compose.production.yml"
|
|
regexp: 'image:.*{{ image_name }}:.*'
|
|
replace: 'image: {{ registry_url }}/{{ image_name }}:{{ image_tag }}'
|
|
|
|
- name: Update docker-compose.production.yml with new image (alternative format)
|
|
replace:
|
|
path: "{{ deployment_path }}/docker-compose.production.yml"
|
|
regexp: 'image:.*{{ image_name }}@.*'
|
|
replace: 'image: {{ registry_url }}/{{ image_name }}:{{ image_tag }}'
|
|
|
|
- name: Ensure Docker networks exist
|
|
docker_network:
|
|
name: traefik-public
|
|
state: present
|
|
ignore_errors: yes
|
|
|
|
- name: Deploy services
|
|
docker_compose_v2:
|
|
project_src: "{{ deployment_path }}"
|
|
files:
|
|
- "{{ deployment_path }}/docker-compose.base.yml"
|
|
- "{{ deployment_path }}/docker-compose.production.yml"
|
|
pull: missing
|
|
state: present
|
|
recreate: always
|
|
|
|
- name: Wait for services to start
|
|
pause:
|
|
seconds: 15
|
|
|
|
- name: Check container status
|
|
command: docker compose -f {{ deployment_path }}/docker-compose.base.yml -f {{ deployment_path }}/docker-compose.production.yml ps
|
|
register: container_status
|
|
|
|
- name: Display container status
|
|
debug:
|
|
var: container_status.stdout_lines
|
|
|
|
- name: Health check
|
|
uri:
|
|
url: https://michaelschiemer.de/health
|
|
method: GET
|
|
status_code: [200, 201, 204]
|
|
validate_certs: no
|
|
register: health_result
|
|
retries: 10
|
|
delay: 10
|
|
until: health_result.status == 200
|
|
ignore_errors: yes
|
|
|
|
- name: Display health check result
|
|
debug:
|
|
msg: "? Health check passed!" if health_result.status == 200 else "?? Health check failed"
|
|
|
|
- name: Summary
|
|
debug:
|
|
msg:
|
|
- "? Production deployment completed!"
|
|
- "Image: {{ registry_url }}/{{ image_name }}:{{ image_tag }}"
|
|
- "URL: https://michaelschiemer.de"
|