Rust で実装したモック用 REST API サーバーを実行できる CLI を crates.io と Homebrew で公開する
CLI ツールを公開・配布する
Rust で実装した CLI ツールを公開・配布したいなと思い、crates.io と Homebrew で公開・配布する方法を試してみました!!!!
ripgrep から学ぶ
Rust 実装の有名なツールとして、ripgrep (rg) という 正規表現でディレクトリを再帰的に grep できる ツールがあります。
次のコマンドを実行すると、特定の glob にマッチするファイルの中から、マッチする単語 foo
を検索することができます。
rg foo -g 'README.*'
この ripgrep は CLI ツールの実装の参考としてはもちろん、
様々な方法でインストールすることができるので、ツールの公開・配布する方法も学ぶことができます!
crates.io と cargo install
Rust プログラマーなら馴染みがあるであろう crates.io ですが、ライブラリとなるクレートだけでなく、作成したツールであるバイナリクレートを共有することもできます。
バイナリクレートは cargo install
でインストールすることができます。
例えば、SQLx なども以下のコマンドで sqlx-cli をインストールして開発時に使用します。
cargo install sqlx-cli
バイナリクレートとは、クレートが src/main.rs ファイルやバイナリとして指定された他のファイルを持つ場合に生成される実行可能なプログラムのことを指します。[1]
大雑把にいうと cargo new --bin
で作成した Rust アプリケーションです。
crates.io に公開する
CLI ツールを crates.io で公開する手順については、同僚の Shota.i さんが紹介してくれているので、ここでは割愛します!
以下の記事を参考にしてください😉🌟
なお、公開する際は以下のメタデータを Cargo.toml に記載する必要があります。
最初に作成される Cargo.toml にないものもあるので、追記を忘れないようにしましょう!
(最初、必要な情報がないよと怒られてエラーで公開できませんでした...笑)
参考のために、公開したツールの Cargo.toml もおいておきます!
[package]
name = "mocks"
version = "0.2.1"
edition = "2021"
authors = ["codemountains <codemountains@gmail.com>"]
description = "Get a mock REST APIs with zero coding within seconds."
homepage = "https://github.com/mocks-rs/mocks"
repository = "https://github.com/mocks-rs/mocks"
documentation = "https://github.com/mocks-rs/mocks"
readme = "README.md"
license = "MIT"
cargo install
無事に crates.io に公開することができました!
以下のコマンドでインストールできます。
cargo install mocks
アンインストール
もちろん、アンインストールもできます。
cargo uninstall mocks
Homebrew で公開する
Homebrew は、macOS 向けのオープンソースのパッケージ管理システムで、ターミナルを使って簡単にさまざまなソフトウェアをインストール・アップデート・削除できます。
macOS において、開発ツールやアプリケーションをインストールする手段として一般的に利用されているため、Mac で開発しているエンジニアなら一度は触ったことがある方も多いのではないでしょうか!
公開手順で Ruby のファイルを作成するので気になって調べてみると、
[brew](https://github.com/Homebrew/brew)
コマンドは Ruby 製なんですね...!
なんちゃって Ruby デビューです🙌笑
brew install
できるようにする
Homebrew でインストールする場合のコマンドは brew install
です。
このコマンドで作成した CLI をインストールできるようにします!
Homebrew でインストールを可能にするには、以下の方法があります。
- Github に
homebrew-xxx
repository を作成する - Github に
homebrew-tap
repository を作成する - Homebrew の公式リポジトリに Formula を追加する
公式リポジトリに Formula を追加する方法以外では、brew tap
コマンドを使い、
サードパーティのツールをインストールできる仕組みを利用していきます!
では、順番に手順を確認していきます。
homebrew-xxx
repository を作成する
1. まず、homebrew-{ツール名}
というリポジトリを作成します。
ローカルにクローンして作業を進めます。
cargo build する
ツールをビルドして、tar
コマンドで tar.gz に圧縮していきます。
また、次のステップで Formula を作成する際に、SHA ハッシュ値を使用するため shasum
を実行して、値を控えておきます。
cargo build --release
cd target/release
tar -czf mocks-0.1.1-x86_64-apple-darwin.tar.gz mocks
shasum -a 256 mocks-0.1.1-x86_64-apple-darwin.tar.gz
作成した tar.gz を Github のリリースに添付します!
この添付したファイルを Homebrew がダウンロード・解凍してツールを格納してくれるわけです。
なお、ファイル名は ripgrep (rg) を参考に命名しました。
Homebrew Formula の作成
以下の構成で Formula/mocks.rb を作成します。
.rb
ということで、Ruby で記述する必要があります!
Ruby 未経験者なので、テンプレートをコピーして改変していきます笑
homebrew-mocks
└── Formula
└── mocks.rb
class Mocks < Formula
desc "Get a mock REST APIs with zero coding within seconds."
homepage "https://github.com/mocks-rs/mocks"
url "https://github.com/mocks-rs/mocks/releases/download/0.1.1/mocks-0.1.1-x86_64-apple-darwin.tar.gz"
sha256 "0acdf8512f8a22f5a2766d63fd9dea92930b09859b36694e9ed6372fa7170dda"
version "0.1.1"
def install
bin.install "mocks"
end
end
ここまで作成したら、プッシュして完了です。
以下のコマンドで公開したツールをインストールすることができます
brew tap mocks-rs/mocks
brew install mocks
アンインストール
もちろん、アンインストールもできます。
brew remove mocks
brew untap mocks-rs/mocks
homebrew-mocks repository
プッシュしたリポジトリです。
homebrew-tap
repository を作成する
2. Github で homebrew-tap
というリポジトリを作成します。
必ず -tap
を付ける必要があり、tap とは Homebrew のパッケージの定義ファイルである Formula を集めたリポジトリです。
この tap で有名なものとして aws/homebrew-tap があります。
この公開手順も、先ほどの homebrew-mocks
の手順と大きな違いはありません。
cargo build する
上述した cargo build する と同じ手順です。
すでにリリースでビルドしたツールを公開している場合、
そのツールのダウンロード URL は同じで OK なのでスキップします。
Homebrew Formulaの作成
以下の構成で Formula/mocks.rb を作成します。
homebrew-tap
└── Formula
└── mocks.rb
class Mocks < Formula
desc "Get a mock REST APIs with zero coding within seconds."
homepage "https://github.com/mocks-rs/mocks"
url "https://github.com/mocks-rs/mocks/releases/download/0.1.1/mocks-0.1.1-x86_64-apple-darwin.tar.gz"
sha256 "0acdf8512f8a22f5a2766d63fd9dea92930b09859b36694e9ed6372fa7170dda"
version "0.1.1"
def install
bin.install "mocks"
end
end
ここまで作成したら、プッシュして完了です。
以下のコマンドで公開したツールをインストールすることができます🥳🎉
tap
-> install
の流れではなく、install
コマンドのみになりました!!!
brew install mocks-rs/tap/mocks
アンインストール
もちろん、アンインストールもできます。
brew remove mocks
brew untap mocks-rs/tap
homebrew-tap repository
プッシュしたリポジトリです。
3. Homebrew の公式リポジトリに Formula を追加する
以下の記事が参考になりそうです。
公式リポジトリ Homebrew/homebrew-core にプルリクを送り、マージされることで追加される仕組みのようです。
公式リポジトリに追加されると、brew install {ツール名}
でインストールすることができます。
機会があれば、こちらにも挑戦してみたいと思います!
[最後に] mocks の紹介
最後に...
作成したツールにも触れていきます...🤫笑
公開手順で出てきた mocks
が気になった方や Rustacean の方は見ていってください🫶
mocks とは
npm でいうところの json-server のような REST API を検証するためのモックサーバーを起動できるツールです。
mocks の使い方
詳細は mocks-rs/mocks をご確認ください✊
REST API サーバーを起動する
まず --help
でオプションなどを確認できます。
% mocks --help
Get a mock REST APIs with zero coding within seconds.
Usage: mocks [OPTIONS] <FILE>
Arguments:
<FILE> Path of json file for data storage
Options:
-H, --host <HOST> Host [default: localhost]
-p, --port <PORT> Port [default: 3000]
--no-overwrite No overwrite save to json file
-h, --help Print help
-V, --version Print version
データを格納した JSON ファイルのパスを指定してコマンドを実行することで、モック用 REST API サーバーの起動することができます。
mocks storage.json
{
"posts": [
{ "id": "01J7BAKH37HPG116ZRRFKHBDGB", "title": "first post", "views": 100 },
{ "id": "01J7BAKH37GE8B688PT4RC7TP4", "title": "second post", "views": 10 }
],
"comments": [
{ "id": 1, "text": "a comment", "post_id": "01J7BAKH37HPG116ZRRFKHBDGB" },
{ "id": 2, "text": "another comment", "post_id": "01J7BAKH37HPG116ZRRFKHBDGB" }
],
"profile": { "id": "01J7BAQE1GMD78FN3J0FJCNS8T", "name": "mocks" },
"friends": []
}
JSON ファイルを読み取り、エンドポイントを作成してくれます。
% mocks storage.json
`mocks` started
Press CTRL-C to stop
Index:
http://localhost:3000
Storage files:
storage.json
Overwrite:
YES
Endpoints:
http://localhost:3000/comments
http://localhost:3000/friends
http://localhost:3000/posts
http://localhost:3000/profile
% curl http://localhost:3000/posts
{"posts":[{"id":"01J7BAKH37HPG116ZRRFKHBDGB","title":"first post","views":100},{"id":"01J7BAKH37GE8B688PT4RC7TP4","title":"second post","views":10},{"id":"01J7WV7H1KE5RJN7W0HMW9YQTH","title":"new post","views":0}]}
% curl -X POST http://localhost/posts -H 'Content-Type: application/json' -d '{"id":"01J7WV7H1KE5RJN7W0HMW9YQTH","title":"new post","views":0}'
{"id":"01J7WV7H1KE5RJN7W0HMW9YQTH","title":"new post","views":0}
最初に添付した GIF 画像を見ていただけると分かりますが、
JSON ファイルの更新されるところを見ながら操作するのが個人的には好きです笑
--no-overwrite モード
JSON ファイルを上書きしないように実行することができます。
上書きしない場合、メモリ上にデータが保存されるので起動中は参照することができますが、
ファイルに書き込みに行くことはしません。
再実行した際に、元々の綺麗なデータの状態から API を起動することができます!!
mocks の実装について
以下のクレートを使って実装しています。
-
axum
- Web フレームワーク、REST API サーバーを起動
-
clap
- CLI ツールのインターフェースを構築
-
serde_json
- JSON オブジェクトの操作
-
tokio
- 非同期ランタイム
型の決まっていない不定形の JSON オブジェクトの取り扱いに難儀しました...。
型が決まっていれば、serde で簡単に扱えると思うのですが...🥶🥶
テストコードを追加して、リファクタリングもやっていきたいところです。
興味のある方が Github をのぞいてみてください🤝✨
まとめ
CLI ツールを crates.io と Homebrew で公開・配布する方法を試してみました!
ただ、crates.io は Rust プログラマー向けですし、Homebrew は Mac ユーザー向けです。
様々環境でのインストールに対応するには、まだまだやることがあるかなと思います。
自分も OSS で誰かの役に立つツールを開発できるようになりたいものです🔥🔥
mocks
もページング対応だったり、ソーティング対応だったり...
もう少しパワーアップできるように細々とメンテしていきたいです!!!!
参考
- Formula Cookbook
- 🍺 RustのcliをHomebrewで公開する | Happy developing
- How to Publish your Rust project on Homebrew - Federico Terzi - A Software Engineering Journey
- Homebrewを利用して社内ツールを配布する - estie inside blog
- Rust 実装のモック用 REST API サーバーを起動できる CLI ツール “mocks” を開発しているというお話 - dotTrail
Discussion