GitHub + Slack + RaspberryPiを用いたHUBOT開発環境の構築

# GitHub + Slack + RaspberryPiを用いたHUBOT開発環境の構築

## １．はじめに
どうも、ISAOXです。
最近、仲間内で開発とか雑談とかに使うチャットツールとしてSlackを使い始めました。
このSlack上ではBOTなるものがチャットのお手伝いをしてくれます。
このBOTはGitHub社製のHUBOTというものを使えば自分で作れるそうです。
HUBOTはRaspberryPiのOS(Raspbian)でも動作します。
家には放置されているRaspberryPi(以下RPi)があります。
RPiはGPIO等を備えているのでカメラとかサーボとか色々なデバイスと連携できます。
なので、Slackチャットに面白い投稿をしてくれるBOTアイデアが広がりそうです！
そこで、私なりのHUBOT開発環境の構築を紹介します。

## 2. 前提条件
この記事の前提条件は以下です。

* GitHubに自分のリポジトリを持って利用している。
* Slackを利用している + Slack上でHUBOT用のBOTを追加している。
* インターネットに接続したRaspberryPi(Raspbian)がある。
* RPi上でHUBOTを起動できる環境にしている(node.js,npm,yo,generator-hubot,coffee-scriptをインストール済であること)

## 3. 開発サイクルの設計
面倒くさがり屋の私は毎度毎度RPiをモニタにつないだりPCとつないだりとか考えるだけでやる気が失せます。
なので、そういうのにつなげるのは最初の環境構築とデバイスを追加する時だけにしたいです。
よって、以下のような流れで開発サイクルを回していける環境構築を行います。
##### 1. 私がローカルPC上でHUBOT用のスクリプトを書く。
##### 2. 私がGitHubリポジトリにスクリプトをPUSHして更新する。
##### 3. 私がSlack上でBOTにRPi上のスクリプトを最新状態にするよう命令する。
##### 4. 必要なら、私がSlack上でBOTにRPiを再起動するよう命令する。
##### 5. RPi上のHUBOTが更新された最新のスクリプトで動作する。
##### 6. 1～5を繰り返してBOTの開発を行う。

## 4. 開発サイクル環境の構築
上記の開発サイクルにするには以下を実現する必要があります。

* RPi上でのスクリプト格納先はHUBOTの読み取り先とGitHubリポジトリの格納先で同じにする。
* RPiを起動したらHUBOTが自動起動できるようにする。
* Slack上でBOTに『git pull』を送信したらRPi上でGitHubリポジトリのクローンを更新できるようにする。
* Slack上でBOTに『reboot』を送信したらRPiを再起動できるようにする。

以降の記事は階層パスやファイル名などは各自の環境に読み換えてください
私の場合、SlackとHUBOT上でのBOT名は『iotbot』にしました。

### 4-1. RPi上でのスクリプト格納先はHUBOTの読み取り先とGitHubリポジトリの格納先で同じにする。
私のGitHubリポジトリでは、HUBOT用のスクリプトは以下の階層に格納していくようにしました。
`StudyRPi/Hubot/iotbot/scripts`  

そして、RPi上でGitHubリポジトリをクローンして、以下のように配置させます。
`home/pi/GitHub/StudyRPi/Hubot/iotbot/scripts`

次に、RPi上でscriptsディレクトリがあるiotbotディレクトリ内でHUBOT実行環境を構築します。
そうすれば、scriptsディレクトリ内にあるcoffeeスクリプトをHUBOTが起動した際に読み込むようになります。
HUBOTの初期設定の方法は省略しますが、必ずadapterをslackに設定するようにしてください。
そして、slack上で取得したBOTのAPIトークンを設定しておいてください。

```
cd home/pi/GitHub/StudyRPi/Hubot/iotbot
yo hubot
```
これで、RPi上でGitHubリポジトリのクローンをPULLすれば最新状態に更新できます。
HUBOTを再起動すれば最新状態のcoffeeスクリプトで動作します。

### 4-2. RPiを起動したらHUBOTが自動起動できるようにする。
私のGitHubリポジトリでは、HUBOTを起動するShellスクリプトを以下に格納するようにしました。
`StudyRPi/Hubot/iotbot/kick_iotbot.sh`
kick_iotbot.shの中身は以下です。
HUBOTをslackアダプタとして起動するコードです。

```kick_iotbot.sh
#!/bin/sh
cd /home/pi/GitHub/StudyRPi/Hubot/iotbot
sudo ./bin/hubot -a slack
```

RPi上で`/etc/rc.local`内の`exit 0`の前に以下のコードを記載すれば起動時にこのShellスクリプトを実行できます。
`sudo -u pi /home/pi/GitHub/StudyRPi/Hubot/iotbot/kick_iotbot.sh`
これで、RPiが起動したらkick_iotbot.shが実行されHUBOTが立ち上がるようになります。

### 4-3. Slack上でBOTに『git pull』を送信したらRPi上でGitHubリポジトリのクローンを更新できるようにする。
以下のような階層パスと内容のShellスクリプトを用意します。
`/home/pi/GitHub/StudyRPi/Hubot/iotbot/my_exec/git_cmd.sh`

