背景
現在の ansible/playbook.yaml は tag が for_devcontainer / not_for_wsl の2つで、「付いていない = 全環境で動く」 という暗黙のルールに依存している。否定形の tag (not_for_wsl) と --skip-tags の組み合わせは、対象環境が増えるほど「このroleはどこで動くのか」が読み取れなくなる。
そこで、
- platform tag を
for_devcontainer / for_ubuntu / for_wsl / for_mac の4つに限定し、全roleに明示的に付与する。実行は常に --tags for_X を1つ指定する形にする(--skip-tags は使わない)
docker を dev_tools/tasks/commands/docker.yaml から roles/docker/ に昇格する
- その上で macOS 対応を進める
を行いたい。
設計方針
tag と when: の役割分担
2つの機構が重複して分かりにくくならないよう、責務を分ける。
- tag = 「どの環境を構築しているか」の選択。role単位の粗い ON/OFF のみに使う
when: ansible_os_family / include_tasks: <OS>.yaml = 「今のOSでどう入れるか」。role内部の実装差分に使う
role に付けた tag は配下の全taskに継承されるため、role内のOS差分を task-level tag で表現しないこと(for_ubuntu を選んだ時点でrole内の全taskが対象になる)。
platform tag → role の対応表
現状の挙動を保存した上で、macOS列を追加する。
| role |
for_devcontainer |
for_ubuntu |
for_wsl |
for_mac |
preflight (新規) |
always |
always |
always |
always |
init_snap |
|
✓ |
✓ |
|
xdg_base_directory |
✓ |
✓ |
✓ |
✓ |
dot_rc |
✓ |
✓ |
✓ |
✓ |
system_tools |
|
✓ |
✓ |
✓ |
docker (新規) |
|
✓ |
✓ |
(要判断) |
terminal (wezterm) |
|
✓ |
|
(要判断) |
emacs |
|
✓ |
✓ |
✓ |
dev_tools |
|
✓ |
✓ |
✓ |
fonts |
|
✓ |
✓ |
✓ |
gui_tools |
|
✓ |
|
|
tag の書き方
4つ全部に付くケースが多いので、YAML anchor で重複を避ける。vars: は roles: より前に書けるので同一play内でanchorが解決できる。
- hosts: localhost
vars:
_tags:
all: &tags_all [for_devcontainer, for_ubuntu, for_wsl, for_mac]
linux: &tags_linux [for_ubuntu, for_wsl]
baremetal: &tags_baremetal [for_ubuntu, for_mac]
roles:
- { role: preflight, tags: always }
- { role: init_snap, tags: *tags_linux }
- { role: xdg_base_directory, tags: *tags_all }
- { role: dot_rc, tags: *tags_all }
...
実行方法の強制
tag 無しで叩くと always 以外の全roleが走ってしまうので、preflight role で ansible_run_tags を検査して落とす。
- name: assert exactly one platform tag is specified
ansible.builtin.assert:
that:
- (ansible_run_tags | intersect(_platform_tags) | length) == 1
fail_msg: >-
specify exactly one of {{ _platform_tags | join(', ') }}
(e.g. ansible-playbook ansible/playbook.yaml --tags for_ubuntu)
Phase 1: platform tag の整理 (macOS対応の前提)
Phase 2: docker の role 化
Phase 3: OS抽象化の土台
fd を例にすると、apt では fd-find 名で入り symlink が要る/brew では fd そのままで symlink 不要、という パッケージ名の差 と 手続きの差 の両方が出る。前者はデータ、後者はファイル分割で吸収する。
Phase 4: 手続き差分の大きい role を <OS>.yaml に分割
Phase 5: macOS runner でのCI検証
Linux固有で macOS に持っていかないもの
判断済みとして記録しておく。
init_snap — snapd が存在しない
coredumpctl (systemd-coredump) — 既にコメントアウト済み
nvidia-container — 既に is_ci でskip
.Xmodmap / .config/autostart / xclip / xsel — X11固有(dot_rc の symlink リストを platform で分岐する必要あり)
mlocate / etckeeper — 事実上非対応
gui_tools の gparted / simplescreenrecorder
未確定事項
背景
現在の
ansible/playbook.yamlは tag がfor_devcontainer/not_for_wslの2つで、「付いていない = 全環境で動く」 という暗黙のルールに依存している。否定形の tag (not_for_wsl) と--skip-tagsの組み合わせは、対象環境が増えるほど「このroleはどこで動くのか」が読み取れなくなる。そこで、
for_devcontainer/for_ubuntu/for_wsl/for_macの4つに限定し、全roleに明示的に付与する。実行は常に--tags for_Xを1つ指定する形にする(--skip-tagsは使わない)dockerをdev_tools/tasks/commands/docker.yamlからroles/docker/に昇格するを行いたい。
設計方針
tag と
when:の役割分担2つの機構が重複して分かりにくくならないよう、責務を分ける。
when: ansible_os_family/include_tasks: <OS>.yaml= 「今のOSでどう入れるか」。role内部の実装差分に使うrole に付けた tag は配下の全taskに継承されるため、role内のOS差分を task-level tag で表現しないこと(
for_ubuntuを選んだ時点でrole内の全taskが対象になる)。platform tag → role の対応表
現状の挙動を保存した上で、macOS列を追加する。
preflight(新規)init_snapxdg_base_directorydot_rcsystem_toolsdocker(新規)terminal(wezterm)emacsdev_toolsfontsgui_toolstag の書き方
4つ全部に付くケースが多いので、YAML anchor で重複を避ける。
vars:はroles:より前に書けるので同一play内でanchorが解決できる。実行方法の強制
tag 無しで叩くと
always以外の全roleが走ってしまうので、preflightrole でansible_run_tagsを検査して落とす。Phase 1: platform tag の整理 (macOS対応の前提)
roles/preflight/を追加し、ansible_run_tagsに platform tag がちょうど1つ含まれることを assert する(tags: always)playbook.yamlに tag anchor (_tags.all/_tags.linuxなど) を定義するnot_for_wslを廃止するinstall.shはすでに--tags for_devcontainerなので変更不要 — 動作確認のみ.github/workflows/ansible-ci.yamlの matrix をplaybook_optsの羅列から--tags for_devcontainer/--tags for_ubuntu/--tags for_wslに置き換える--tags for_ubuntu付きに更新するuv run ansible-playbook ansible/playbook.yaml --list-tagsの出力をCIで検査し、4つの platform tag 以外が増えていないことを担保する(任意)Phase 2: docker の role 化
dev_tools/tasks/commands/docker.yamlをroles/docker/tasks/main.yamlへ移動するdocker-ce等のinstall / docker group 設定 の3ブロックをtasks/配下のファイルに分割するis_ciの check_mode 分岐をroles/docker/defaults/main.yamlに移すdev_tools/tasks/main.yamlからimport_tasks: commands/docker.yamlを削除するplaybook.yamlのroles:にdockerを追加(tag は*tags_linux)nvidia-container.yamlは docker に依存するため、roles/docker/配下に置くかmeta/dependenciesで表現するかを決めるPhase 3: OS抽象化の土台
fdを例にすると、apt ではfd-find名で入り symlink が要る/brew ではfdそのままで symlink 不要、という パッケージ名の差 と 手続きの差 の両方が出る。前者はデータ、後者はファイル分割で吸収する。ansible/vars/packages_Debian.yaml/packages_Darwin.yamlにパッケージ名の対応表を作る(値がnullのものはそのOSでskip)playbook.yamlでvars_filesに"vars/packages_{{ ansible_os_family }}.yaml"を追加するroles/common/tasks/_install_package.yamlを追加し、ansible.builtin.apt/community.general.homebrewの分岐を1箇所に閉じ込めるplaybook.yamlの play-levelbecome: trueをbecome: falseに反転し、apt系taskにbecome: trueを明示する理由:
community.general.homebrewは root 実行で異常終了するため。macOS対応の必須前提_install_package.yaml経由に置き換える(system_tools/tasks/main.yamlの14個、dev_toolsの fzf/jq/ripgrep)Phase 4: 手続き差分の大きい role を
<OS>.yamlに分割emacs: snap → brew。.emacs.dの symlink 部分は共通のまま残すsystem_tools/commands/tmux.yaml: snap → brew。plugin clone とtmux-mem-cpu-loadのcmakeビルドは共通fonts: 展開先 (/usr/local/share/fonts→~/Library/Fonts)、fc-cacheの有無、検証コマンド (fc-list) がすべて異なるdev_tools/commands/fd.yaml,bat.yaml: Debian のみfdfind/batcatの symlink が必要difft/act/ghq/lsd/btm。現在URLにx86_64/linux/amd64/.debが直書きされているterminal/commands/wezterm.yaml:.deb(Ubuntu22.04直書き) → caskgui_tools: macOS では対象外(gparted / simplescreenrecorder に対応するcaskが無い)Phase 5: macOS runner でのCI検証
macos-15×--tags for_macを追加するmacos-14/macos-15は arm64、macos-13/macos-15-intelが x86_64Linux固有で macOS に持っていかないもの
判断済みとして記録しておく。
init_snap— snapd が存在しないcoredumpctl(systemd-coredump) — 既にコメントアウト済みnvidia-container— 既にis_ciでskip.Xmodmap/.config/autostart/xclip/xsel— X11固有(dot_rcの symlink リストを platform で分岐する必要あり)mlocate/etckeeper— 事実上非対応gui_toolsの gparted / simplescreenrecorder未確定事項
for_macでは docker role ごと対象外にするか、colima まで面倒を見るかmacos-15) のみ対応か、Intel も両対応にするか