Keep sanitized Compose sources in-repo with a confirmation-gated Ansible playbook, add repo-wide validation, tighten runbook ownership/STOP/review metadata, and archive stale research docs. Co-authored-by: Cursor <cursoragent@cursor.com>
85 lines
3.0 KiB
YAML
85 lines
3.0 KiB
YAML
---
|
|
# Deploy the repo-owned, sanitized Compose declaration to the host.
|
|
#
|
|
# Safety model:
|
|
# - Only hosts with an inventory `compose_repo_project` (allowlisted) are valid.
|
|
# - The repo file is staged to `<file>.dsh-new` and validated with
|
|
# `docker compose config --quiet` against the server-local .env BEFORE it
|
|
# replaces anything. A failed validation never touches the live file.
|
|
# - The current file is kept as `*.bak-<timestamp>` before promotion.
|
|
# - Apply mode requires `compose_deploy_confirm=true`; `--check` gives a
|
|
# read-only diff + validation without writes.
|
|
# - The playbook never writes, reads, or transfers the server .env.
|
|
|
|
- name: Require an allowlisted repo compose project for this host
|
|
ansible.builtin.assert:
|
|
that:
|
|
- compose_repo_project is defined
|
|
- compose_repo_project in compose_repo_projects
|
|
fail_msg: >-
|
|
No allowlisted compose_repo_project for {{ inventory_hostname }}.
|
|
Supported: {{ compose_repo_projects | join(', ') }}.
|
|
|
|
- name: Require explicit confirmation for apply mode
|
|
ansible.builtin.assert:
|
|
that:
|
|
- ansible_check_mode or (compose_deploy_confirm | bool)
|
|
fail_msg: >-
|
|
This playbook replaces the server compose file and may recreate
|
|
containers. Run with --check for a read-only diff, or supply
|
|
compose_deploy_confirm=true to apply.
|
|
|
|
- name: Stage the repo compose file next to the live one
|
|
ansible.builtin.copy:
|
|
src: "{{ playbook_dir }}/../../compose/{{ compose_repo_project }}/compose.yml"
|
|
dest: "{{ compose_project_dir }}/{{ compose_remote_file | default('compose.yml') }}.dsh-new"
|
|
mode: "0644"
|
|
diff: true
|
|
register: compose_stage
|
|
|
|
- name: Validate staged compose against the server .env (read-only)
|
|
ansible.builtin.command:
|
|
argv:
|
|
- docker
|
|
- compose
|
|
- -f
|
|
- "{{ compose_project_dir }}/{{ compose_remote_file | default('compose.yml') }}.dsh-new"
|
|
- --project-directory
|
|
- "{{ compose_project_dir }}"
|
|
- config
|
|
- --quiet
|
|
register: compose_validate
|
|
changed_when: false
|
|
failed_when: compose_validate.rc != 0
|
|
|
|
- name: Show staged-vs-live difference
|
|
ansible.builtin.debug:
|
|
msg: "{{ compose_stage.diff | default('(no change)') }}"
|
|
when: ansible_check_mode
|
|
|
|
- name: Back up the current compose file (apply mode)
|
|
ansible.builtin.shell:
|
|
cmd: >-
|
|
cp -a '{{ compose_project_dir }}/{{ compose_remote_file | default('compose.yml') }}'
|
|
'{{ compose_project_dir }}/{{ compose_remote_file | default('compose.yml') }}.bak-$(date +%Y%m%d-%H%M%S)'
|
|
when: not ansible_check_mode
|
|
|
|
- name: Promote the validated compose file (apply mode)
|
|
ansible.builtin.command:
|
|
argv:
|
|
- mv
|
|
- "{{ compose_project_dir }}/{{ compose_remote_file | default('compose.yml') }}.dsh-new"
|
|
- "{{ compose_project_dir }}/{{ compose_remote_file | default('compose.yml') }}"
|
|
when: not ansible_check_mode
|
|
|
|
- name: Apply the compose declaration (apply mode)
|
|
ansible.builtin.command:
|
|
argv:
|
|
- docker
|
|
- compose
|
|
- --project-directory
|
|
- "{{ compose_project_dir }}"
|
|
- up
|
|
- -d
|
|
when: not ansible_check_mode
|