ハッカソンの開催情報を自動でお知らせするBotをGithub Actionsに移行して運用費が0円になりました

新着のハッカソン・ゲームジャム・アイディアソン・開発合宿の情報を自動的にお知らせしているBotがあります。
よかったらフォローしてください!!

 * [Twitter (@HackathonPortal)](http://bit.ly/2O1gmYi)
 * [Qiita (@HackathonPortal)](http://bit.ly/2CyqzWH)
 * [Googleカレンダー](http://bit.ly/34VA7HI)
 * [Blogger (ブログ)](http://bit.ly/2CuDGIw)

このBotの頭の中身についてはこちらの記事にて紹介しました。

[最新のハッカソンの開催情報を自動で集めて、お知らせするBotを作ったので頭の中を紹介](https://qiita.com/taptappun/items/f913dc8daaec931508a1)

また、具体的なソースコードも公開していますのでこちらを参照してください。

[hackathon_portal](https://github.com/TakuKobayashi/hackathon_portal)

今回はこのHackathonPortalをこれまで、[AWS Lightsail](https://aws.amazon.com/jp/lightsail/) (Ubuntu)サーバーにて稼働していたものを [Github Actions](https://github.com/features/actions) に完全に移行したので、その内容について紹介します。

## Github Actionsの本来の使い方について

本来の [Github Actions](https://github.com/features/actions) の正しい使い方はCI/CDがメインで主に以下のような開発支援として用いられます。

* 自動的にデプロイ
* 自動テストの実行
* issueやプルリクのお掃除

など

今回は [Github Actions](https://github.com/features/actions) の [schedule機能](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#scheduled-events-schedule) にのみ着目して活用しました。
また [Github Actions](https://github.com/features/actions) の本来の使い方については [こちら](https://qiita.com/taptappun/items/4a8f7ecaa3f91cb21be9) などにまとめています。

[Github Actionsにて自動的にデプロイする環境作成(Webサイト編)](https://qiita.com/taptappun/items/4a8f7ecaa3f91cb21be9)

## そもそもなぜ、Github Actionsに移行したのか?

* [Github Actions](https://github.com/features/actions) で稼働させる間は月額費用が0円になるため
  * [Github Actions](https://github.com/features/actions) の費用はPublicリポジトリならいくら使っても0円です。(privateは無料枠を超えたら費用がかかります。詳しくは[こちら](https://github.com/features/actions))
  * 元々,HackathonPortalはPublicリポジトリで稼働しています。
* 下記の仕様の関係上、 [schedule機能](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#scheduled-events-schedule) さえあれば、要件を満たせるので [Github Actions](https://github.com/features/actions) の使用に適していたため

## 仕様

HackathonPortalの仕様を簡単にまとめると以下になります

* 1日に1回イベント公開されたイベントの情報を集める → `cron` を活用
* 集めた情報をデータベースに保存する
* 保存したデータベースの情報を整理して、Twitterなどに発信する

基本的に定期的に `Batch` が実行されればいいので [Github Actions](https://github.com/features/actions) の [schedule機能](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#scheduled-events-schedule) を使えば実現できます。

## 実現させるにあたって苦労したこと

### データベース

[Github Actions](https://github.com/features/actions) ではMySQLなどのミドルウェアを使用することはできますが、 [Github Actions](https://github.com/features/actions) では毎回実行されるたびにデータが空っぽになります。
そのため [Github Actions](https://github.com/features/actions) のみで完結させようとした場合、これまでためたデータをどこかに保持するためておく仕組みが必要です。
外部のデータベースを活用するなど考えましたがいずれの場合も

 * 結局、月額費用がかかる
 * 無料のデータベースは容量が少ない
 * 何かと制約が多い

ということで結局<font color="#FF0000">これまでためたデータを全てGitの管理下に置いてGithubに保管してもらう</font>ことで対応しました。

具体的には以下のフローを [Github Actions](https://github.com/features/actions) の中で行なっています

 1. MySQL稼働
 2. MySQLの中にデータを挿入する
 3. データを集める → 発信する
 4. `mysqldump` してデータを全て `SQLファイル` で出力する
 5. `git push` で Githubにアップロード

こうすることで [Github Actions](https://github.com/features/actions) (Github) のみで完結する仕組みを構築しました。

実際に設定している内容については [こちら](https://github.com/TakuKobayashi/hackathon_portal/blob/master/.github/workflows/crawl-and-publish.yml) を参照

### データ容量におけるGithub上の仕様

Github上では `100MB` を超えるデータをpushすることができません。
(詳しくは [こちら](https://help.github.com/ja/github/managing-large-files/conditions-for-large-files))

1ファイル `100MB` を超えるデータを保存する場合は Githubでは [Git LFS](https://git-lfs.github.com/) を使用する必要があります。
しかし、 [Git LFS](https://git-lfs.github.com/) を使用してのデータ管理は `月間1GB` を超えると月額費用が発生してしまします。

今回、月額費用0円での運用を実現したかったので、`mysqldump` で抽出するSQLを `1ファイル100MB未満` になるように分割してpushするようにしました。そのために以下のようなコマンドを `Batch` の中で実行しています。

```sh
mysqldump データベース名 テーブル名 -u ユーザー名 -pパスワード --no-create-info -c --order-by-primary --skip-extended-insert --skip-add-locks --skip-comments --compact > SQLファイル.sql
```

上記のように `mysqldump` をするときに

 * `--no-create-info` でデータのみを取得し
 * `--skip-extended-insert` で一行ずつINSERT文を抽出
 * `--skip-add-locks --skip-comments --compact` でコメントなどの不要なものを全て排除

したSQLファイルを出力します。そして以下のように出力したSQLファイルを `split` コマンドを使い分割しています。

```sh
split -l 10000 -d --additional-suffix=.sql fulldump.sql テーブル名/
```

上記の場合10000行ごとに分割しています。これにより1ファイル 大体 `100MB` 以下になるように分割しています。

※ `split` コマンドの `--additional-suffix` オプションはLinuxでは使用可能ですが、`Mac OS` では使用することができません。`Mac OS` で`--additional-suffix` オプションを使用する場合は `gsplit` を `brew install gsplit` にてインストールして `gsplit` コマンドにすることで使用することができます。

### 実行されるブランチをmaster以外に切り替える

基本的に  [Github Actions](https://github.com/features/actions) の [schedule機能](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#scheduled-events-schedule) は `default` ブランチ(最初は `master` ブランチ)の内容が実行されます。
今回データを蓄積するブランチは `master` ブランチ以外で行いたかったです。そのため、[Github Actions](https://github.com/features/actions) が実行された瞬間にブランチを切り替えるには [Github Actions](https://github.com/features/actions)が実行される `yml` にて使用されている、[actions/checkout](https://github.com/actions/checkout) (`uses: actions/checkout@v1` の部分) で、`with:`とともにブランチを一緒に指定することで実行できました。(`ref: ブランチ名`)

以下にその部分を記述します。


```yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
      with:
        ref: crawled-data
```

### Github Actions内からGithubへpushする

[Github Actions](https://github.com/features/actions) の中からGithubへのpushをそのまま行おうとするとエラーとなってしまいます。
今回、pushを可能にするために `Personal access tokens` を発行し、`User Name`(Githubのアカウント名) とともに以下のように設定します。

```sh
git remote set-url origin "https://${User_Name}:${Personal_Access_Tokens}@github.com/TakuKobayashi/hackathon_portal.git"
```

この状態で

```sh
git push origin ブランチ名
```

を行うことで、[Github Actions](https://github.com/features/actions) の中からGithubへのpushを実現しています。

※ `Personal access tokens` の発行の仕方は[こちら](https://help.github.com/ja/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line)を参照してください。

[コマンドライン用の個人アクセストークンを作成する](https://help.github.com/ja/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line)

## 課題

### Github Actionsで稼働しているマシンスペックの問題

Github Actionsで稼働しているマシンのストレージ容量は `14GB` です。

【参考】

* [Virtual environments for GitHub-hosted runners](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners)

`mysqldump` したSQLファイルの容量が `14GB` を超えるようなデータ量となるとき、別の方法を考える必要があります。
(現状 `1GB` も超えていないのでまだ大丈夫)

## 最後に

ハッカソン・ゲームジャム・アイディアソン・開発合宿への参加に興味がある皆さんは是非フォローしてください!!
よろしくお願いします。

 * [Twitter (@HackathonPortal)](http://bit.ly/2O1gmYi)
 * [Qiita (@HackathonPortal)](http://bit.ly/2CyqzWH)
 * [Googleカレンダー](http://bit.ly/34VA7HI)
 * [Blogger (ブログ)](http://bit.ly/2CuDGIw)