From 9803f23b8d996d06cfdf17ef18291be2a131f6b8 Mon Sep 17 00:00:00 2001 From: jedi Date: Mon, 17 Aug 2026 12:37:18 +0200 Subject: [PATCH] stash --- deploy/prod/.gitignore | 1 + deploy/prod/playbook.yml | 69 ++++++++++++++++++++++++++--- frontend/src/components/Sidebar.vue | 6 +++ 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/deploy/prod/.gitignore b/deploy/prod/.gitignore index cb88020..7e17447 100644 --- a/deploy/prod/.gitignore +++ b/deploy/prod/.gitignore @@ -1,2 +1,3 @@ .secrets/ inventory.yml +.frontend-build/ diff --git a/deploy/prod/playbook.yml b/deploy/prod/playbook.yml index 7096962..d46c406 100644 --- a/deploy/prod/playbook.yml +++ b/deploy/prod/playbook.yml @@ -41,6 +41,13 @@ toolshed_backend_port: 8000 toolshed_wiki_dist_dir: /var/www/toolshed-wiki toolshed_local_dir: /var/www/toolshed-local + # The frontend build runs on the controller (see "Build frontend builder + # docker image (controller)" below) rather than the target host, so its + # scratch checkout and build output live here instead of under + # toolshed_src_dir/toolshed_dist_dir. Keyed by inventory_hostname so + # concurrent deploys to different hosts never collide. + toolshed_frontend_build_src_dir: "{{ playbook_dir }}/.frontend-build/{{ inventory_hostname }}/src" + toolshed_frontend_build_dist_dir: "{{ playbook_dir }}/.frontend-build/{{ inventory_hostname }}/dist" # Django's collectstatic output (admin/drf-yasg assets etc.), exported # from the built backend image so nginx can serve it directly instead of # proxying to gunicorn for every asset request. @@ -248,11 +255,14 @@ {% endif %} tasks: - - name: Install docker.io and nginx + - name: Install docker.io, nginx and rsync ansible.builtin.apt: name: - docker.io - nginx + # rsync is what the frontend dist sync (further down) relies on - + # it's the ansible.posix.synchronize module's transport. + - rsync state: present update_cache: true @@ -319,12 +329,18 @@ # until reloaded. notify: reload nginx + # Owned by ansible_user rather than www-data up front: the frontend dist + # sync below pushes files over a plain rsync-over-ssh connection as + # ansible_user (synchronize shells out to the local rsync binary, which + # opens its own ssh session - it doesn't go through Ansible's become), + # so that account needs write access here first. "Fix ownership of + # exported frontend build" resets this to www-data (via become) right + # after the sync completes. - name: Create frontend static output directory ansible.builtin.file: path: "{{ toolshed_dist_dir }}" state: directory - owner: www-data - group: www-data + owner: "{{ ansible_user }}" mode: "0755" - name: Create backend static output directory @@ -430,17 +446,56 @@ enabled: true state: started - - name: Build frontend builder docker image + # The next few tasks build the frontend on the controller instead of the + # target host: `npm run build` pulls in bootstrap+jquery+vue+moment+ + # js-nacl+qrcode, and esbuild's rendering/minification pass for that + # bundle needs more memory than small/memory-constrained target hosts + # (e.g. LXC containers without usable swap) reliably have. Only the + # resulting static dist/ is shipped to the target - the docker image + # itself never runs there. This assumes docker is already usable on the + # controller (not managed by this playbook, since "Install docker.io, + # nginx and rsync" above targets the remote host only). + - name: Checkout toolshed source (controller, for frontend build) + ansible.builtin.git: + repo: "{{ toolshed_repo_url | mandatory('toolshed_repo_url must be set as a host_var for ' ~ inventory_hostname) }}" + dest: "{{ toolshed_frontend_build_src_dir }}" + version: "{{ toolshed_version | default('stable') }}" + force: true + recursive: false + delegate_to: localhost + become: false + + - name: Build frontend builder docker image (controller) ansible.builtin.command: cmd: >- docker build -t {{ toolshed_frontend_image }}:{{ toolshed_image_tag }} - -f {{ toolshed_src_dir }}/deploy/prod/Dockerfile.frontend {{ toolshed_src_dir }}/frontend + -f {{ toolshed_frontend_build_src_dir }}/deploy/prod/Dockerfile.frontend {{ toolshed_frontend_build_src_dir }}/frontend changed_when: true + delegate_to: localhost + become: false - - name: Run frontend builder once to export the static build + - name: Create local frontend dist scratch directory (controller) + ansible.builtin.file: + path: "{{ toolshed_frontend_build_dist_dir }}" + state: directory + mode: "0755" + delegate_to: localhost + become: false + + - name: Run frontend builder once to export the static build (controller) ansible.builtin.command: - cmd: docker run --rm -v {{ toolshed_dist_dir }}:/output {{ toolshed_frontend_image }}:{{ toolshed_image_tag }} + cmd: docker run --rm -v {{ toolshed_frontend_build_dist_dir }}:/output {{ toolshed_frontend_image }}:{{ toolshed_image_tag }} changed_when: true + delegate_to: localhost + become: false + + - name: Sync built frontend dist to the target host + ansible.posix.synchronize: + src: "{{ toolshed_frontend_build_dist_dir }}/" + dest: "{{ toolshed_dist_dir }}/" + delete: true + delegate_to: localhost + become: false - name: Fix ownership of exported frontend build ansible.builtin.file: diff --git a/frontend/src/components/Sidebar.vue b/frontend/src/components/Sidebar.vue index c55f002..de5fc9a 100644 --- a/frontend/src/components/Sidebar.vue +++ b/frontend/src/components/Sidebar.vue @@ -51,6 +51,12 @@ Swatch +