💧

aqua が Go 製のツールのビルドをサポート

2022/06/08に公開

CLI ツールを YAML でバージョン管理できるツール aqua を開発しています。

https://aquaproj.github.io/

https://zenn.dev/topics/aquaclivm

aqua が v1.7.0 及び v1.10.0 から binary を提供していない Go 製のツールのインストールをサポートしたので紹介します。

多くの Go 製の CLI はビルド済みのバイナリを提供しているため、ユーザーは自分でビルドすることなくツールを利用することが出来、 aqua でも多くの Go 製の CLI をサポートしています。
例えば tfcmt は GitHub Releases からバイナリをダウンロード出来ますし、 Terraform は公式サイトからダウンロードできます。

しかし中にはビルド済みのバイナリを提供しておらず、自分でビルドする必要のあるツールもあります。
例えば google/wire は 2022-06-08 現在バイナリを提供しておらず、 go install コマンドを実行してインストールする必要があります。

aqua は基本的にインストール時に外部コマンドの実行をサポートしていません。これは aqua の基本的なデザインです。

https://github.com/aquaproj/aqua-registry/issues/987#issuecomment-1104422712

そのため google/wire のようなツールはこれまで aqua はサポートしてきませんでしたが、 aqua v1.7.0 及び v1.10.0 からインストール時に go build あるいは go install の実行をサポートするようになりました。
これは上記の「基本的なデザイン」に反する部分もありますが、以下の理由でサポートすることにしました。

  1. go buildgo install で悪意のあるコードを実行するのは難しい
  2. 環境依存は比較的少なく、トラブルが起こりにくい(build するために OS のライブラリに依存したりすることがあまりない)
  3. aqua のインストールディレクトリ(AQUA_ROOT_DIR) 以外に勝手にファイルを作ったりすることもなく(~/go/pkg 配下は除く)、 aqua でコントロールできる範囲に閉じることが出来る

aqua-registry では現状以下のようなツールをサポートしています。

使い方はバイナリが提供されている従来のツールと特に変わりません。

$ aqua g -i google/wire # google/wire を追加
$ aqua i # install

tag がちゃんと打たれているツールであれば tag を指定すれば良いですし、そうでなければ commit hash を指定できます。

packages:
  - name: google/wire@v0.5.0
  - name: golang.org/x/perf/cmd/benchstat
    version: 84e58bfe0a7e5416369e236afa007d5d9c58a0fa

install 時のログをみるとバイナリがビルドされているのが分かります。
ビルド時に Go が実行されるので、 Go に依存します。ちなみに Go は aqua でもインストールできます。
ツールが要求する Go のバージョンより古いとビルドに失敗するので気をつけてください。

2 種類の package type

ここは若干 advanced な内容になるので、 Registry を書く人、 https://github.com/aquaproj/aqua-registry に PR を投げるような人以外は読み飛ばしても大丈夫です。
aqua にはインストール時に Go のツールをビルドする package type が 2 種類あります。

  • go: GitHub Repository から archive をダウンロードして展開し、 go build コマンドを実行
  • go_install: 環境変数 GOBIN を指定して go install コマンドを実行

なぜ 2 種類あるかというと、これは単に歴史的経緯によるもので、基本的に新たに package を追加する際は go_install のほうを選択すればいいと思っています。
go install コマンドではインストール先を指定できないと思いこんでいたので package type go を導入したものの、
その後環境変数 GOBIN を指定すれば go install でもインストール先を変更できることに気づき、 package type go_install を導入しました。
go_install のほうが内部的な処理が単純(態々 archive をダウンロードして展開しなくて良い)ですし、 benchstat のように GitHub 以外で管理されているツールにも対応できるなど、メリットが多いので package type go を選択する理由は特にないかなと思っています。

さいごに

以上、 aqua が Go 製のツールをインストール時にビルド出来るようになった話を紹介しました。

これは Go のツールに限った話ではないですが、 aqua i という一つのコマンドでインストールできるようになるというのは便利です。
ドキュメントに「 google/wire をインストールしてください」とか書かなくても良いわけです。
あとはバージョンを固定できる、プロジェクトごとに切り替えられるというのも便利でしょう。バージョンを統一することでトラブルを解消できますし、 update したことによる問題の特定も容易になります。

aqua-registry v2.20.1 の時点では対象のパッケージの数はそこまで多くありませんが、今後更に増えていくことでしょう。

Discussion