Ruby で octokit と Slack の bot でインターン生が楽をする

# GitHub のコミットを Slack で bot に投稿させる
ご閲覧ありがとうございます。いつも皆様のブログや記事に大変お世話になっております。

この記事では Ruby で GitHub のコミットを Slackbot に投稿させるまでのフローを書いています。

## はじめに
私は3ヶ月ほど前からエンジニアのインターン生として週2~3ほど働かせてもらってます。その中で色々と継続的なタスクを頂いているわけですが、忘れやすくそして面倒なタスクがあります。それは GitHub のマージされた前日分のコミットを Slack の開発チームのチャンネルで共有するというタスクです。
共有する際のテンプレートとして以下のようにして投稿していました。
<img width="413" alt="スクリーンショット 2018-11-16 17.34.25.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/278797/e75b0e40-03a3-4a90-d5b1-6d786a5b4dda.jpeg">
必要なのはその日毎の番号とコミット名と名前です。
私がこのタスクを引き継ぐ前から、朝の共有会に間に合うよう GitHub からコミットをコピーしてきてテンプレのように整形して投稿するという作業を毎日おこなっていました。

## 製作に思い立った経緯
エンジニアのインターン生としていただいたこのタスクがとにかくめんどくさい！そもそも忘れがちなタスクだし、このタスクは深夜から朝にかけて必要なタスクであるため、眠い中 GitHub を開いてコミットを見に行き、前日分をとってきて Slack に貼り番号をつけて...なんてことしたくない！と強く思ったことが一番の経緯です。

業務で使用している Ruby がまだまだ実力不足、というのもあり、今回は Ruby で実装することを目標にしました。

せっかくのエンジニアとしてインターンをやらせてもらっているので、このような業務をプログラムにやらせるというのは自分にとってもいい課題だと思いました。

## 開発環境

- OS: Mac OS
- 言語: Ruby

## 作成したプログラム
今回はプログラムを役割別に作成しました。作成したプログラムは以下の２つです。

- GitHub からコミットを取ってくるプログラム
- 上のプログラムから所得したメッセージを Slackbot に送らせるプログラム

実行としては下のプログラムを実行することで今まで手動で行っていた業務を全ておこなってくれることを想定しています。

### GitHub からコミットを取ってくるプログラム
こちらが今回のメインとなるプログラムです。

```get_commit_receiver.rb
require 'octokit'
require 'byebug'
require 'tapp'
require 'date'
require 'dotenv'

Dotenv.load

# comment return
class Commit
  attr_accessor :message

  MONDEY_INDEX = 1

  def initialize
    @message = ''
  end

  def get_commit
    num_of_days = today_is_monday? ? 3 : 1
    commit_lists = fetch_commits.select do |commit|
      neccesary_commit?(date_of(commit), num_of_days)
    end

    message = commit_lists.each.with_index(1) do |commit, index|
      formated_message = commit[:commit][:message].gsub(/\*(.*?)\n/, '')
                                                  .gsub(/(\r\n?|\n)/, '')
      author = commit[:commit][:author][:login]
      @message += "#{index}. #{formated_message}(#{author})\n"
    end
  end

  private

  def fetch_commits
    client = Octokit::Client.new login: ENV['LOGIN'], password: ENV['PASSWORD']
    client.commits ENV['REPOSITORY']
  end

  def today_is_monday?
    Date.today.wday == MONDEY_INDEX
  end

  def neccesary_commit?(commit_date, num_of_days)
    Date.today - commit_date <= num_of_days
  end

  def date_of(commit)
    commit[:commit][:author][:date].to_date
  end
end
```

コミットをとってくるメソッドは　`get_commit`です。平日のみの運用で、月曜日には金土日の３日分のコミットが欲しいため`num_of_days`で曜日を確認しています。`fetch_commits`メソッドでは「[octokit](https://github.com/octokit/octokit.rb "octokit")」を利用しております。こちらを利用して特定のレポジトリの特定のコミットを所得しています。

```.rb
def fetch_commits
    client = Octokit::Client.new login: ENV['LOGIN'], password: ENV['PASSWORD']
    client.commits ENV['REPOSITORY']
  end
```

`neccesary_commit?`では`fetch_commits`でとってきたコミットの一覧に対して`num_of_days`で指定された分の日数以下のコミットを選別しています。
その後、`commit_list`として受け取ったメッセージを整形して　*所得したメッセージをSlackbotに送らせるプログラム*　に送るためのインスタンス変数`@message`に格納しています。

### 所得したメッセージをSlackbotに送らせるプログラム
上記のプログラムで所得したメッセージを slackbot に投稿させるプログラムはこちらです。

```slackbot.rb
require './get_commit_receiver'
require 'http'
require 'json'

Dotenv.load

cr = Commit.new
cr.get_commit

response = HTTP.post('https://slack.com/api/chat.postMessage', params: {
                       token: ENV['SLACK_API_TOKEN'],
                       channel: '#SLACKCHANNEL',
                       text: cr.message.insert(0, "```\n").insert(-1, '```'),
                       as_user: true
                     })
puts JSON.pretty_generate(JSON.parse(response.body))

```

`#SLACKCHANNEL`には bot に投稿させる送信先のチャンネルを指定してください。
こちらのプログラムでは先程のプログラムをインスタンス化して実行し、所得してきたメッセージを bot に送らせています。
こちらの記事を主に参考にしました。(http://studio-andy.hatenablog.com/entry/ruby-bot)
slack側での bot の設定はこちらの記事などを参考にしてください。

## プログラムを実行
このプログラムが無事に実行されると下記の写真のように投稿されます。
<img width="690" alt="スクリーンショット 2018-11-16 19.15.58.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/278797/5afa08e6-c070-d67d-56f6-14d5b2b9e400.jpeg">


## 今後の課題
このアプリのおかげでプログラムの実行でめんどくさいタスクを簡単にすることができました。しかしここまで来たらもちろん**定時実行**をやらせてみたいですね。今回の記事ではプログラムの作成で終わりにしますが後に定時実行にして是非また記事を投稿したいと思います。  
最後に私がインターン生として働かせていただいている[会社のブログ](https://blog.localworks.co.jp/)を宣伝させていただきます。現在エンジニアのインターン生として在籍しているのは私一人ですが他の部署のインターン生も同じオフィスで共に働いています。よろしければ是非[ブログ](https://blog.localworks.co.jp/)を見ていってください。