長らくZshのプラグインマネージャとして使用してきたZinitからsheldonへと移行するため、GitHub Releasesから実行可能ファイルをダウンロード・インストールするCLIツール gh-rd を Deno で作成しました。
これは何?
TypeScriptの設定ファイルでGitHub ReleasesからインストールするCLIツールを管理できるツールです。
// $XDG_CONFIG_HOME/gh-rd/config.ts import { defineConfig } from "https://raw.githubusercontent.com/Ryooooooga/gh-rd/main/src/config/types.ts"; export default defineConfig({ tools: [ { name: "rossmacarthur/sheldon", }, { name: "BurntSushi/ripgrep", }, { name: "neovim/neovim", enabled: Deno.build.arch === "x86_64", }, ], });
# .zshrc # PATHを通しておく path=( "$XDG_DATA_HOME/gh-rd/bin"(N-/) "$path[@]" ) fpath=( "$XDG_DATA_HOME/gh-rd/completions"(N-/) "$fpath[@]" )
$ gh-rd Installing packages rossmacarthur/sheldon Install completed (0.7.2) BurntSushi/ripgrep Install completed (13.0.0) neovim/neovim Install completed (stable)
ツールの更新も同様のコマンドで行えます (すでに最新リリースのものがインストールされている場合はインストールがスキップされます)。
$ gh-rd Installing packages rossmacarthur/sheldon Install completed (0.7.3) BurntSushi/ripgrep Up to date (13.0.0) neovim/neovim Up to date (stable)
また、インストール時・更新時に任意の処理を実行できる onDownload
hookがあるため、補完の生成などはそのタイミングで行えます。
// $XDG_CONFIG_HOME/gh-rd/config.ts import { defineConfig } from "https://raw.githubusercontent.com/Ryooooooga/gh-rd/main/src/config/types.ts"; async function saveCommandOutput( cmd: [string, ...string[]], to: string, ) { const { stdout } = await new Deno.Command(cmd[0], { args: cmd.slice(1), stderr: "inherit", }).output(); await Deno.writeFile(to, stdout); } export default defineConfig({ tools: [ { name: "cli/cli", async onDownload({ packageDir, bin: { gh } }) { // 補完の生成: gh completion --shell zsh >_gh await saveCommandOutput( [gh, "completion", "--shell", "zsh"], `${packageDir}/_gh`, ); }, }, { name: "direnv/direnv", rename: [ { from: "direnv*", to: "direnv", chmod: 0o755 }, ], async onDownload({ packageDir, bin: { direnv } }) { // 初期化スクリプトのキャッシュ: direnv hook zsh >direnv.zsh await saveCommandOutput( [direnv, "hook", "zsh"], `${packageDir}/direnv.zsh`, ); }, }, ], });
私の運用している設定は以下のdotfilesから参照できます。
経緯
Zinitをやめた理由
2021年にZinitの作者であるpsprint氏がZinitのリポジトリをzdharma organization ごと爆破して以降 *1、zdharma-continuum/zinit を使用してきました。
直近のZinitはログのスタイルが崩れるなど動作の安定性に欠けていたのですが、zdharma-continuum/zinit に対してコントリビューションを続けていたpsprint氏が Zinit 4 なるforkを作成したことでいよいよ諦めてsheldonへと乗り換える決心が付きました。
実のところsheldonへの乗り換えは今まで何度も検討していたのですが、その障害となっていたのがGitHub Releasesからインストールしている様々なモダンCLIツールの存在でした。
ZinitにはGitHub Releasesから実行可能ファイルをインストールする機能 ( from"gh-r"
) があるのですが、sheldonにはそれに類する機能がありません (Issue はありますが放置されています)。
代替手段の検討
自分のdotfilesはmacOSとUbuntu (on WSL2) をターゲットとしており、それらの環境双方で使用できるなんらかの代替手段が必要になりました。 macOSについては自作ツールを含め Homebrew でほぼ全ての必要なツールを管理できますが、aptは対応しているツールの数が極端に少ないため代替にはなり得ません。
そこで以下に示すいくつかの手段の使用を検討しました。
Linuxbrew
HomebrewはLinuxにも対応していますが、Rubyの導入が必要なため諦めました。
aqua
aqua は有力な候補でしたが、aquaはツールバージョンの固定が必須になっています *2。 その点が基本的にツールを最新バージョンに維持しておきたいdotfilesの要求と噛み合いませんでした。
ちなみにRenovateを導入するとバージョン更新をほぼ自動化できますが、dotfilesのコミットログがRenovateで埋め尽くされるのも体験が悪くなることが予想できたため最終的に使用を断念しました。
この通り、需要を満たしてくれるツールが見つからなかったため、結局自作することにしました。
まとめ
これを作成したことでどうにかZinitからsheldonへの宗旨替えに成功しました。
*1: 現在のzdharmaはdomain spoofingです。z-shell/zi はZinitのフォークですが倫理観の無いカスなので使用してはいけません。