feat(deployment): update Semaphore stack and Traefik configuration
- 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
This commit is contained in:
129
deployment/stacks/semaphore/playbooks/deploy-production.yml
Normal file
129
deployment/stacks/semaphore/playbooks/deploy-production.yml
Normal file
@@ -0,0 +1,129 @@
|
||||
---
|
||||
# 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"
|
||||
Reference in New Issue
Block a user