[memo]Heroku利用方法

Herokuを使ってアプリケーションをデプロイする方法をまとめます。

[手順]
●はじめてデプロイをする場合
・Herokuにアカウント登録する
・Heroku CLIをインストールする
・masterブランチへcommitする
・Heroku上にアプリケーションを作成する
・MySQLを使用できるように設定する
・master.keyを環境変数として設定する
・Herokuへアプリケーションの情報をpushする
・Heroku上でマイグレーションを実行する

●デプロイ済みのアプリケーションに変更修正を加えた場合
・変更修正をcommitする
・ブランチを作成していた場合は、masterブランチへマージする
・Heroku上にpushする
（テーブルに変更を加えた場合は）Heroku上でマイグレーションを実行する

##Herokuの導入

###Heroku CLIをインストール

```
# ターミナル
% brew tap heroku/brew && brew install heroku

# 完了確認コマンド
% heroku --version

# バージョンが出力されれば成功
heroku/7.40.0 darwin-x64 node-v12.16.2
```
インストールについての公式ドキュメント
https://devcenter.heroku.com/articles/heroku-cli

###Herokuにログイン

```
% heroku login --interactive
  => Enter your Heroku credentials.
# メールアドレスを入力し、エンターキーを押す
  => Email:
# パスワードを入力して、エンターキーを押す
  => Password:
```

###Heroku上にアプリケーションを作成
アプリ作成公式ドキュメント
https://devcenter.heroku.com/articles/getting-started-with-rails6

```
# 作成したいアプリのディレクトリへ移動し以下コマンド実行
% heroku create アプリ名
```
アプリ名はアンダーバー``_``ではなくハイフン``-``を使う
例：meisai-app 等


###Heroku上でMySQLを使えるようにする
```
# ClearDBアドオンを追加
% heroku addons:add cleardb

# 下記のように出力されれば成功
Creating cleardb on ⬢ meisai-app... free
Created cleardb-vertical-00000 as CLEARDB_DATABASE_URL
Use heroku addons:docs cleardb to view documentation


# 設定を変更
# ClearDBデータベースのURLを変数heroku_cleardbに格納
% heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL`

# データベースのURLを再設定
% heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}
→mysql2というGemを使用しているので、DATABASE_URLの冒頭がmysql2://に変更されている
```

##Heroku上で非公開の値を管理する

####credentials.yml.encファイル
Railsにて、外部に漏らしたくない情報を扱う際に用いるファイル。
通常時は、英数字の文字列で構成された暗号文が表示され、ファイル内に何が書かれているのか分からないようになっています。このcredentials.yml.encと対になるmaster.keyが存在する場合、credentials.yml.encの暗号文を復号し、ファイル内の記述を確認できます。

####master.keyファイル
credentials.yml.encの暗号文を復号する、鍵の役割を持ったファイルです。特定のcredentials.yml.encと対になっているため、その他のcredentials.yml.encへは、効果を発揮しません。
master.keyはデフォルトで.gitignoreに記述されており、Gitで管理されない仕組みになっています。

###credentials.yml.encの中身を確認
アプリのディレクトリを開き、config/credentials.yml.encを開くと暗号文が確認できる

###credentials.yml.encをmaster.keyによって復号

```
# ターミナル
% EDITOR="vi" bin/rails credentials:edit

# 確認後は、「escキー」→「:」→「q」と入力し、「enterキー」を押して credentials.yml.encを閉じる
```

##Heroku上にmaster.keyを設置
Herokuへアプリケーションのコードをデプロイします。
しかし、その際にデプロイされるコードというのは、Gitで管理されているコードになります。
つまり、master.keyはこのままだとHeroku上へデプロイできず、credentials.yml.encもHeroku上で扱えないということになります。

そこで、Heroku上に別途master.keyを設置し、Heroku上でもcredentials.yml.encを扱えるようにする必要があります。
``環境変数``という「どのディレクトリ・ファイルからでも参照できる変数」を使いmaster.keyの値を設置します。

``heroku configコマンドの使用``
Heroku上で環境変数の参照・追加・削除等をする場合に用います。環境変数の追加であればheroku config:set 環境変数名="値"と実行します。そうすることによって、Heroku上で環境変数を追加できます。

### Heroku上で環境変数を設定
```
# Heroku上に環境変数を設定
% heroku config:set RAILS_MASTER_KEY=`cat config/master.key`

# Heroku上で環境変数を確認
% heroku config

# RAILS_MASTER_KEYという変数名で値が設定されていれば成功
```

##アプリケーションをプッシュ
```
# Rubyのバージョン2.6.5が動作するStack（動作環境）を指定
% heroku stack:set heroku-18 -a アプリ名

# アプリケーションをHerokuへ追加
% git push heroku master
```

#### エラーが出る場合
git push heroku master 実行時に「remote: ! Could not detect rake tasks」「remote: ! ensure you can run $ bundle exec rake -P against your app」とエラーが表示される場合は、bundlerのバージョンがエラーの原因である可能性が高いので次の手順を試す。

```
# 現在入っているbundlerを削除[何度か確認を求められますが、「y」を入力してエンター]
% gem uninstall bundler

