以下の内容はhttps://swfz.hatenablog.com/entry/2024/11/10/191523より取得しました。


Ansibleのgitモジュールでcloneしたリポジトリの変更を残したままにする

あまりないケースかとは思うけど、自分には必要だった

自分はdotfilesの管理をAnsibleで行っていて、dotfilesのリポジトリの中にansibleディレクトリがありそれを実行するようにしている

基本ローカルで実行することを想定してたのでAnsibleのgitモジュールでdotfilesリポジトリをcloneして設定ファイルなどのシンボリックリンクなどを行っていた

ただ、この辺の処理に手を加えて試しにローカルで実行しようとするとエラーが出る

 - name: Clone dotfiles repository
   ansible.builtin.git:
     repo: "{{ repo }}"
     dest: "{{ dotfiles_path }}"
     clone: true

この設定で実行すると

fatal: [localhost]: FAILED! => changed=false  
before: 81e3473d8b36204aeedb45d40cd78b2199ffbb5a  
msg: 'Local modifications exist in the destination: /path/to/dotfiles (force=no).'

ローカルで変更があると失敗するようになっている

エラーが出ないようにするにはforce: trueで変更を上からなくすことでエラーは出なくなる(changed扱い)

 - name: Clone dotfiles repository
   ansible.builtin.git:
     repo: "{{ repo }}"
     dest: "{{ dotfiles_path }}"
     clone: true
     force: true

これでエラーは出ないようになるがそれまで作業していたデータが消えてしまう

tag管理でうまくやるとか、他のVMから実行するとか、回避方法はいくつかあると思うが今触ってる環境でとりあず実行したいけど差分は残しておきたい、差分を適用したplaybookを実行したいみたいなときに便利かと思って対応できる処理を書いてみた

  • ansible/roles/deploy/tasks/main.yml
+- name: Check repository directory exists
+  ansible.builtin.stat:
+    path: "{{ dotfiles.dest }}"
+  register: dotfiles_dir
+
+- name: Check unstaged changes  # noqa command-instead-of-module
+  ansible.builtin.command:
+    cmd: git diff --exit-code
+    chdir: "{{ dotfiles.dest }}"
+  register: repo_changed
+  ignore_errors: true
+  changed_when: repo_changed.rc != 0
+  when: dotfiles_dir.stat.exists
+
+- name: Stash Changes  # noqa command-instead-of-module
+  ansible.builtin.command: git stash
+  when: repo_changed is defined and repo_changed.rc is defined and repo_changed.rc != 0
+  changed_when: true

 - name: Clone dotfiles repository
   ansible.builtin.git:
     repo: "{{ repo_prefix }}{{ dotfiles.src.repo }}"
     dest: "{{ dotfiles.dest }}"
     clone: true
     update: true
     force: true

+- name: Pop stash changes  # noqa command-instead-of-module
+  ansible.builtin.command: git stash pop
+  when: repo_changed is defined and repo_changed.rc is defined and repo_changed.rc != 0
+  changed_when: true

要はcloneの前に変更があればstashして、clone後にpopするだけ

上書きの範囲がどの程度のものなのか深追いしていないからよくわかっていないが変更の情報が存在する.gitディレクトリは上書きしないようなのでこれで行けた

gitコマンド使っているがgitモジュールで同様の機能を実現はできなそうだったのでlint対象から除外している(# noqa command-instead-of-module)

これで冒頭書いていた不便がなくなったのでだいぶやりやすくなった




以上の内容はhttps://swfz.hatenablog.com/entry/2024/11/10/191523より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14