From f91ffffe83d74db952e97028a95cccad56918d73 Mon Sep 17 00:00:00 2001 From: "martin.fencl" Date: Tue, 10 Nov 2026 10:19:51 +0100 Subject: [PATCH] feat: update BetterShift configuration to use dynamic versioning and enhance backup procedures --- .DS_Store | Bin 8196 -> 10244 bytes docker-compose/docker-compose-bettershift.yml | 4 +- update_bettershift.yml | 143 ++++++++++++------ 3 files changed, 97 insertions(+), 50 deletions(-) diff --git a/.DS_Store b/.DS_Store index 2c90403c9d0975d4be96cc5414a51c0db70656a3..98c09f267fe0d5e2805ab5c9e6dd44c99d94660e 100644 GIT binary patch delta 1187 zcmb`Gy)Q#i7{;Hrw71%{x6+726IU1vQpA8kqKb_W2^NF)Qj*f!ulPvh8b~aL=7z*9 z{(z=`1dD-@4TG4N3>NQct3BtsI=RXHI?r>?^E)5!(fH9^I{@26UL6D!`jqHqZ`oT& zw-v%&flm6d(La)j!G(BgODm?&U4_Fy$t5*OI#ZhvMgp72{Wz!%a7sm9+e%GN#*(QR zwMlQd8(EyaiHN$|P}epp>C^{kQP|T5)o7JF{8cX21Vkexue|3B@_8>GD@$F`n~33+ z6%y(}ydVn+cn5PE$8CPS8S6B=B-W4>W{8$Y3glEi^EELXTJA2-QE=45tsNqTOaVIF z*rxDZNPKD%6kWs!?QyR%Dg7hOJIUToKu4?czZK{rmT$7iAEO@oG>y zo!G`!0kB*>a3M>Zl_5BdAWi4S`#^9e2M_j?KU?mm^ICC5_eHYW84#OXs585kL-^*khFu>l17CJQ^7#q 0 + fail_msg: "Missing or empty file: {{ item.item }}" + loop: "{{ bettershift_files.results }}" + loop_control: + label: "{{ item.item }}" - - name: Upload BetterShift compose file to remote host + - name: Check database before changing deployment + ansible.builtin.command: + argv: + - python3 + - -c + - | + import pathlib, sqlite3, sys + path = pathlib.Path(sys.argv[1]) + with sqlite3.connect(path.as_uri() + '?mode=ro', uri=True) as src: + with sqlite3.connect(':memory:') as db: + src.backup(db) + integrity = db.execute('PRAGMA integrity_check').fetchall() + errors = db.execute('PRAGMA foreign_key_check').fetchall() + print('Integrity:', integrity, 'Foreign key violations:', errors) + sys.exit(0 if integrity == [('ok',)] and not errors else 1) + - "{{ bettershift_data_dir }}/sqlite.db" + changed_when: false + + - name: Upload BetterShift compose file ansible.builtin.copy: src: "{{ compose_local_dir }}/{{ bettershift_compose_filename }}" dest: "{{ compose_remote_base }}/{{ bettershift_compose_filename }}" - mode: "0644" + mode: '0644' + backup: true - - name: Check BetterShift env file exists on remote host - ansible.builtin.stat: - path: "{{ compose_remote_base }}/.env.bettershift" - register: bettershift_env_file + - name: Pull image without starting it + community.docker.docker_compose_v2_pull: + project_name: "{{ bettershift_project }}" + project_src: "{{ compose_remote_base }}" + files: ["{{ bettershift_compose_filename }}"] - - name: Fail if BetterShift env file is missing - ansible.builtin.fail: - msg: >- - Missing {{ compose_remote_base }}/.env.bettershift on remote host. - Create it manually because it contains secrets. - when: not bettershift_env_file.stat.exists + - name: Create private backup directory + ansible.builtin.tempfile: + state: directory + path: /data/compose/bettershift + prefix: backup-before-upgrade- + register: bettershift_backup - - name: Pull latest BetterShift image + - name: Show backup location + ansible.builtin.debug: + msg: "Backup: {{ bettershift_backup.path }}" + + - name: Stop service and create a verified backup + block: + - name: Stop BetterShift + ansible.builtin.command: + argv: [docker, stop, --timeout, '60', bettershift] + changed_when: true + + - name: Copy data and compare files + ansible.builtin.shell: | + set -eu + test "$(docker inspect --format '{% raw %}{{.State.Running}}{% endraw %}' bettershift)" = false + cp -a -- "$DATA_DIR" "$BACKUP_DIR/data" + diff -qr -- "$DATA_DIR" "$BACKUP_DIR/data" + environment: + DATA_DIR: "{{ bettershift_data_dir }}" + BACKUP_DIR: "{{ bettershift_backup.path }}" + changed_when: true + + rescue: + - name: Restart original container if backup fails + ansible.builtin.command: + argv: [docker, start, bettershift] + changed_when: true + + - name: Abort update + ansible.builtin.fail: + msg: Backup failed. Original container restarted; update aborted. + + - name: Recreate BetterShift once community.docker.docker_compose_v2: project_name: "{{ bettershift_project }}" project_src: "{{ compose_remote_base }}" - files: - - "{{ bettershift_compose_filename }}" - pull: always - - - name: Recreate BetterShift service - community.docker.docker_compose_v2: - project_name: "{{ bettershift_project }}" - project_src: "{{ compose_remote_base }}" - files: - - "{{ bettershift_compose_filename }}" - services: - - "{{ bettershift_service }}" + files: ["{{ bettershift_compose_filename }}"] + services: ["{{ bettershift_service }}"] state: present + pull: never recreate: always - - name: Wait for BetterShift port - ansible.builtin.wait_for: - host: 127.0.0.1 - port: "{{ bettershift_port }}" - timeout: 60 - - name: Check BetterShift HTTP endpoint ansible.builtin.uri: url: "http://127.0.0.1:{{ bettershift_port }}/" - status_code: - - 200 - - 307 - - 308 + status_code: [200, 307, 308] follow_redirects: none register: bettershift_http retries: 30 delay: 3 - until: bettershift_http.status in [200, 307, 308] + until: bettershift_http.status | default(0) in [200, 307, 308] changed_when: false