# bundlerのバージョン2.1.4を指定してインストール
%  gem install bundler -v '2.1.4'

# ディレクトリ内の Gemfile.lock を削除

# Gemfile.lockを作り直す
%  bundle install

# 変更をGitHubへ反映
  GitHubDesktopより、commit と push

# Herokuにアプリケーションの情報を追加
% git push heroku master
```

###Herokuデータベースにマイグレーションの情報を反映
```
# Heroku上でマイグレーションを実行
% heroku run rails db:migrate
```

###公開を確認
```
# Herokuにデプロイされたアプリケーションの情報を確認
% heroku apps:info

===meisai-app
Addons:         cleardb:ignite
Auto Cert Mgmt: false
Dynos:          web: 1
Git URL:        https://git.heroku.com/meisai-app.git
Owner:          sample@sample.com
Region:         us
Repo Size:      165 KB
Slug Size:      56 MB
Stack:          heroku-18
Web URL:        https:/meisai-app.herokuapp.com/
```


###エラーが出る場合のログの確認
```
# ログの最後の10行を表示するためのtailオプションを使いログ表示
% heroku logs --tail --app アプリ名

# 出力結果
2020-05-08T09:03:30.572301+00:00 app[web.1]: F, [2020-05-08T09:03:30.572206 #4] FATAL -- : [52bf1bef-ea70-4df0-897a-6d0c3d925b1e]
2020-05-08T09:03:30.572302+00:00 app[web.1]: [52bf1bef-ea70-4df0-897a-6d0c3d925b1e] ActionView::Template::Error (undefined method `checked' for #<Post:0x000055f0ec57ec88>):
2020-05-08T09:03:30.572303+00:00 app[web.1]: [52bf1bef-ea70-4df0-897a-6d0c3d925b1e]      7: <div id="list">
2020-05-08T09:03:30.572303+00:00 app[web.1]: [52bf1bef-ea70-4df0-897a-6d0c3d925b1e]      8: </div>
2020-05-08T09:03:30.572304+00:00 app[web.1]: [52bf1bef-ea70-4df0-897a-6d0c3d925b1e]      9: <% @posts.each do |post| %>
2020-05-08T09:03:30.572305+00:00 app[web.1]: [52bf1bef-ea70-4df0-897a-6d0c3d925b1e]     10:   <div class="post" data-id = <%= post.id %> data-check=<%= post.checked %>>
2020-05-08T09:03:30.572305+00:00 app[web.1]: [52bf1bef-ea70-4df0-897a-6d0c3d925b1e]     11:     <div class="post-date">
2020-05-08T09:03:30.572306+00:00 app[web.1]: [52bf1bef-ea70-4df0-897a-6d0c3d925b1e]     12:       投稿日時：<%= post.created_at %>
2020-05-08T09:03:30.572306+00:00 app[web.1]: [52bf1bef-ea70-4df0-897a-6d0c3d925b1e]     13:     </div>
2020-05-08T09:03:30.572306+00:00 app[web.1]: [52bf1bef-ea70-4df0-897a-6d0c3d925b1e]
2020-05-08T09:03:30.572307+00:00 app[web.1]: [52bf1bef-ea70-4df0-897a-6d0c3d925b1e] app/views/posts/index.html.erb:10
2020-05-08T09:03:30.572307+00:00 app[web.1]: [52bf1bef-ea70-4df0-897a-6d0c3d925b1e] app/views/posts/index.html.erb:9
2020-05-08T09:03:30.574057+00:00 heroku[router]: at=info method=GET path="/" host=ajax-app-123456.herokuapp.com request_id=52bf1bef-ea70-4df0-897a-6d0c3d925b1e fwd="125.12.120.68" dyno=web.1 connect=1ms service=79ms status=500 bytes=1827 protocol=https
2020-05-08T09:03:31.014022+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=ajax-app-123456.herokuapp.com request_id=56eb5531-4288-48d7-9614-b58fed6deb86 fwd="125.12.120.68" dyno=web.1 connect=2ms service=2ms status=304 bytes=48 protocol=https
```

##デプロイ済みのアプリケーションに変更を加えた場合

###ファイルの変更履歴が存在する場合
```
# Githubのmasterブランチへcommitする(Githubデスクトップからでもok)
% git add .
% git commit -m "後から見てわかりやすいコミット名"

# 作成したコミットをHerokuへプッシュ
% git push heroku master
```

###ファイルの変更履歴が存在しない場合
Herokuの仕様上、最新のコミット履歴が存在しない状態でgit push heroku masterコマンドを実行すると「Everything up-to-date（すでに最新の状態に更新されています）」と表示されます。その場合は空のコミットを作成してHerokuにプッシュする方法を使います。

```
# 空のコミットを生成
% git commit --allow-empty -m "空のcommit" 

# 作成したコミットをHerokuへプッシュ
% git push heroku master
```