ローカル環境の管理戦略を一新しよう
overview
intro
経緯
今まで環境構築時に、ansible + dotfile リポジトリ + 独自スクリプトを用いて
- dotfiles の配置
- git prompt (powerline 等) の便利ツール配置
をしていました。
課題感
しかしながら、以下の理由から煩わしさを感じていました。
- 都度 playbook を記述するのが面倒
- role 作って配置して... など
- 配置した機能の on/off をするのが面倒
業務 PC がモタつくのもあり、新 PC の乗り換えが決まったので
ローカル環境管理を見直すことにしました。
新しい管理戦略
方針
おおまかに以下をゴールに設定しました。
- マルチ OS (MacOS / WSL2 ≒ linux) に対応できるようにする
- ファイルの配置に独自スクリプトを使用しない
- dotfiles の管理を簡素化する
選定したツール
Homebrew
言わずと知れたパッケージマネージャ。mac 以外にも linux であれば利用可能。
chezmoi
ドットファイル管理ツール。複数 OS 対応
asdf
CLI のバージョン管理ツール。terraform など頻繁にバージョンを出し入れする場合に使用
解説
Homebrew
今までパッケージマネージャは OS にデフォルトで備わるものを利用していました。
あくまでローカル環境の管理なので、ポータビリティを優先して Homebrew を使うことにします。
新しい業務 PC が Mac になるかもしれないというのも理由の一つ。
chezmoi
(読み:シェモア)
今回一番推したいツール。
dotfile そのものの管理 + 配置用コマンド が用意されているため
./init.sh みたいなものを手書きする必要がない。
asdf
これも環境差分吸収の意味合いが大きいです。
あと『terraform は tfenv』『golang は goenv』みたいに、都度〇〇env を入れるのが不毛に思えたので...
ポイント
bashrc zshrc のフラグメント化
例えば go のツールや git のユーティリティを入れた場合
都度 bashrc, zshrc に追加の記述が必要になると思います。
今までもフラグメント化のアイデア自体はあって
- ansible テンプレートを作成
- /etc/profile.d/ に配置
で対応してたのですが、dotfile 側にディレクトリ設けてまるっと読み込ませればよくね?
と思い、そうすることに。
ディレクトリ構造
~/.bashrc or ~/.zshrc から ~/.shellrc.d 配下のファイルを読むように記述
*.sh なら bash, zsh 共通 *.{bash,zsh} なら対応した SHELL から読まれる仕組み。
ファイル名順に読み込ませるようにしたので、順番の制御も可能です。
### Write your commands to ~/.shellrc.d/xxx.{sh,zsh}
if [ -d ~/.shellrc.d ]; then
for i in `find ~/.shellrc.d/*.{sh,zsh} -type f | sort`; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi
樹形図
boomkun: ~ $ eza -TA -L 2 ~/.
/home/boomkun
├── .bashrc
├── .shellrc.d
│ ├── 010_aliases.sh
│ ├── 010_brew.sh
│ ├── 010_environment.sh
│ ├── 010_environment.zsh
│ ├── 010_git_util.bash.disabled
│ ├── 010_git_util.zsh
│ ├── 010_shopt.bash
│ ├── 010_vscode_integration.bash
│ ├── 010_vscode_integration.zsh
│ ├── 100_asdf.bash
│ ├── 100_asdf.zsh
│ ├── 200_go.sh
│ ├── 200_powerline-go.bash
│ ├── 200_powerline-go.zsh
│ └── 200_powerline-go.zsh.disabled
└── .zshrc
例えば
- asdf は brew で入れるので、brew の読み込みが先
- go は asdf で入れるので asdf の読み込みが先
- でないと
$(go env GOPATH)が通らない
- でないと
などの配慮ができる。
非インストール時への配慮
この手の dotfiles 管理であるあるなのが
『スクリプトで全部入れるので、bashrc, zshrc に入っている前提で書いてしまう』
というのが考えられます。
例えば Homebrew にパスを通すとき /home/linuxbrew/.linuxbrew/bin/brew を実行するのですが
当然ながら Homebrew が入っていなければ失敗します。
なので『入ってない場合は実行しない』を {bash,zsh}rc には徹底しています。
# homebrew
if [ -f /home/linuxbrew/.linuxbrew/bin/brew ]; then
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
fi
# asdf install by brew on zsh
if [ -f /home/linuxbrew/.linuxbrew/opt/asdf/libexec/asdf.sh ]; then
. "/home/linuxbrew/.linuxbrew/opt/asdf/libexec/asdf.sh"
fi
chezmoi の利用
dotfile の管理ツールということは前述したので省きます。
詳細な使い方は他の方も記事書いてらっしゃるので、そちらを参照のこと。
ここでは便利だと思ったポイントに絞って紹介。
chezmoiexternals
従来の環境構築時に ansible を利用していた理由でもあるんですが
git-prompt などを配置する際、外部からファイルをダウンロードして特定のパスに配置する必要があります。
ansible の場合
- block:
- name: git-completion download
get_url:
url: https://raw.github.com/git/git/master/contrib/completion/git-completion.bash
dest: ~/.git-completion.bash
- name: git-prompt download
get_url:
url: https://raw.github.com/git/git/master/contrib/completion/git-prompt.sh
dest: ~/.git-prompt.bash
この管理手法だと
- dotfiles 側のリポジトリに入っていてほしいものが ansible で管理される
- ansible をたたくまで、dotfile で定義した環境が揃わない
という辛さがありました。
[".git_util/git-completion.bash"]
type = "file"
url = "https://raw.github.com/git/git/master/contrib/completion/git-completion.bash"
executable = true
[".git_util/git-prompt.sh"]
type = "file"
url = "https://raw.github.com/git/git/master/contrib/completion/git-prompt.sh"
executable = true
chezmoi だと上記のように記述でき、以下のようなメリットがあります。
- dotfiles と dotfiles で読むのに必要な外部ファイルが同じリポジトリ・スキームで管理できる
- 常に最新のファイルが参照できる
chezmoiscripts
~/.chezmoiscripts 配下にスクリプトを置くと
- 初回 apply 時のみ
- 変更があった場合のみ
- 毎回の apply 時に実行
という条件付けで任意のスクリプトを実行させられます。
ユースケースとしては、brewfile を置いといてパッケージを一括で入れる などの使い方をするようです。
私は chezmoi を dotfile 管理リポジトリとして捉えているため
スクリプトを実行する役割をもたせるのは違うかなと思い、~/.Brewfile をダンプして管理するのに留めています。
新しいセットアップ手順
dotfile を整えるまでのステップは以下のようになりました。
従来の方法
- dotfile リポジトリクローン
- dotfile セットアップスクリプト実行
- ansible インストール
- ansible リポジトリクローン
- ansible-playbook 実行
新しい方法
- chezmoi インストール
- chezmoi リポジトリクローン
- chezmoi apply
なんなら ↑ の手順をワンライナーでやる方法すらあります。
詳しくは公式ページを確認
sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply $GITHUB_USERNAME
outro
やはり新環境の構築は楽しいですね。
chezmoi の外部ファイルダウンロードはかなりありがたかったです。
Discussion