ファイルを保存するたびにタスクを再実行したい

【mise】mise runでタスクを定義して実行する で紹介したmise runは、実行するたびに手動でコマンドを打つ必要がある。mise watchを使うと、ソースファイルの変更を検知して自動的にタスクを再実行できる。

mise watchにはwatchexecが必要

mise watchは内部でwatchexecというファイル監視ツールを使う。事前にインストールしておく。

$ mise use -g watchexec@latest

mise watchでタスクを実行し変更を監視する

mise.tomlにタスクを定義する。sourcesに監視対象のファイルパターンを指定する。

[tasks.build]
run = "echo building..."
sources = ["src/**/*.txt"]

mise watchにタスク名を指定して実行する。

$ mise watch build

即座に1回タスクが実行され、その後sourcesに一致するファイルが変更されるたびに再実行される。

[Running: mise run build]
[build] $ echo building...
building...
[Command was successful]
[Running: mise run build]
[build] $ echo building...
building...
[Command was successful]

1回目はmise watch実行直後、2回目はsrc/main.txtを編集して保存したタイミングで実行されている。

–postponeで最初の実行をスキップする

mise watchは既定で実行直後に1回タスクを実行するが、--postponeを付けると、最初のファイル変更が発生するまで実行を待機する。

$ mise watch build --postpone

–restartで実行中のコマンドを再起動する

mise runで起動するサーバーのように、実行し続けるタスクを監視したい場合は--restart(-r)を使う。ファイル変更を検知すると、実行中のプロセスを終了してから再度実行する。

$ mise watch serve --restart
[Running: mise run serve]
[serve] $ echo starting server...; sleep 100
starting server...
[serve] ERROR sh exited with non-zero status: killed by SIGTERM
[serve] ERROR task failed
[Running: mise run serve]
[serve] $ echo starting server...; sleep 100
starting server...

–globで監視対象を上書きする

タスクのsourcesとは異なるファイルを監視したい場合は、--globmise watch(内部のwatchexec)が監視するパターンを直接指定する。

$ mise watch build --glob "src2/**/*.rs"

ただし--globが変えるのは監視対象だけであり、タスク自体のsources設定には影響しない。mise runはタスクのsourcesに変更がなければ実行をスキップする機能を持つため、--globで指定したファイルの変更が引き金になってmise watchは再実行を試みても、タスクのsources(src/**/*.txt)側に変更がなければsources up-to-date, skippingと表示されコマンド本体は実行されない。

[Running: mise run build]
[build] $ echo building...
building...
[Command was successful]
[Running: mise run build]
[build] sources up-to-date, skipping
[Command was successful]

タスクのsourcesと異なるファイルを監視したい場合は、--globだけでなくタスク側のsourcesもあわせて見直す必要がある。