KotlinでDiscord Botを始めてみる4 ~Herokuへのホスト編~

# はじめに
この記事は「KotlinでDiscord Botを始めてみる」第四弾です。
第一弾 : [環境構築と起動編](https://qiita.com/hisuie08/items/264456e505ab75f75bbe)
第二弾 : [シンプルなコマンド実装編](https://qiita.com/hisuie08/items/2cc32edbfa772af57a45)
第三弾 : [Embed実装編](https://qiita.com/hisuie08/items/43e9b48ed02c8f4d40bd)
も併せてどうぞ

今回はBotの実装から少し離れて、運用面の解説をはさもうと思います。

# 用意するもの
1. GitHubアカウント
1. Herokuアカウント(クレジットカード登録していると尚良)
1. Discord Bot用トークン

HerokuはGithubと相性が良く、GithubのリポジトリにあるソースコードをHerokuにデプロイ(動かすプログラムとして配置)することができます。
他のデプロイ方法もありますが、今回はGithubを使った方法を紹介します。

# リポジトリの準備

私のGithubに[テンプレートリポジトリ](https://github.com/hisuie08/kotlin-jda-startup)を用意しました。
リポジトリページに有る `Use this template` をクリックして、自分のアカウント下にこのテンプレートベースのリポジトリを作ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398976/f0e92d94-c7ac-a45d-fcf6-7575348b219a.png)

**Herokuへのデプロイはプライベートリポジトリでも可能**ですので、公開の有無は好みで設定できます。

1. 作成したリポジトリをクローン
1. クールなBotのソースコードを書き込み
1. コミット
1. プッシュ

### リポジトリの編集において気をつけてほしいこと

テンプレートはHerokuにデプロイする上で必要な要件を満たして作られています。
リポジトリを編集するとき、上書きによって要件を破壊しないように気をつける必要があります。具体的には

#### .gitignore
`.gitignore` に**テンプレートに既存するファイル追加しないでください！** 
これらのファイルはkotlinソースをHerokuがビルド・起動するのに必要です。`.gitignore`に追加してしまうとまず失敗します。

#### build.gradle.kts
このファイルは極めて重要で、多くの役割を持ちます。Botに追加ライブラリを導入させるときに編集することがあるかもしれません。
しかし、以下に提示したブロックは**Herokuに実行させるビルド手順**が書かれています。
HerokuとGradle両方に詳しくない場合は**これらのブロックには手を触れないでください**。

```kotlin
tasks.register("stage"){
    dependsOn("clean","shadowJar")
}

tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>{
    archiveFileName.set("bot.jar")
}

application{
    mainClass.set("MainKt")
}
```

#### Procfile
Herokuに**デプロイされたとき自動で実行されるコマンド**を指定するものです。
テンプレート通りならデプロイされると`build.gradle.kts`の前述ブロックの指示通りビルドされた完成ファイルは`build/libs/bot.jar`に出力され、ここに記載されているコマンドがそのファイルを起動する、というカラクリです。
こちらもイジる必要はありません。

#### main.kt
`main.kt`のファイル名は変更しないでください。
Kotlinはプログラム実行時一番最初に呼ばれる部分(エントリポイント)を指定する必要があり、テンプレートの`build.gradle.kts`で`main.kt`(正確には`main.kt`内の`main()`関数)を指定しています。
例えば`bot.kt`に変更すると

```kotlin
application{
    mainClass.set("BotKt")
}
```

のようにエントリポイントを指定し直す必要があります。手間をかけて変えるメリットもないので触らないことを推奨します。

また、一番下の`main`関数内にある

```kotlin
val token = System.getenv("Discord_Bot_Token")
```
は**Herokuの環境変数(後述)からトークンを取得する処理**です。
トークンを直接ソースに書き込むのはデメリットが圧倒的に多いため、環境変数に格納されたものを読み込みましょう。
`"Discord_Bot_Token"`文字列はトークンを読み込むためのキーです。変更しても構いませんが、キーは後で使うので忘れないようにしましょう。

# Herokuアプリケーション作成
作成したリポジトリをデプロイするための枠と考えてください。
Herokuダッシュボードにアクセスすると、空っぽのページの真ん中に `Create new app` というボタンがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398976/1281721e-e1a9-7df8-225b-8b1f5622a460.png)
クリックして作成手続きを開始します。

- **App name** : 自由に設定できますが、すでに使用されているアプリ名は使用できませんので、望み通りの名前が得られないことも多々あります。
- **Region**: いじらなくて大丈夫です。

`Create app` クリック。

# Githubとの連携
Herokuのアカウントを作ったばかりの場合、Githubとの連携が必要になります。
アプリページの`Deploy` タブにある `Deployment method` で `GitHub` を選択。
下に現れる `Connect to GitHub` をクリックしてください。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398976/a55539e3-01ba-d020-3070-71ba6f29740b.png)
GitHub認証画面が出たらログイン情報を入力、認証してください。

認証に成功すると、Githubのアカウント配下にあるリポジトリを検索できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398976/c79da7be-e67a-733f-54ea-060e91eae418.png)
準備したリポジトリがGithub上にあることを確認した上で、リポジトリ名を検索し、目的のリポジトリで `Connect` クリック。

# Discordトークンを安全に設定
Botの起動にはトークンが必要不可欠です。
Githubのソースにトークンを直接書き込むことも可能ではありますが、

- **プライベートリポジトリでない場合非常に危険**
- プライベートに設定していてもうっかりパブリックにしてしまう可能性が0とは言い切れない
- 万一の場合などトークンを書き換えたい場合ソースを変更→プッシュという手間がある

と、百害あって一利なし。強く非推奨です。
**Herokuにはトークンを安全に格納する場所があります。**

アプリページの `Setting`タブから `Config Vars` > `Reveal Config Vars` をクリック。

- **KEY** : リポジトリをテンプレートから作成した場合は`Discord_Bot_Token`<br>変更した場合はソースで指定した環境変数キー
- VALUE** : DiscordBotのトークン

`Add` をクリック。


# デプロイ
接続に成功すると、以下のような画面になります。
まずは矢印で示した2箇所のブランチを確認しましょう。
大体の場合`main`です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398976/2c9191fa-f295-7b76-e144-55f6fe6f20e0.png)

`Automatic deploys` > `Enable Automatic Deploys`
`Manual Deploys` > `Deploy Branch`
それぞれクリック。

すぐ下にログがつらつら流れていきます。しばらくお待ち下さい。
`Daemon will be stopped at the end of the build ` で止まることがありますが正常な動作です。
気長に待ってください。
具体的には、`Deploy to Heroku`が緑色になり、`Your app was successfully deployed.` と出れば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398976/967ffff5-9bb3-3618-561c-fec1a5e30ab5.png)

# Botの起動
Herokuはデプロイしたプログラムを**Dyno**と呼ばれるコンテナで動かします。
デプロイが成功してもDynoが有効になっていないとBotは起動できません。

デプロイが成功したら、一旦ページを更新して、`Resource`タブに移動しましょう。
`Free Dynos` セクションに、デプロイ前はなかった1行項目があるはずです。
右端の鉛筆マークをクリックして
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398976/7ed08f8d-8391-4a4d-5e06-ddc0c280340c.png)
スライドを右に移動、`Confirm`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398976/188a74e5-a68a-9190-16f0-3811e52e74cd.png)
これでBotが起動します。

# Botの更新

特別手続きは必要ありません。
リポジトリを書き換えてプッシュすると、自動で更新されたリポジトリをビルド、起動してくれます。