Elixir/PhoenixアプリをGitHub ActionsでGigalixirに継続的デプロイする

Elixir/Phoenixアプリをパブリックに公開するとき、一番手軽な方法はおそらく __Gigalixir__ にデプロイすることです。

https://www.gigalixir.com/

Gigalixirは、Elixirに対するサポートが強い（Hot Upgradeできたりします）HerokuのようなPaaSです。Herokuと同様にCLIでアプリを作って設定を行い、git pushするだけでデプロイできます。DB（PostgreSQL）も使えます。
Gigalixirの基本や導入については @piacerex さんの記事が分かりやすくまとまっているので、そちらをご覧ください。

https://qiita.com/piacerex/items/1a9cbcc740ca3707eaec

# 手動でデプロイしたくない！

Phoenixは[Productive |> Reliable |> Fast なフレームワーク](https://www.amazon.co.jp/Programming-Phoenix-1-4-Productive-Reliable/dp/1680502263)なので、たくさん改善してたくさんデプロイしたいですよね。それなのに、git pushだけでいいとはいえわざわざ手動でデプロイしたくありません。

ということで、みんな大好きGitHub Actionsで自動デプロイできるようにしてみましょう。

# マーケットプレイスを探してみる

ありました。

https://github.com/marketplace/actions/gigalixir-action

このactionを使えば解決！なんですが、個人的に少し気に入らない点があります :thinking: 

```yaml
- uses: mhanberg/gigalixir-action@<current release>
  with:
    GIGALIXIR_USERNAME: ${{ secrets.GIGALIXIR_USERNAME }}
    GIGALIXIR_PASSWORD: ${{ secrets.GIGALIXIR_PASSWORD }}
    GIGALIXIR_APP: my-gigalixir-app # Feel free to also put this in your secrets
    SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
    MIGRATIONS: false  # defaults to true
```

- Gigalixirアカウントのパスワードを使わないといけない
- SSH秘密鍵を使わないといけない

パスワードもSSH秘密鍵も、あまり外に出したくないですよね…

ちなみに、[ソースコード](https://github.com/mhanberg/gigalixir-action/blob/main/index.js)を見るとGigalixir CLIをインストールしているようです。あれ？git pushだけでいいんじゃなかったっけ？

# 公式ドキュメントを見る

素直に公式ドキュメントを見てみましょう :innocent: 

https://gigalixir.readthedocs.io/en/latest/deploy.html#how-to-set-up-continuous-integration-ci-cd

> How to Set Up Continuous Integration (CI/CD)?

やりたいことど真ん中なセクションがありました。GitHub Actionsを使う方法も書いてありますが、Travis CIの例を見るとGigalixir CLIは使っていません :eyes: 

```yaml:.travis.yml（抜粋）
script:
  - git remote add gigalixir https://$GIGALIXIR_EMAIL:$GIGALIXIR_API_KEY@git.gigalixir.com/$GIGALIXIR_APP_NAME.git
  - mix test && git push -f gigalixir HEAD:refs/heads/master
```

どうやらGigalixirのAPIキーが必要なようです。発行しましょう。

# GigalixirのAPIキーを発行する

管理コンソールの「Account > API Key」でAPIキーを確認できます。明示的に発行しなくても、アカウントを作った時点ですでに発行されているはずです。

![スクリーンショット 2021-04-02 17.22.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28249/7edcec31-2155-13f1-eea8-cb8ea7e5f8c9.png)

（APIキーはすでに更新しているので、ご心配なく）

# GitHub Actionsの設定ファイルを書く

`main` ブランチにプッシュされたら自動デプロイされるようにします。


```yaml:.github/workflows/deploy_to_gigalixir.yml
name: Deploy to Gigalixir
on:
  push:
    branches:
      - main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: git push gigalixir
        run: |
          git remote add gigalixir https://${{ secrets.GIGALIXIR_EMAIL }}:${{ secrets.GIGALIXIR_API_KEY }}@git.gigalixir.com/${{ secrets.GIGALIXIR_APP_NAME }}.git
          git push -f gigalixir HEAD:refs/heads/master
```

1つ注意が必要なのが、`actions/checkout@v2` をデフォルト設定で使うとshallow cloneとなり、このままgit pushするとエラーが出てしまうため、`fetch-depth: 0` を指定する必要があります。2021/01/23時点で起こっていたエラーなので、今は解決しているかもしれません。

`.github/workflows/deploy_to_gigalixir.yml` を追加して `main` ブランチにプッシュすると、GitHub Actionsによって自動デプロイされます :tada: 

# 最後に

`mhanberg/gigalixir-action` ではデプロイ時にDBマイグレーションも行えるようですが、git pushだけではDBマイグレーションを行うことができません。が、Gigalixirは [Distillery](https://github.com/bitwalker/distillery) というリリースパッケージを作成できるツールに対応していて、Distilleryを使うとPhoenixアプリの起動時にDBマイグレーションを行うように設定できるので、対応したい方はそれぞれの公式ドキュメントを見ながら設定してみてください。

https://gigalixir.readthedocs.io/en/latest/modify-app/distillery.html

https://github.com/bitwalker/distillery/blob/master/docs/guides/running_migrations.md

また、私がPhoenix LiveViewの勉強用に作ったTodoアプリで自動デプロイされるように設定しているので、興味があればこちらもご覧ください :muscle: 

https://github.com/mokichi/todo-phoenix-liveview

## 2021/04/06追記

Elixir1.9以降であれば、標準で __mix release__ を使うことができます。DistilleryのようにHot Upgradesはできませんが、より手軽にリリースパッケージを作成できるので、Hot Upgradesが必要ない場合はmix releaseも試してみてください。

https://hexdocs.pm/mix/Mix.Tasks.Release.html

https://gigalixir.readthedocs.io/en/latest/modify-app/index.html#mix-vs-distillery-vs-elixir-releases

https://gigalixir.readthedocs.io/en/latest/database.html#how-to-run-migrations-on-startup