```git_cmd.sh
#!/bin/sh

cd /home/pi/GitHub/StudyRPi
git $@
```
HUBOTが読み込むcoffeeスクリプトに『git』という文字列が来たら上記Shellスクリプトを呼び出す命令を追記します。
『git』の後に入力した文字列群もShellスクリプトに渡せるようにしてます。
`/home/pi/GitHub/StudyRPi/Hubot/iotbot/scripts/test.coffee`

```test.coffee
  robot.respond /git (.*)/i, (msg) ->
    arg = msg.match[1]
    @exec = require('child_process').exec
    command = "sudo -u pi sh /home/pi/GitHub/StudyRPi/Hubot/iotbot/my_exec/git_cmd.sh #{arg}"
    msg.send "Command: #{command}"
    @exec command, (error, stdout, stderr) ->
      msg.send error if error?
      msg.send stdout if stdout?
      msg.send stderr if stderr?
```

これで、Slack上でBOTに対して以下のようにしてメッセージを送信します。
`@iotbot git pull`
すると、RPi上にあるクローンしたGitHubリポジトリをPULLしてくれ最新状態に更新してくれます。
また、『pull』以外の命令も受け付けれるようにしてますのでgitコマンドは思いのままにできます。
Slackメンバーに危険人物がいる場合は以下のようにしてBOTが自分の命令(ここではisaoxにのみ)にだけ従うようにするのもいいでしょう。

```test.coffee
  robot.respond /git (.*)/i, (msg) ->
    if msg.message.user.name == "isaox"
      arg = msg.match[1]
      @exec = require('child_process').exec
      command = "sudo -u pi sh /home/pi/GitHub/StudyRPi/Hubot/iotbot/my_exec/git_cmd.sh #{arg}"
      msg.send "Command: #{command}"
      @exec command, (error, stdout, stderr) ->
        msg.send error if error?
        msg.send stdout if stdout?
        msg.send stderr if stderr?
    else
      msg.send "get out !!"
```


### 4-4. Slack上でBOTに『reboot』を送信したらRPiを再起動できるようにする。
以下のような階層パスと内容のShellスクリプトを用意します。

`/home/pi/GitHub/StudyRPi/Hubot/iotbot/my_exec/cmd_reboot.sh`

```cmd_reboot.sh
#!/bin/sh
sudo reboot
```

HUBOTが読み込むcoffeeスクリプトに上記Shellスクリプトを呼び出す命令を追記します。
`/home/pi/GitHub/StudyRPi/Hubot/iotbot/scripts/test.coffee`

```test.coffee
  robot.respond /reboot/, (msg) ->
    @exec = require('child_process').exec
    command = "sudo -u pi sh /home/pi/GitHub/StudyRPi/Hubot/iotbot/my_exec/cmd_reboot.sh"
    msg.send "Command: #{command}"
    @exec command, (error, stdout, stderr) ->
      msg.send error if error?
      msg.send stdout if stdout?
      msg.send stderr if stderr?
```

HUBOTを再起動してこのcoffeeスクリプトで動作するようになります。
これで、Slack上でBOTに対して以下のようにしてメッセージを送信します。
`@iotbot reboot`
すると、RPi上でHUBOTはcmd_reboot.shを実行してくれRPiが再起動します。

## 4. 開発サイクルの実施
『開発サイクル環境の構築』ができたら、後は簡単です。
自分の好きなPC上でHUBOT用のスクリプトを書き、GitHubリポジトリにPUSHしたら、
Slack上でBOTに以下のようにしてRPi上のリポジトリのクローンを最新にしてもらいます。
※下のスクリーンショットはSlack上の『DIRECT MESSAGES』上で入力しているので頭に指定するBOT名は省略してます。
![Picture](https://github.com/IsaoNakamura/StudyRPi/blob/master/Hubot/image/sc_git-pull_create.png?raw=true)

もし、coffeeスクリプトを更新したのであれば以下のようにしてRPiごとHUBOTを再起動します。

![Picture](https://github.com/IsaoNakamura/StudyRPi/blob/master/Hubot/image/sc_reboot.png?raw=true)

一旦、Slack上でBOTがオフラインに代わり、しばらくしてオンラインに戻れば再起動成功です。
さすれば、最新のスクリプトでHUBOTが動き出します。
これを繰り返していけば、いちいちRPiをひっぱりださずに、
さらには自宅のRPiを出先のPC・スマホからSlack経由で操作してHUBOTへの命令・育成ができます。

以下のGitHubに今回作成したHUBOT用のスクリプトを格納しました。
[https://github.com/IsaoNakamura/StudyRPi/tree/master/Hubot/iotbot](https://github.com/IsaoNakamura/StudyRPi/tree/master/Hubot/iotbot)

## 5. 最後に
今回はHUBOTで何をするかではなく、HUBOTを育てるための環境構築を考えました。
本当に取り組みたいこととは別のことに時間がかかって、めんどくさくなって投げ出すケースは多々あります。
それを緩和するための手段のひとつです。
SlackはPC・スマホ上で操作できるのでシームレスに使え素晴らしいです。
なので、これを介せば仲間だけでなくBOTとのコミュニケーションも密にとれると考えてます。
各自、開発に集中できる環境を考えてみましょう。