--- # Синхронизация репозитория контура в gitea. # # Flux читает манифесты ИЗ gitea, а не из этого репозитория, поэтому содержимое # нужно туда доставить. Схема: control-node пакует нужное подмножество путей в # архив → ansible кладёт его на хост → на хосте архив распаковывается в рабочую # копию репозитория gitea и коммитится. # # Почему коммит делается на хосте, а не push'ем с control-node: gitea публикует # порт только на самом хосте, и контур остаётся замкнутым — наружу за git никто # не ходит. # # Синхронизируется ЗАМЫКАНИЕ ссылок clusters/aero (gitea_sync_paths), а не весь # репозиторий: ansible-роль, snapshots и docs кластеру не нужны. # # Идемпотентно: если содержимое не изменилось, коммита не будет. - name: Установить git на хосте (нужен для коммита в gitea) ansible.builtin.package: name: git state: present - name: Проверить, что синхронизируемые пути существуют ansible.builtin.stat: path: "{{ deploy_src_root }}/{{ item }}" loop: "{{ gitea_sync_paths }}" loop_control: label: "{{ item }}" delegate_to: localhost become: false register: gitea_sync_stat - name: Прервать деплой, если путь из gitea_sync_paths отсутствует ansible.builtin.fail: msg: >- Путь {{ item.item }} указан в gitea_sync_paths, но отсутствует в репозитории. Список должен совпадать с тем, на что ссылается clusters/aero — иначе kustomize в кластере упадёт. loop: "{{ gitea_sync_stat.results }}" loop_control: label: "{{ item.item }}" when: not item.stat.exists # Архив собирается из РАБОЧЕГО ДЕРЕВА, а не из HEAD: синхронизировать нужно то, # что лежит на диске, включая ещё не закоммиченные локально правки. - name: Собрать архив синхронизируемых путей на control-node ansible.builtin.command: cmd: "tar -czf {{ gitea_sync_archive_local }} {{ gitea_sync_paths | join(' ') }}" chdir: "{{ deploy_src_root }}" delegate_to: localhost become: false changed_when: true - name: Запомнить исходную ревизию (для сообщения коммита) ansible.builtin.command: cmd: git rev-parse --short HEAD chdir: "{{ deploy_src_root }}" delegate_to: localhost become: false register: gitea_sync_rev changed_when: false failed_when: false - name: Скопировать архив на хост ansible.builtin.copy: src: "{{ gitea_sync_archive_local }}" dest: "{{ gitea_sync_archive_remote }}" mode: "0600" - name: Синхронизировать и закоммитить содержимое в gitea ansible.builtin.shell: cmd: | set -eu WORKDIR={{ gitea_sync_workdir | quote }} BRANCH={{ aero_git_branch | quote }} URL={{ gitea_sync_url | quote }} mkdir -p "$WORKDIR" cd "$WORKDIR" # Клон может не существовать, а репозиторий в gitea — быть пустым (до # первого коммита у него нет ни одной ветки). init+fetch переживает оба # случая, в отличие от `git clone`, который на пустом репозитории # оставляет рабочую копию без ветки. [ -d .git ] || git init -q git config user.name {{ gitea_commit_name | quote }} git config user.email {{ gitea_commit_email | quote }} git remote remove origin 2>/dev/null || true git remote add origin "$URL" if git fetch -q origin "$BRANCH" 2>/dev/null; then git checkout -q -B "$BRANCH" FETCH_HEAD else git checkout -q -B "$BRANCH" fi # Управляемые пути удаляются перед распаковкой, иначе файлы, удалённые в # исходном репозитории, остались бы в gitea навсегда: `git add -A` увидит # удаление только если файла действительно нет на диске. for p in {{ gitea_sync_paths | join(' ') }}; do rm -rf "$p" done tar -xzf {{ gitea_sync_archive_remote | quote }} git add -A if git diff --cached --quiet; then echo "SYNC_RESULT=nochange" else git commit -q -m "sync from control-node ({{ gitea_sync_rev.stdout | default('unknown') }})" echo "SYNC_RESULT=committed" fi git push -q origin "$BRANCH" echo "SYNC_DONE" chdir: "{{ deploy_dir }}" register: gitea_sync_result changed_when: "'SYNC_RESULT=committed' in gitea_sync_result.stdout" no_log: true - name: Удалить архив с хоста ansible.builtin.file: path: "{{ gitea_sync_archive_remote }}" state: absent - name: Удалить архив с control-node ansible.builtin.file: path: "{{ gitea_sync_archive_local }}" state: absent delegate_to: localhost become: false - name: Итог синхронизации ansible.builtin.debug: msg: >- gitea {{ gitea_org }}/{{ gitea_repo }}@{{ aero_git_branch }}: {{ 'закоммичены изменения' if 'SYNC_RESULT=committed' in gitea_sync_result.stdout else 'изменений нет' }} (источник {{ gitea_sync_rev.stdout | default('unknown') }}, путей: {{ gitea_sync_paths | length }})