CLIツールをHomebrewで配布する

Blog Single

前回の記事で、Go言語で作成したCLIツールをGitHub Releaseで配布するという記事を書きました。
プログラムをビルドするよりは楽になったといえ、ツールのインストールにわざわざtar.gzのファイルをダウンロードして解凍するというのはやはり手間だと思います。

そこで、今回は実際にHomebrewからインストールを行えるように公開していきます。

HomebrewとはMacで使われているパッケージマネージャーです。
Linuxのパッケージマネージャーとしてはyumなどが有名かと思いますが、自分がMacを利用していてかなりHomebrewにお世話になっているのでHomebrewでパッケージをインストールできるように実際にformulaを公開していきます。

formulaとは、パッケージマネージャーで管理されるパッケージのことで公式のformulaとして取り込んで貰うのは難しいためHomebrew Tapという公式以外のformulaをインストールできるコマンドを使ってインストールできるように公開を行います。

公式のformulaと公式以外のformulaをインストールする手順は以下のようになります。

公式のformula

brew install <formula>

公式以外のformula
Tap

brew tap <github_name>/<formula>
# Tapを行った後にインストール
brew install <formula>

または、
タップコマンドを使わない場合

brew install <github_name>/<formula>/<formula>

といった形でインストールできます。

配布手順

前回、GitHub Releaseでの公開を行ったQiitaの人気記事を取得し表示するコマンドラインツールをHomebrewで配布します。

配布するためには、アプリケーションのコードとは別のHomebrewの配布用のリポジトリを作成します。

homebrew-<パッケージ名>という名前のリポジトリを作成します。

そのリポジトリにHomebrewで配布する際の設定を記述する<パッケージ名>.rbという名前の、Rubyファイルを作成します。

cli-sample.rb

# 定数 バージョン管理しやすくするため
HOMEBREW_CLI_SAMPLE_VERSION='1.0.2'

class CliSample < Formula
  # ダウンロードファイルのURL
  url "https://github.com/fox-kazuki-matsumoto/cli-sample/releases/download/v#{HOMEBREW_CLI_SAMPLE_VERSION}/cli-sample_#{HOMEBREW_CLI_SAMPLE_VERSION}_darwin_amd64.tar.gz"
  # 配布するアプリのホームページ(空でもいい)
  homepage "https://github.com/fox-kazuki-matsumoto/cli-sample"
  # ダウンロードファイルのSHA256ハッシュ値
  sha256 "c3d8fb12347b1461a800e31e12600cfe4b556fcc74ec0dfcf97d8c41476a3bfa"
  # パッケージのバージョン
  version "v#{HOMEBREW_CLI_SAMPLE_VERSION}"

  # brew installを行う際のスクリプト
  # bin.installで指定したバイナリが/usr/local/binにシンボリックリンクを貼り実行可能な状態にしてくれる
  def install
    bin.install 'cli-sample'
  end

end

sha256で設定されているハッシュ値は、ダウンロードを行うファイルのハッシュ値を取得して、その値を格納します。

ハッシュ値の取得

$ openssl dgst -sha256 cli-sample_1.0.2_darwin_amd64.tar.gz
SHA256(cli-sample_1.0.2_darwin_amd64.tar.gz)= 6812737673ba79d61df3f00399f17f0c98527938a845b5d8b08728d591242b09

この内容をそのままリポートリポジトリに反映させると、Homebrewを使ってインストール可能な状態になります。

Formulaの設定の詳細はこちら

Homebrewでインストール

実際にHomebrewを使ってインストールを行います。

brew install fox-kazuki-matsumoto/cli-sample/cli-sample

問題なく設定されていれば、正常にインストールが完了します。

実行

作成したプログラムが正しく実行されました。

また今回は、Rubyファイルをそのまま作成しましたが、brew createコマンドを使うと、雛形を作成してくれるのでもう少し簡単に作成できます。

# brew create ダウンロードファイルのリンク
$ brew create https://github.com/fox-kazuki-matsumoto/cli-sample/releases/download/v1.0.1/cli-sample_1.0.1_darwin_amd64.tar.gz

Formulaの更新を自動化

手動でRubyファイルを編集してFormulaの公開を行いましたが、これをツールを更新するたびに編集を行うのは面倒です。

手動での更新だと、Rubyファイルのバージョンの部分を更新したはいいものの、ファイルのハッシュ値の更新を忘れたりしてFormulaがうまくダウンロードできなかったりしてしまう可能性があります。

これを少しでも楽に行うために、前回の記事で紹介したGoReleaserを使って行います。

goreleaserの設定は.goreleaser.ymlファイルで行いますが、記法が少し変わるだけで設定する内容は先ほどRubyで記述した設定の内容とほとんど同じです。
ダウンロードファイルのハッシュ値などの設定などはgoreleaserが勝手にやってくれるため、設定が不要です。

.goreleaser.yml

builds:
- main: main.go
  binary: cli-sample
  goos:
  - windows
  - darwin
  - linux
  goarch:
  - amd64

# Homebrewの設定
brew:
  # Formulaのリポジトリ情報
  github:
    owner: fox-kazuki-matsumoto
    name: homebrew-cli-sample

  # 配布するアプリのホームページ(空でもいい)
  homepage: "https://github.com/fox-kazuki-matsumoto/cli-sample"

  # 自動でコミットするAuthorの情報
  # goreleaserで自動でコミットされていることがわかるようにデフォルトの値を利用
  commit_author:
    name: goreleaserbot
    email: goreleaser@carlosbecker.com

  # brew installを行う際のスクリプト
  # bin.installで指定したバイナリが/usr/local/binにシンボリックリンクを貼り実行可能な状態にしてくれる
  install: |
    bin.install "cli-sample"

設定項目の詳細のこちら

これで、前回の記事のように、コミットをしてタグを貼りプッシュして、goreleaserを実行することで、本体のリポジトリとHomebrew用のリポジトリ両方が更新されます。

ただ、機能も何も追加しないでバージョンを上げるのがちょっと変な感じがするため、出力をテーブル形式にしてより見やすいように変更します。

テーブル形式の出力を行うために、olekukonko/tablewriterのパッケージを用いて更新しました。
Goのコードの差分を見たい方は、以下のリンクから見れます。

fox-kazuki-matsumoto/cli-sample 出力形式をテーブルに変更

ここからは、前回の記事と同じように変更をコミットして、v1.0.3のタグを貼りプッシュを行います。

これで、Formulaのバージョンを上げて更新する準備が整いました。

goreleaserの実行

$ goreleaser --rm-dist

確認

このように本体のリポジトリとHomebrew用のリポジトリが更新されました。

それでは、インストールされたパッケージを更新します。

$ brew upgrade cli-sample

実行

このように少しは前より見やすくなったのではないでしょうか。

まとめ

Homebrewで実際に配布することによってパッケージがどのように配布されているかが知ることができました。

今回配布したツールは、サブコマンドもオプションも用意していないですが、取得する日数を指定できるようにしたいです。

今回配布に利用したgoreleaserや普段利用しているツールのコードがどうなっているのかが気になったのでコードを読んでみようと思います。

参考

Posted by MatsumotoKazuki
PHPやJavaで開発を行っているエンジニア。 LOLというゲームの試合を観戦するのが好きです。

Other Posts: