Skip to content

ansible: platform tagの明示化・dockerのrole化とmacOS対応 #157

Description

@soblin

背景

現在の ansible/playbook.yaml は tag が for_devcontainer / not_for_wsl の2つで、「付いていない = 全環境で動く」 という暗黙のルールに依存している。否定形の tag (not_for_wsl) と --skip-tags の組み合わせは、対象環境が増えるほど「このroleはどこで動くのか」が読み取れなくなる。

そこで、

  1. platform tag を for_devcontainer / for_ubuntu / for_wsl / for_mac の4つに限定し、全roleに明示的に付与する。実行は常に --tags for_X を1つ指定する形にする(--skip-tags は使わない)
  2. dockerdev_tools/tasks/commands/docker.yaml から roles/docker/ に昇格する
  3. その上で 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対応の前提)

  • roles/preflight/ を追加し、ansible_run_tags に platform tag がちょうど1つ含まれることを assert する(tags: always
  • playbook.yaml に tag anchor (_tags.all / _tags.linux など) を定義する
  • 全roleに platform tag を明示的に付与し、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 に置き換える
  • README のセットアップ手順を --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.yamlroles/docker/tasks/main.yaml へ移動する
  • apt repository 追加 / 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.yamlroles: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.yamlvars_files"vars/packages_{{ ansible_os_family }}.yaml" を追加する
  • roles/common/tasks/_install_package.yaml を追加し、ansible.builtin.apt / community.general.homebrew の分岐を1箇所に閉じ込める
  • playbook.yaml の play-level become: truebecome: false に反転し、apt系taskに become: true を明示する
    理由: community.general.homebrew は root 実行で異常終了するため。macOS対応の必須前提
  • 単純な一括installを _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 が必要
  • バイナリ直DL系の arm64 対応 — difft / act / ghq / lsd / btm。現在URLに x86_64 / linux / amd64 / .deb が直書きされている
  • terminal/commands/wezterm.yaml: .deb (Ubuntu22.04 直書き) → cask
  • gui_tools: macOS では対象外(gparted / simplescreenrecorder に対応するcaskが無い)

Phase 5: macOS runner でのCI検証

  • CI matrix に macos-15 × --tags for_mac を追加する
  • arm64 前提の確認 — macos-14 / macos-15 は arm64、macos-13 / macos-15-intel が x86_64
  • runner に git / curl / gh / rustup / Homebrew がプリインストール済みである点を踏まえ、「既にある」パスばかり通っていないか確認する
  • macOS runner の課金レートは Linux の10倍なので、PR毎に回すか nightly に回すかを決める

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

未確定事項

  • docker: GitHub-hosted macOS runner には Docker デーモンが無く、入れる手段も実質無い(Docker Desktop はライセンス+GUI、colima/lima は起動が重い)。for_mac では docker role ごと対象外にするか、colima まで面倒を見るか
  • アーキテクチャ: arm64 (macos-15) のみ対応か、Intel も両対応にするか
  • ゴール: 「CIが緑になる」までか、「実機のmacOS開発環境として使える」ところまでか

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions