はじめに

私の dotfiles では、ローカルの dry-run と GitHub Actions で、設定の変更を確認できるようにしています。dotfiles の設定適用にはスクリプトを使っていたのですが、手を入れるうちにスクリプトとテストコードが増えてきました。

そこで、シンボリックリンクの作成・解除や、パッケージ・開発ツールの導入を mise bootstrap に寄せました。

この記事では、もともとスクリプトで行っていた処理と、mise に移したあとの設定やコマンドを紹介します。

1. もともとはスクリプトで導入・解除していた

dotfiles のセットアップは、PC のリプレイスなどを除けば頻繁に実行するものではありません。

そこで、ローカルでは dry-run で適用・解除の内容を確認し、GitHub Actions では自動テスト用に HOME 相当のディレクトリを用意して、一連の操作を試せるようにしていました。

当初は、複雑なことをしていなかったので、mise のようなツールを使うのはオーバーキルだと考えていました。そのため、install / uninstall といった操作に使うスクリプトを書いていました。

その後、適用前に dry-run で内容を確認したい、ローカルと CI でできるだけ同じ操作を使いたい、と要件が増えていきました。導入処理とは別に、それらを支えるスクリプトやテストコードも増え、構成が複雑になってきました。

要件が増えるたびに、実装とテストの両方を変更する必要がありました。dotfiles の設定に加えて、導入・解除の仕組みも自分でメンテすることになっていました。そこで、mise bootstrap を使って、このあたりをまとめて管理することにしました。

2. dotfiles の配置とツールの導入を mise bootstrap にまとめる

mise bootstrap は、[dotfiles]、[bootstrap.packages]、[tools] などの設定をまとめて扱います。dotfiles だけを操作したい場合は mise dotfiles のコマンドを使えます。

dotfiles だけを操作するには、mise dotfiles を使えます。

2-1. シンボリックリンクの配置先を [dotfiles] に書く

mise.toml の [dotfiles] に、どのファイルをどこへ配置するかを記述します。下記は一例です。

[dotfiles]
# "<target>" = { source = "<リポジトリをルートとした相対パス>", mode = "<symlink/シンボリックリンクなど指定したいモード>" }

"~/.dotfiles" = { source = ".", mode = "symlink" }
"~/.bashrc" = { source = ".bashrc", mode = "symlink" }
"~/.bash_profile" = { source = ".bash_profile", mode = "symlink" }
"~/.gitconfig" = { source = ".gitconfig", mode = "symlink" }
"~/.config/mise/config.toml" = { source = "mise.toml", mode = "symlink" }

各エントリに mode = "symlink" を明示して、シンボリックリンクで配置するようにしています。たとえば、~/.bashrc にはリポジトリ内の .bashrc へのリンクを作ります。リンクの作成・解除は mise に任せるので、dotfiles 側では配置先の設定をメンテすることになります。

2-2. パッケージや開発ツールを [bootstrap.packages] と [tools] に書く

Homebrew で導入する Git は、同じ mise.toml の [bootstrap.packages] に書いています。

[bootstrap.packages]
"brew:git" = "latest"

Node.js や Python などの開発ツールは [tools] に記述します。mise bootstrap を実行すると、パッケージの導入、シンボリックリンクの配置、開発ツールの導入をまとめて行えます。私の構成では、Makefile から mise bootstrap を呼び出しています。

3. 一連の操作を Makefile に集約する

Homebrew と mise のセットアップからインストール、状態確認、アンインストールまで、Makefile を共通のエントリポイントにしています。mise 導入後の操作は、Makefile から mise-operations.toml のタスクを経由して mise bootstrap などを呼び出します。

make setup           # Homebrew と mise を準備
make install         # install 内容を確認(dry-run)
make install-apply   # install する
make verify          # install できたか確認
make uninstall       # シンボリックリンクの解除対象を確認(dry-run)
make uninstall-apply # シンボリックリンクを解除

uninstall は実際にアンインストールするわけではなく、dotfiles のファイル群のシンボリックリンクを解除することに留めました。この点は「### 3-5. アンインストールではシンボリックリンクだけを解除する」で後述します。

