Hex で Elixir のライブラリをリリースする方法

新しい言語を覚えたらライブラリを作りたいですよね。ということで Hex を使って Elixir ライブラリをリリースし、https://hex.pm/ に登録する方法を紹介します。

## Hex とは

Hex は Elixir, Erlang 向けのパッケージ管理ツールです。ruby で言うところの rubygems、node.js で言うところの npm です。
登録されているライブラリは https://hex.pm/ から探すことができます。

## Hex のインストール

前提として Elixir のインストールまでは済んでいるものとします。

以下コマンドで Hex をインストールします。

```bash
$ mix local.hex
```

## ユーザ登録

`mix hex.user register` でユーザ登録します。アカウント、メールアドレス、パスワードが必要です。

```bash
$ mix hex.user register
Username: you
Email: your.email@example.com
Password:
Password (confirm):
Registering...
Generating API key...
You are required to confirm your email to access your account,  a confirmation email has been sent to <your.email@example.com>
```

tips: Generating API key とありますが、`~/.hex/hex.config` に格納されます。`~/.hex` は環境変数 HEX_HOME で変更できます。

## ライブラリ作成

リリースするためにサンプルのライブラリが必要になるので `mix new` します。

```bash
$ mix new hex_sample
$ cd hex_sample
```

とりあえずサンプルということで、ライブラリ作成はこれで終わりです。
ここで作成された `mix.exs` に Hex へリリースするために必要なメタ情報を追記します。

## `mix.exs` の書き方

生成された`mix.exs` に Hex へ登録するのにオススメなメタ情報を追加してみます。
必須要素の `:version` はすでに定義されていますが、その他に `:description`, `:maintainers`, `:licenses`, `:links`, `:files` などがあります。
ライブラリの情報を見やすくするためにも、これらの情報を埋めておくのがよいです。

`mix new` 直後は以下のようになっていますが、

```ex:before
defmodule HexSample.Mixfile do
  use Mix.Project

  def project do
    [app: :hex_sample,
     version: "0.0.1",
     elixir: "~> 1.0",
     deps: deps]
  end

  # 略
end
```

以下のようにメタ情報を追加します。

```ex:after
defmodule HexSample.Mixfile do
  use Mix.Project

  def project do
    [app: :hex_sample,  # Hex でのライブラリ名になるので後悔しない名前にしよう
     version: "0.0.1",  # semantic version で
     elixir: "~> 1.0",
     description: "Your Library's Description", # ライブラリの概要
     package: [
       maintainers: ["Your Name"],              # メンテナ(以前は :contributors でしたが deprecated になりました。)
       licenses: ["MIT"],                       # ライセンス名 SPDX License identifier (https://spdx.org/licenses) から選ぶのが推奨されています
       links: %{"GitHub" => "https://github.com/ma2gedev/hex_sample"} # リンク集
     ],
     deps: deps]
  end

  # 略
end
```

ここには記載していませんが、`:package` 下に `:files` も指定できます。指定していないのはデフォルトで Hex が `mix new` で作られる構成のファイルをリストしてくれるためです。ファイル構成を変えている場合や、個別に指定したい場合などに必要となります。

## リリース(publish)

ここまで来たら後は `mix hex.publish` でリリースです。準備ができると Proceed? [Yn] と聞かれるので Y を押してください。hex_sample はリリースしたくないので n を入力してます。。。

```bash
$ mix hex.publish
Publishing hex_sample v0.0.1
  Dependencies:
  Included files:
    lib/hex_sample.ex
    mix.exs
    README.md
Proceed? [Yn] 
```

リリースできるとパッケージの url が作成されます。`mix.exs` の `project` 関数で定義した `:app` に指定した名前が url に含まれるようです。例えば `hex_sample` の場合は`https://hex.pm/packages/hex_sample` になる(はずです)。 

ちなみにリリースが上手くいくと最後に以下のメッセージが表示されドキュメントのアップロードを促されますが、ここで `mix hex.docs` してもエラーが出てしまいます。

```
Don't forget to upload your documentation with `mix hex.docs`
$ mix hex.docs
** (Mix) The task docs could not be found
```

## Document リリース

`mix hex.docs` は内部で `mix docs` task を呼び出しているのですが、その task がないために上記のエラーになっています。

docs task を追加するためには、[ex_doc](https://github.com/elixir-lang/ex_doc) を project に追加する必要があります。`mix.exs` の deps 関数に ex_doc の依存関係を追加します。tips: `ex_doc` のなるべく新しいバージョンを指定するとレイアウトも綺麗なものになります。

```ex:mix.exs
  defp deps do
    [{:ex_doc, "~> 0.10", only: :dev}] # [] となっているところに :ex_doc を追加
  end
```

後は `mix deps.get` すれば、`mix docs` が使えるようになり、結果 `mix hex.docs` も使えるようになるので実行してみてください。

ちなみに ex_doc も `mix.exs` にメタ情報(`:name`, `:source_url`, `:homepage_url`)を追加することができるようですが、詳細は ex_doc の [README](https://github.com/elixir-lang/ex_doc) をご覧ください。

## Pro tip

### バッジをつける

折角ライブラリを公開したら rubygems のようにバッジをつけたいですよね。hex.pm では提供してないのですが、http://shields.io/ というサービスがあり、そちらで hex.pm 用のバッジが提供されています。

以下のように記載することで(power_assert のところを自分のライブラリ名に置き換えてください)、

```
[![hex.pm version](https://img.shields.io/hexpm/v/power_assert.svg)](https://hex.pm/packages/power_assert)
[![hex.pm](https://img.shields.io/hexpm/l/power_assert.svg)](https://github.com/ma2gedev/power_assert/blob/master/LICENSE)
```

[![hex.pm version](https://img.shields.io/hexpm/v/power_assert.svg)](https://hex.pm/packages/power_assert) [![hex.pm](https://img.shields.io/hexpm/l/power_assert.svg)](https://github.com/ma2gedev/power_assert/blob/master/LICENSE)

こんなバッジたちが表示されるようになります。README.md とかに書いておくとカッコいいですね。ライセンスの方は mix.exs に記載してある licenses が hex に適用されると自動で表示されます。他にもダウンロード数用バッジもあるので、http://shields.io/ にいって hex で検索してみてください。

## Resources

- https://hex.pm/docs/publish
    - 公式です。ここ見ておけば十分だと思います。
- https://github.com/ma2gedev/power_assert_ex
    - 実際に hex.pm へ公開しているライブラリサンプルです。mix.exs の書き方とか参考になれば。
- https://github.com/hexpm/hex
    - Hex のリポジトリ
- https://github.com/hexpm/hex_web
    - hex.pm のリポジトリ
- https://github.com/elixir-lang/ex_doc
    - ex_doc のリポジトリ
- https://spdx.org/licenses
    - SPDX のライセンスリスト。licenses に指定する際に SPDX License Identifier が推奨されています
- http://shields.io/
    - shields.io


## 最後に

Elixir もまだまだライブラリが多くはないので(Erlang の資産は相当あるけれど)、作ったものがどんどん公開されていくと盛り上がっていくと思います。というわけで私の公開している [ライブラリ](https://github.com/ma2gedev) にも :star: をお願いします :pray: 

Enjoy!!