fix: more details deployment

This commit is contained in:
Benno Tielen 2026-04-16 13:22:17 +02:00
parent c4060dad0c
commit 2efcb5f672
6 changed files with 185 additions and 35 deletions

View file

@ -169,42 +169,38 @@ docker restart postgres
## Deploy via Ansible (without CI/CD)
Use the `deploy.yml` playbook to deploy from your local machine — no Forgejo runner or CI/CD pipeline needed. This is useful for hotfixes, CI outages, or production servers without Forgejo.
Use these playbooks to deploy from your local machine — no Forgejo runner needed.
```bash
cd infra/ansible
# Deploy to test/staging VPS
ansible-playbook playbooks/deploy.yml -i inventory/test.yml --ask-vault-pass
# Deploy both environments (git pull once, then build+deploy each sequentially)
ansible-playbook playbooks/deploy.yml --ask-vault-pass
# Deploy to production
ansible-playbook playbooks/deploy.yml -i inventory/production.yml --ask-vault-pass
# Deploy staging only
ansible-playbook playbooks/deploy-staging.yml --ask-vault-pass
# Deploy test only
ansible-playbook playbooks/deploy-test.yml --ask-vault-pass
```
**What it does:**
**Steps executed per environment:**
1. Pulls the latest code from the configured branch (`repo_branch` in inventory)
2. Runs `deploy.sh` for each environment (sequentially to save RAM), which:
- Builds the Docker app image with build-time env vars
- Builds a migration image and runs `npx payload migrate`
- Stops the old container, starts the new one
- Prunes old Docker images
1. Pull latest code from the configured branch (`staging`)
2. Build app Docker image (bakes in `NEXT_PUBLIC_SERVER_URL` and `NEXT_PUBLIC_SITE_ID`)
3. Build migration image and run `npx payload migrate`
4. Stop and remove the old container
5. Start the new container
6. Fix upload volume permissions
7. Prune old Docker images
**Deploy a specific branch:**
```bash
ansible-playbook playbooks/deploy.yml -i inventory/test.yml --ask-vault-pass \
-e repo_branch=feature/my-branch
ansible-playbook playbooks/deploy.yml --ask-vault-pass -e repo_branch=feature/my-branch
```
**Deploy only one environment** (e.g., just staging):
```bash
ansible-playbook playbooks/deploy.yml -i inventory/test.yml --ask-vault-pass \
-e '{"app_environments": [{"name": "staging", "port": 3001}]}'
```
> **Note:** The server must already be provisioned with `setup.yml` before using `deploy.yml`. The deploy playbook only pulls code and rebuilds containers — it does not install Docker, Caddy, or PostgreSQL.
> **Note:** The server must already be provisioned with `setup.yml` before deploying. The deploy playbooks only pull code and rebuild containers — they do not install Docker, Caddy, or PostgreSQL.
---

View file

@ -0,0 +1,20 @@
---
- name: Deploy staging environment
hosts: all
become: true
tasks:
- name: Pull {{ repo_branch }} branch
ansible.builtin.git:
repo: "{{ repo_url }}"
dest: "{{ repo_dir }}"
version: "{{ repo_branch }}"
force: true
accept_hostkey: true
- name: Build and deploy staging
ansible.builtin.include_role:
name: app
tasks_from: deploy_env
vars:
env: "{{ app_environments | selectattr('name', 'equalto', 'staging') | first }}"

View file

@ -0,0 +1,20 @@
---
- name: Deploy test environment
hosts: all
become: true
tasks:
- name: Pull {{ repo_branch }} branch
ansible.builtin.git:
repo: "{{ repo_url }}"
dest: "{{ repo_dir }}"
version: "{{ repo_branch }}"
force: true
accept_hostkey: true
- name: Build and deploy test
ansible.builtin.include_role:
name: app
tasks_from: deploy_env
vars:
env: "{{ app_environments | selectattr('name', 'equalto', 'test') | first }}"

View file

