GitのDiffをSlackへ流したいだけなんだ

# GitのDiffをSlackへ流したい
[cloudpack あら便利カレンダー　2017](https://cloudpack.github.io/benri2017/)の23日目です。

GitのDiffをSlackにコピペすると…
<img width="635" alt="スクリーンショット 2017-06-29 12.47.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/115059/c9a8365f-e990-c367-9e1e-0b878533a9e1.png">
うーん、このままじゃ見づらい。
あと、毎回コピペするのは面倒！
ということで投稿できる様にしてみました。

# Webhook
Slackへ投稿するためにはIncoming Webhookを使います。
Incoming Webhookを使うと、ユーザーごとにユニークなURLが配布され、
そのURLにSlackのAPIに沿ったPOSTを行うと、投稿ができます。
ユーザーとして投稿の権限が与えられるので、
生成されたURLはむやみに公開しないように注意してください。

参考記事
http://qiita.com/vmmhypervisor/items/18c99624a84df8b31008

# Slackへの投稿を行うシェルスクリプト
とりあず、Slackへ投稿を行うシェルを書きます。
bashのバージョンは
`GNU bash, version 3.2.57(1)-release`
で行っています。
ちなみにシェルはすべてホームディレクトリ`~/`に配置されている前提です。

```bash:post_slack.sh
#!/bin/bash
readonly WEBHOOK_URL="https://hooks.slack.com/XXXXX/XXXXXXX"

# $1 :text
# $2 :channel

username=`hostname`

# escape
escaped_text=`echo "$1" | sed 's/\"/\\\"/g'| sed 's/\\\/\\\\\\\/g'`

# format
body=$(cat << EOF
{
    "channel": "$2",
    "username": "${username}'s console",
    "text": "$escaped_text",
    "icon_emoji": ":console:"
}
EOF
)
# post
curl -X POST --data-urlencode 'payload='"${body}" ${WEBHOCK_URL}
echo ""
```
やっていることは単純で、

1. 引数をJSON用にエスケープ
1. API用に整形
1. 投稿

をしているだけです。
エスケープ処理ではJSON用に`"`と`\`をエスケープしてます。
(`sed 's/\\\/\\\\\\\/g'`の部分は若干闇を感じます)
投稿者の名前は端末ごとに`hostname`で取得しています。
`icon_emoji`では、投稿する絵文字を指定できるので、コンソールっぽい画像を登録しています。

実行方法は
`sh ~/post_slack.sh　"投稿したい文" "投稿先チャンネル名"`
になります。

```shell-session
usersMac:~ user$ sh ~/post_slack.sh uho-uho chat-test
ok
```

結果はこんな感じ。
<img width="281" alt="スクリーンショット 2017-06-28 18.06.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/115059/30b955e5-aaaf-79ca-afaa-4d5a954a7466.png">

コンソールが`uho-uho`言っていることがわかります。

pipeでつなぐ時はこんな感じにするとコマンド内容が投稿できます。
`"コマンド" |sh ~/post_slack.sh "$(cat -)" "投稿先チャンネル"`

例えばこんな感じで実行すると

```shell-session
usersMac:sample user$ ls -a | sh ~/post_slack.sh "$(cat -)" chat-test
ok
```

こんな感じの内容が投稿されます。
<img width="316" alt="スクリーンショット 2017-06-28 18.10.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/115059/1c4830bb-2518-0c10-6071-7279865b8ed7.png">

# Slack用に整形するシェルスクリプト
そのまま投稿しようとすると、見づらいので整形します。

```bash:post_git_diff.sh
#!/bin/bash

# $1 : channel

diff=$(cat -)

# format function
function to_slack_format(){
  while read line; do
    if [[ "$line" =~ ^-.+ ]]; then
      echo "~"$line"~" 
    elif [[ "$line" =~ ^\+.+ ]]; then
      echo "*"$line"*"
    else
      echo "$line"
    fi
  done <<EOF 
  $1
EOF
}
# escape
escaped_text=`echo "${diff}" | sed 's/\\\/\\\\\\\/g'`

# format
formatted_text=`to_slack_format "$escaped_text"`

# post
sh ~/post_slack.sh "${formatted_text}" $1
```

こちらも

1. diffの結果をパイプで受け取り
1. エスケープ処理
1. 整形
1. 投稿するシェルへ渡す

の順に処理しています。
こちらのエスケープ処理はバックスラッシュを含んだ文字列を`post_slack.sh`へ渡すためにエスケープしてます。

整形処理では見やすさを考慮して

* 行頭が`-`の行を~~打ち消し線~~に
* 行頭が`+`の行を**太字**

に置き換えています。
Slackでは
`~strike~`が打ち消し線の~~strike~~
`*bold*`が太字の**bold**
になります。

実行方法はリポジトリのディレクトリへ行き、
diffを実行、結果をパイプで渡します。

```shell-session
usersMac:sample user$ git diff HEAD^ | sh ~/post_git_diff.sh chat-test
```

結果はこんな感じになります。
<img width="388" alt="スクリーンショット 2017-06-29 12.48.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/115059/bbb33f4f-3582-59bb-a61c-0550fd5b2156.png">

ちょっと見やすくなりました。

<img width="278" alt="スクリーンショット 2017-06-29 13.10.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/115059/c3d67fdb-c14d-9c01-24ab-c60c0d80a1f1.png">