diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml
index d6280de..9b32f9a 100644
--- a/.github/workflows/build_and_deploy.yml
+++ b/.github/workflows/build_and_deploy.yml
@@ -14,6 +14,10 @@ jobs:
- name: Checkout code
uses: actions/checkout@v3
+ # Uv is needed for the deployment lint
+ - name: Install uv
+ uses: astral-sh/setup-uv@v5
+
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
@@ -43,6 +47,10 @@ jobs:
docker run --rm intbot make ci/lint
docker run --rm intbot make ci/type-check
+
+ - name: Run deployment playbooks lint
+ run: make lint/deploy
+
services:
postgres:
image: postgres:16.4
diff --git a/Makefile b/Makefile
index dabbabb..30db2d4 100644
--- a/Makefile
+++ b/Makefile
@@ -15,6 +15,7 @@ CI_RUN=cd intbot && DJANGO_SETTINGS_MODULE="intbot.settings" DJANGO_ENV="ci"
# Deployment
DEPLOY_CMD=cd deploy && uvx --from "ansible-core" ansible-playbook -i hosts.yml
+DEPLOY_LINT_CMD=cd deploy && uvx --from "ansible-lint" ansible-lint
# mostly useful for docker and deployment
current_git_hash=$(shell git rev-parse HEAD)
@@ -149,3 +150,8 @@ deploy/provision:
deploy/app:
@echo "Deploying version $(V) to a remote server"
$(DEPLOY_CMD) playbooks/03_app.yml --extra-vars "app_version=$(V)"
+
+lint/deploy:
+ $(DEPLOY_LINT_CMD) playbooks/01_setup.yml
+ $(DEPLOY_LINT_CMD) playbooks/02_nginx.yml
+ $(DEPLOY_LINT_CMD) playbooks/03_app.yml
diff --git a/deploy/playbooks/01_setup.yml b/deploy/playbooks/01_setup.yml
index 4768bf3..bcb0743 100644
--- a/deploy/playbooks/01_setup.yml
+++ b/deploy/playbooks/01_setup.yml
@@ -1,14 +1,14 @@
- name: Deploy nginx and Let's Encrypt SSL certificate
hosts: intbot_setup
- become: yes
- gather_facts: yes
+ become: true
+ gather_facts: true
tasks:
- name: Install Docker dependencies
- apt:
+ ansible.builtin.apt:
name: "{{ package }}"
state: present
- update_cache: yes
+ update_cache: true
vars:
package:
- apt-transport-https
@@ -21,22 +21,22 @@
- name: Install Docker
block:
- name: Add Docker GPG key
- apt_key:
+ ansible.builtin.apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Add Docker repository
- apt_repository:
+ ansible.builtin.apt_repository:
repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_lsb.codename }} stable
state: present
- name: Install Docker
- apt:
+ ansible.builtin.apt:
name: docker-ce
state: present
- name: Combine non-root users to a single list
- set_fact:
+ ansible.builtin.set_fact:
non_root_user_names: ["{{ nginx_user }}", "{{ app_user }}"]
- name: Create non-root users
@@ -45,10 +45,10 @@
ansible.builtin.user:
name: "{{ username }}"
shell: "/bin/bash"
- generate_ssh_key: yes
+ generate_ssh_key: true
ssh_key_type: ed25519
ssh_key_comment: "{{ username }}@{{ inventory_hostname }}"
- create_home: yes
+ create_home: true
loop: "{{ non_root_user_names }}"
loop_control:
loop_var: username
@@ -59,37 +59,37 @@
state: directory
owner: "{{ username }}"
group: "{{ username }}"
+ mode: "0755"
loop: "{{ non_root_user_names }}"
loop_control:
loop_var: username
- name: Then copy the authorized_keys from root so you can ssh later to the user
- copy:
+ ansible.builtin.copy:
src: "/root/.ssh/authorized_keys"
dest: "/home/{{ username }}/.ssh/authorized_keys"
owner: "{{ username }}"
group: "{{ username }}"
mode: "0600"
- remote_src: "yes"
+ remote_src: true
loop: "{{ non_root_user_names }}"
loop_control:
loop_var: username
- name: Add the non root users (both nginx and app) to docker group
- user:
+ ansible.builtin.user:
name: "{{ username }}"
groups: docker
- append: yes
+ append: true
loop: "{{ non_root_user_names }}"
loop_control:
loop_var: username
- name: Read the deploy public key
- slurp:
+ ansible.builtin.slurp:
src: "/home/{{ app_user }}/.ssh/id_ed25519.pub"
register: deploy_key
- name: Display the public key
- debug:
+ ansible.builtin.debug:
msg: "For private repositories, make sure to put this key as deploy key on github: {{ deploy_key.content | b64decode }}"
-
diff --git a/deploy/playbooks/02_nginx.yml b/deploy/playbooks/02_nginx.yml
index d2b4a60..884dbad 100644
--- a/deploy/playbooks/02_nginx.yml
+++ b/deploy/playbooks/02_nginx.yml
@@ -4,22 +4,28 @@
tasks:
- name: Copy nginx configuration file
ansible.builtin.template:
- src: ../templates/nginx/nginx.conf.j2
+ src: nginx/nginx.conf.j2
dest: ./nginx.conf
+ mode: "0644"
- name: Create a server Makefile (for nginx) to manage on-server tasks
ansible.builtin.template:
- src: ../templates/nginx/Makefile.nginx.j2
+ src: nginx/Makefile.nginx.j2
dest: ./Makefile
+ mode: "0640"
- name: Set up docker-compose.yml on the remote server
ansible.builtin.template:
- src: ../templates/nginx/docker-compose.nginx.yml.j2
+ src: nginx/docker-compose.nginx.yml.j2
dest: ./docker-compose.yml
+ mode: "0640"
- name: Make sure the directory structure for certs exist
- shell: mkdir -p ./data/certbot/conf
+ ansible.builtin.file:
+ path: "/home/{{ ansible_user }}/data/certbot/conf"
+ state: directory
+ mode: "0755"
- name: Display info at the end
- debug:
+ ansible.builtin.debug:
msg: "Go to /home/{{ ansible_user }} and run make certbot/init-staging; then make certbot/upgrade-to-prod"
diff --git a/deploy/playbooks/03_app.yml b/deploy/playbooks/03_app.yml
index eea96b3..85e1c0a 100644
--- a/deploy/playbooks/03_app.yml
+++ b/deploy/playbooks/03_app.yml
@@ -3,26 +3,33 @@
tasks:
- name: Clone the repository to a specific version (to a temp location)
- git:
+ ansible.builtin.git:
repo: "{{ repository_url }}"
dest: /tmp/src
- accept_hostkey: yes
+ accept_hostkey: true
version: "{{ app_version }}"
- name: Build with a given commit hash
# This will be stored in local registry, and available as version to docker-compose
# where we can just reference correct version
- shell: "cd /tmp/src && make docker/build V={{ app_version }}"
+ ansible.builtin.command:
+ chdir: /tmp/src
+ cmd: "/usr/bin/make docker/build V={{ app_version }}"
+ register: output
+ changed_when: output.rc != 0
+ failed_when: output.rc != 0
- name: Create a server Makefile to manage app tasks
ansible.builtin.template:
- src: ../templates/app/Makefile.app.j2
+ src: app/Makefile.app.j2
dest: ./Makefile
+ mode: "0640"
- name: Set up docker-compose.yml for the app
ansible.builtin.template:
- src: ../templates/app/docker-compose.app.yml.j2
+ src: app/docker-compose.app.yml.j2
dest: ./docker-compose.yml
+ mode: "0640"
- name: Check if the env file exists
ansible.builtin.stat:
@@ -31,8 +38,9 @@
- name: If env file doesn't exist - copy the example
ansible.builtin.copy:
- src: ../templates/app/intbot.env.example
+ src: app/intbot.env.example
dest: intbot.env.example
+ mode: "0644"
when: not env_file.stat.exists
- name: If the env file doesn't exist - fail with error message
@@ -41,10 +49,25 @@
when: not env_file.stat.exists
- name: Start docker compose to see if everything is running
- shell: "docker compose up -d"
+ ansible.builtin.command:
+ chdir: "{{ ansible_user_dir }}"
+ cmd: "docker compose up -d"
+ register: output
+ changed_when: output.rc != 0
+ failed_when: output.rc != 0
- name: Migrate on prod
- shell: "make prod/migrate"
+ ansible.builtin.command:
+ chdir: "{{ ansible_user_dir }}"
+ cmd: "/usr/bin/make prod/migrate"
+ register: output
+ changed_when: output.rc != 0
+ failed_when: output.rc != 0
- name: Restart everything and finish
- shell: "docker compose up -d"
+ ansible.builtin.command:
+ chdir: "{{ ansible_user_dir }}"
+ cmd: "docker compose up -d"
+ register: output
+ changed_when: output.rc != 0
+ failed_when: output.rc != 0
diff --git a/deploy/templates/app/.env.example b/deploy/playbooks/templates/app/.env.example
similarity index 100%
rename from deploy/templates/app/.env.example
rename to deploy/playbooks/templates/app/.env.example
diff --git a/deploy/templates/app/Makefile.app.j2 b/deploy/playbooks/templates/app/Makefile.app.j2
similarity index 100%
rename from deploy/templates/app/Makefile.app.j2
rename to deploy/playbooks/templates/app/Makefile.app.j2
diff --git a/deploy/templates/app/docker-compose.app.yml.j2 b/deploy/playbooks/templates/app/docker-compose.app.yml.j2
similarity index 100%
rename from deploy/templates/app/docker-compose.app.yml.j2
rename to deploy/playbooks/templates/app/docker-compose.app.yml.j2
diff --git a/deploy/templates/app/intbot.env.example b/deploy/playbooks/templates/app/intbot.env.example
similarity index 100%
rename from deploy/templates/app/intbot.env.example
rename to deploy/playbooks/templates/app/intbot.env.example
diff --git a/deploy/templates/nginx/Makefile.nginx.j2 b/deploy/playbooks/templates/nginx/Makefile.nginx.j2
similarity index 100%
rename from deploy/templates/nginx/Makefile.nginx.j2
rename to deploy/playbooks/templates/nginx/Makefile.nginx.j2
diff --git a/deploy/templates/nginx/docker-compose.nginx.yml.j2 b/deploy/playbooks/templates/nginx/docker-compose.nginx.yml.j2
similarity index 100%
rename from deploy/templates/nginx/docker-compose.nginx.yml.j2
rename to deploy/playbooks/templates/nginx/docker-compose.nginx.yml.j2
diff --git a/deploy/templates/nginx/nginx.conf.j2 b/deploy/playbooks/templates/nginx/nginx.conf.j2
similarity index 100%
rename from deploy/templates/nginx/nginx.conf.j2
rename to deploy/playbooks/templates/nginx/nginx.conf.j2