@ -1,19 +1,37 @@
---
- name: Deploy app (rebuild + restart)
- name: Pull latest code (shared for both environments)
hosts: all
become: true
tasks:
- name: Pull latest code
- name: Pull {{ repo_branch }} branch
ansible.builtin.git:
repo: "{{ repo_url }}"
dest: "{{ repo_dir }}"
version: "{{ repo_branch }}"
force: true
accept_hostkey: true
- name: Deploy each environment
ansible.builtin.shell: |
{{ scripts_dir }}/deploy.sh {{ item.name }} {{ item.port }}
loop: "{{ app_environments }}"
loop_control:
label: "{{ item.name }}"
- name: Deploy staging environment
hosts: all
become: true
tasks:
- name: Build and deploy staging
ansible.builtin.include_role:
name: app
tasks_from: deploy_env
vars:
env: "{{ app_environments | selectattr('name', 'equalto', 'staging') | first }}"
- name: Deploy test environment
hosts: all
become: true
tasks:
- name: Build and deploy test
ansible.builtin.include_role:
name: app
tasks_from: deploy_env
vars:
env: "{{ app_environments | selectattr('name', 'equalto', 'test') | first }}"

View file

@ -1,9 +1,7 @@
---
- name: Deploy each environment (sequentially to save RAM)
ansible.builtin.shell: |
{{ scripts_dir }}/deploy.sh {{ item.name }} {{ item.port }}
ansible.builtin.include_tasks: deploy_env.yml
loop: "{{ app_environments }}"
loop_control:
label: "{{ item.name }}"
register: deploy_result
changed_when: true
loop_var: env
label: "{{ env.name }}"

View file

@ -0,0 +1,98 @@
---
- name: "{{ env.name }} | Build app image"
ansible.builtin.command:
argv:
- docker
- build
- --build-arg
- "NEXT_PUBLIC_SERVER_URL=https://{{ env.domain }}"
- --build-arg
- "NEXT_PUBLIC_SITE_ID={{ env.site_id }}"
- -t
- "church-website:{{ env.name }}"
- "{{ repo_dir }}"
changed_when: true
- name: "{{ env.name }} | Build migration image"
ansible.builtin.command:
argv:
- docker
- build
- --target
- builder
- --build-arg
- "NEXT_PUBLIC_SERVER_URL=https://{{ env.domain }}"
- --build-arg
- "NEXT_PUBLIC_SITE_ID={{ env.site_id }}"
- -t
- "church-website-migrate:{{ env.name }}"
- "{{ repo_dir }}"
changed_when: true
- name: "{{ env.name }} | Run database migrations"
ansible.builtin.command:
argv:
- docker
- run
- --rm
- --network
- "{{ docker_network }}"
- --env-file
- "{{ envs_dir }}/{{ env.name }}/.env"
- "church-website-migrate:{{ env.name }}"
- npx
- payload
- migrate
changed_when: true
- name: "{{ env.name }} | Stop old container"
ansible.builtin.command: "docker stop app-{{ env.name }}"
failed_when: false
changed_when: true
- name: "{{ env.name }} | Remove old container"
ansible.builtin.command: "docker rm app-{{ env.name }}"
failed_when: false
changed_when: true
- name: "{{ env.name }} | Start new container"
ansible.builtin.command:
argv:
- docker
- run
- -d
- --name
- "app-{{ env.name }}"
- --restart
- unless-stopped
- --network
- "{{ docker_network }}"
- --env-file
- "{{ envs_dir }}/{{ env.name }}/.env"
- -v
- "uploads-{{ env.name }}-media:/app/media"
- -v
- "uploads-{{ env.name }}-documents:/app/documents"
- -p
- "127.0.0.1:{{ env.port }}:3000"
- "church-website:{{ env.name }}"
changed_when: true
- name: "{{ env.name }} | Fix upload volume permissions"
ansible.builtin.command:
argv:
- docker
- exec
- -u
- "0"
- "app-{{ env.name }}"
- chown
- -R
- 1001:1001
- /app/media
- /app/documents
changed_when: true
- name: "{{ env.name }} | Prune old Docker images"
ansible.builtin.command: docker image prune -f
changed_when: true