GitHubActionsを使ってみた！masterブランチにpushがあったらSlackに通知する機能をサクッと作る

前々から気にはなっていたGitHubActions。全然試したことがなかったので、今回軽い機能を作ってみて試してみました。

**[※GitHubActionsとは](https://help.github.com/ja/actions/getting-started-with-github-actions/about-github-actions)**
>ワークフローとは、GitHubで任意のプロジェクトをビルド、テスト、パッケージ、リリース、またはデプロイするためにリポジトリで設定できる、カスタムの自動プロセスです

皆んな大好き自動化をymlで簡単に書けるで！って感じのやつ。
説明にある通り、リリースやビルド作業まで全部自動化してくれるすごいやつ。(CircleCIで行なってたことをGitHub内で完結できるのがGitHubActionsのメリット）

今回はそんな大層なものは作成せず、軽いGit運用のための自動化を行います。
「masterブランチにpushがあった段階でslackに通知をする」機能を作成します。完成は以下のような感じ。
<img width="648" alt="Slack.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253969/eed740a6-20b8-59b7-b849-84eb59fdbccd.png">

## GitHubActionsを使ってワークフローを設定しよう
GitHubの公式にほぼ完成系が載っていた。
[ワークフローを設定する](https://help.github.com/ja/actions/configuring-and-managing-workflows/configuring-a-workflow)

これを参考に以下のことを追記していきます。

1. git logをcatする
2. catした内容をcurlでpostしてSlack側に通知


### GitHubのリポジトリにワークフローを設定する
まずGitHubの自分のリポジトリに所に行って「Actions」タブをクリック。
赤枠の部分「Set up workflow yourself」というボタンがあるのでクリックする
<img width="1612" alt="Actions.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253969/dccfb2f9-af53-a1b1-bd77-bc6e1d04a9e1.png">

そうすると.githubディレクトリ配下に自動で雛形を作成してくれます。
<img width="1671" alt="New_File.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253969/7f8269f0-941c-cdef-5212-251d7567dc8d.png">

デフォルトだと以下のように書いてあります。
ほとんどこのまま使えます。

```yml

# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the action will run. Triggers the workflow on push or pull request 
# events but only for the master branch
on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
    # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    - uses: actions/checkout@v2

    # Runs a single command using the runners shell
    - name: Run a one-line script
      run: echo Hello, world!

    # Runs a set of commands using the runners shell
    - name: Run a multi-line script
      run: |
        echo Add other actions to build,
        echo test, and deploy your project.
```

masterブランチにpush,　masterブランチへのプルリクが作成されたら

```yml
on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]
```

色々echoするで！って感じで書かれています。
デフォルトのまま実行してもechoされるだけです。
ここを変えて、git logを出力して、curlでpost送信する記述を書けばOK。

```yml
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
    # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    - uses: actions/checkout@v2

    # Runs a single command using the runners shell
    - name: Run a one-line script
      run: echo Hello, world!

    # Runs a set of commands using the runners shell
    - name: Run a multi-line script
      run: |
        echo Add other actions to build,
        echo test, and deploy your project.
```

### Gitのログをフォーマットして表示する
Gitのログをただ闇雲に送ってもしょうがないので「誰がマージして、何のファイルを更新したか」の内容で送ろうと思います。

割と見やすいサイトがあったので置いておきます。
https://26gram.com/git-log

今回は–numstat オプションを使用して、変更のあったファイル、変更行数を出力。
`git log --numstat -m -1`

上記のコマンドを実際にgitリポジトリのディレクトリで打つと以下のような感じで出力されます。

```bash

❯ git log --numstat -m -1
commit ferfgoergedk32323121 (HEAD -> master, origin/master, origin/HEAD)
Author: ys <hoge@gmail.com>
Date:   Sun Feb 2 10:42:55 2020 +0900

    @style 謎の改行削除

1       1       header.php
```

さらにgitのログをフォーマットして表示したいので、オプションを追加します。
`--date=iso --pretty='[%ad] %h %an : %s'`

これを実際に打つと以下のような感じでコミット者とコミットメッセージなんかも拾えます。
詳しくは以下を参照してください。
[git logのフォーマットを指定する](https://qiita.com/harukasan/items/9149542584385e8dea75)

```bash

❯ git log --date=iso --pretty=format:"[%ad] %h %an : %s"

[2020-02-02 10:42:55 +0900] 34sr3t3 ys : @style 謎の改行削除
[2020-02-02 10:24:17 +0900] 34sr342 ys : @update CSSを最新化
[2020-02-01 10:21:26 +0900] 34sr3t3 ys : @update 運用用にリファクタリング
[2020-01-29 07:18:39 +0900] 34sr3t3 ys : @udpate SEO系を修正
[2020-01-28 07:51:56 +0900] 34sr3t3 ys : @update 構造化マークアップを修正
[2020-01-12 19:09:49 +0900] 34sr3t3 ys : @test テスト修正
```

これを合体させればOK。

```bash
git log --numstat -m -1 --date=iso --pretty='[%ad] %h %an : %s'
```

### SlackのWebhookURLを取得する
すでにSlackに登録してあること前提で進めます。
Slack通知を飛ばすためにはWebhookのURLが必要です。
以下のURLにアクセスして、自分の飛ばしたいワークスペースのチャンネル名でWebhookのURLを作成します。
https://slack.com/services/new/incoming-webhook

赤枠からサインインしてるワークスペースのチャンネルを選択。
選択したら「Incoming Webhook インテグレーションの追加」ボタンをクリック。
<img width="1077" alt="Incoming_Webhook.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253969/cea7eb37-f71b-9336-a1f5-53bac2bacb6f.png">

そうするとWebhookのURLが発行されます。
これは他人には公開してはいけないので大切にコピー。

<img width="996" alt="Incoming_Webhook___Slack_App_ディレクトリ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253969/a796fe13-44fc-24b8-7828-7a641c349ec6.png">

項目の下の方に行くと、「こう送れば、チャットにこう表示されるでー」というcurlのコマンド例が表示されています。＼優しい／
実際に自身のターミナルからコマンド叩けば、Slackに通知がいきます。
<img width="953" alt="Incoming_Webhook___Slack_App_ディレクトリ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253969/82857779-bb72-9951-adbd-8a2f0bbee5f0.png">

このcurlコマンドはほぼそのまま使うのでコピペしておきましょう。

## 実際にGitHubワークフローを変更してみる
上記のコマンドを羅列するには、jobs.build.runsの箇所にコマンドを繋ぐだけ。
一つ一つ設定していきます。


#### ①：ワークフロー名を設定
実行してくれるワークフローの名前。お好みで。

```yml
name: Docker image CI
```

#### ②：トリガーを設定

masterブランチにpushがあったらイベントが発火する。

```yml
on:
  push:
    branches: master
```

#### ③：環境変数を設定

環境変数を設定します。（個人的にコマンドが長くなるのが嫌で変数を使っています）
先ほどコピーしたSlackのWebhookのURLを`HOOK_URL`にペースト。
`REPO_NAME`は自身のリポジトリ名を記入してください。

```yml
env:
  HOOK_URL: https://hooks.slack.com/services/HOFEHOGE/HOGE123HOGE345HOGE678
  REPO_NAME: YOUR_REPOSITORY_NAME
```

#### ④：ジョブを設定

先ほどのコマンドをコピペ。
パイプで実行したい場合は、最初にパイプを置いちゃうらしい。`run: |`みたいな感じで。
先ほどのgitのlogをテキストファイルに保存して、curlでその内容を送信！

Slackの記法については詳しくは触れませんが、`text`部分に送信内容を書けばOK。
`icon_emoji`は自身のSlackに絵文字をインストールするなりして、色々カスタマイズできます。（カスタム絵文字というらしい）
僕の場合は**:github_icon:**という形で、GitHubのアイコンを使用しているので以下の記述になっています。<img width="59" alt="Slack.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253969/9747418c-ca15-65d0-3e70-5047d1fb94d0.png">＞わいがGitHub君や

カスタム絵文字に関しては以下を参照してください。
https://slack.com/intl/ja-jp/help/articles/206870177-%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E7%B5%B5%E6%96%87%E5%AD%97%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B

```yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: Send Slack from gitlog
      run: |
        git log --numstat -m -1 --date=iso --pretty='[%ad] %h %an : %s' > gitlog.txt
        curl -X POST --data-urlencode "payload={\"channel\": \"#hogehoge\", \"username\": \"github_action_bot\", \"text\": \"*${REPO_NAME} masterブランチが更新されました。*\n `cat gitlog.txt`\", \"icon_emoji\": \":github_icon:\"}" ${HOOK_URL}
```

全体像は以下。

```yml
name: Docker image CI

on:
  push:
    branches: master
    
env:
  HOOK_URL: https://hooks.slack.com/services/HOFEHOGE/HOGE123HOGE345HOGE678
  REPO_NAME: Docker-Dev

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: Send Slack from gitlog
      run: |
        git log --numstat -m -1 --date=iso --pretty='[%ad] %h %an : %s' > gitlog.txt
        curl -X POST --data-urlencode "payload={\"channel\": \"#hogehoge\", \"username\": \"github_action_bot\", \"text\": \"*${REPO_NAME} masterブランチが更新されました。*\n `cat gitlog.txt`\", \"icon_emoji\": \":github_icon:\"}" ${HOOK_URL}
```

#### ⑤：動作確認

実際に設定したリポジトリでmasterにpushを実行してみましょう。
以下のような感じで通知が飛んでいれば成功です。
<img width="648" alt="Slack.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253969/eed740a6-20b8-59b7-b849-84eb59fdbccd.png">

### 終わり
思った以上に簡単にできた。
次はデプロイの手順とか色々勉強してみようー！