3-1. 設定と操作を分ける

構成は次のようにしています。

Makefile
  make install / make install-apply / make verify
    │ mise run でタスクを呼び出す
    ▼
mise-operations.toml(操作用のタスク)
  dotfiles:install / dotfiles:install:apply / dotfiles:verify
    │ MISE_CONFIG_FILE で mise.toml を指定
    ▼
mise.toml(配置先・導入するものの設定)
  [dotfiles]           シンボリックリンクの配置先
  [bootstrap.packages] パッケージ
  [tools]              開発ツール

setup 以外の操作は mise-operations.toml のタスクを経由します。配置先や導入対象は mise.toml に置き、操作用のタスクとは分けています。

3-2. Makefile から操作用のタスクを呼び出す

Makefile では MISE_CONFIG_FILE に操作用の mise-operations.toml を指定し、mise run で対応するタスクを呼び出します。

MISE := mise
MISE_CONFIG := $(CURDIR)/mise-operations.toml
MISE_RUN = MISE_CONFIG_FILE="$(MISE_CONFIG)" MISE_TRUSTED_CONFIG_PATHS="$(CURDIR)" $(MISE)

.PHONY: install install-apply

install:
	$(MISE_RUN) run dotfiles:install

install-apply:
	$(MISE_RUN) run dotfiles:install:apply

3-3. タスクから mise.toml を読み込む

mise-operations.toml では、タスク内の MISE_CONFIG_FILE に mise.toml を指定します。これにより、操作用のタスクと、dotfiles やパッケージなどの設定を分けています。

[env]
DOTFILES = "{{ config_source | canonicalize | dirname }}"

[task_config]
dir = "{{ env.DOTFILES }}"

[tasks."dotfiles:install"]
run = 'MISE_CONFIG_FILE="$DOTFILES/mise.toml" mise bootstrap --dry-run'

[tasks."dotfiles:install:apply"]
run = 'MISE_CONFIG_FILE="$DOTFILES/mise.toml" mise bootstrap --yes'

mise.toml は ~/.config/mise/config.toml にシンボリックリンクで配置しますが、操作用の mise-operations.toml はグローバル設定にはせず、Makefile から明示的に指定しています。

3-4. dry-run、適用、状態確認を使い分ける

install 時は、適用内容の確認・実際の適用・適用後の状態確認でコマンドを分けています。

  • make install:mise bootstrap --dry-run で変更内容を確認する
  • make install-apply:mise bootstrap --yes で適用する
  • make verify:mise bootstrap status --missing で不足しているものを確認する

3-5. アンインストールではシンボリックリンクだけを解除する

アンインストールでは、環境全体を元に戻すのではなく、mise が管理しているシンボリックリンクだけを解除します。

  • make uninstall:mise bootstrap dotfiles unapply --dry-run で解除内容を確認する
  • make uninstall-apply:mise bootstrap dotfiles unapply --yes で管理しているシンボリックリンクを解除する

パッケージや開発ツールは残るため、環境全体を導入前の状態に戻す操作ではありません。

4. GitHub Actions では何を確認する?

GitHub Actions では、自動テスト用に HOME 相当のディレクトリを用意し、Makefile から一連の操作を試しています。mise 自体の挙動をテストするのではなく、mise.toml の設定と Makefile からの呼び出しを組み合わせて、ローカルと同じ操作が成立することを確認しています。

5. 補足:リポジトリに載せたくない設定

最後に、リポジトリに載せたくない設定の扱いにも少し触れておきます。Git の設定では、そうしたものを ~/.gitconfig.local に分け、リポジトリ内の .gitconfig から include で読み込んでいます。

[include]
    path = ~/.gitconfig.local

リポジトリには記入例として .gitconfig.local.example を置き、実際の値は手元の ~/.gitconfig.local に記入する形です。

6. まとめ

dotfiles の導入・解除に使っていたスクリプトの処理を mise に寄せました。dry-run と GitHub Actions で変更を確認する流れは残しつつ、シンボリックリンクの作成・解除やパッケージ、開発ツールの導入は mise に任せています。

7. 参考リンク