【GitHub Actions】処理の成否をSlackに通知する

## 完成系のサンプル

実際のワークフローファイルを先に載せておく。以下のGitHub Actionsの定義は、npmによるlintなどを実行した後にGitHub Pagesに自動デプロイし、その実行の成否をSlackで通知する。

▼ GitHub Pagesへの自動デプロイを実行し、成否をSlack通知するGitHub Actionsの定義

```yaml
on:
  push:
    branches:
      - demo

jobs:
  build-deploy:
    runs-on: ubuntu-18.04
    steps:
    - uses: actions/checkout@v2

    - name: setup node
      uses: actions/setup-node@v1
      with:
        node-version: '10.x'

    - name: Cache dependencies
      uses: actions/cache@v1
      with:
        path: ~/.npm
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.os }}-node-

    - name: install
      run: |
        cd web
        npm ci

    - name: lint
      run: |
        cd web
        npm run lint

    - name: build
      run: |
        cd web
        npm run build:prod

    - name: deploy
      uses: JamesIves/github-pages-deploy-action@releases/v3    
      with:
        ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
        BRANCH: gh-pages
        FOLDER: web/dist

    # 上記までの処理が成功した場合、以下のSlack通知処理が実行される
    - name: Slack Notification Success
      uses: rtCamp/action-slack-notify@v2.0.0
      env:
        SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
        SLACK_COLOR: '#5cb85c'
        SLACK_TITLE: 'Success to Deploy to GitHub Pages :rocket:'
        SLACK_MESSAGE: ':closed_book: ${{ github.repository }}' 

    # 上記までの処理のいずれかが失敗した場合、以下のSlack通知処理が実行される
    - name: Slack Notification Failure
      if: failure()
      uses: rtCamp/action-slack-notify@v2.0.0
      env:
        SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
        SLACK_COLOR: '#dc143c'
        SLACK_TITLE: 'Failure to Deploy to GitHub Pages :boom:'
        SLACK_MESSAGE: ':closed_book: ${{ github.repository }}'
```

上記のワークフローは[前回の記事](https://qiita.com/x-color/items/2c9db85c2a97c56b2c21)で紹介した以下のリポジトリで実際に利用している。

<a href="https://github.com/x-color/vue-trello"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/x-color/vue-trello.png" width="460px"></a>

## 処理内容

Slackの通知処理は以下のActionを利用している。

- [rtCamp/action-slack-notify](https://github.com/rtCamp/action-slack-notify)

また、上記ActionsはSlackのIncoming Webhooksを利用しているので別途設定が必要となる。下記参照。

- [Sending messages using Incoming Webhooks](https://api.slack.com/messaging/webhooks)

今回重要なものは、以下の部分。

```yaml
jobs:
  sample-job:
    runs-on: ubuntu-18.04
    steps:
    #    :
    # 何かしらの処理
    #    :

    # 上記までの処理が成功した場合、以下の成功通知処理が実行される
    - name: Slack Notification Success
      uses: rtCamp/action-slack-notify@v2.0.0
      env:
        SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
        SLACK_COLOR: '#5cb85c'
        SLACK_TITLE: Success to Deploy to GitHub Pages :rocket:'
        SLACK_MESSAGE: ':closed_book: ${{ github.repository }}' 

    # 上記までの処理のいずれかが失敗した場合、以下の失敗通知処理が実行される
    - name: Slack Notification Failure
      if: failure() # ← 上記までのいずれかが失敗した場合にこの条件が真になる
      uses: rtCamp/action-slack-notify@v2.0.0
      env:
        SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
        SLACK_COLOR: '#dc143c'
        SLACK_TITLE: 'Failure to Deploy to GitHub Pages :boom:'
        SLACK_MESSAGE: ':closed_book: ${{ github.repository }}'
```

処理自体は簡単で、ワークフローの各ステップの処理の実行の成否により処理を分岐したのちに、Slack通知処理を行ってくれる`rtCamp/action-slack-notify@v2.0.0`を呼び出しているだけ。
成功・失敗で通知内容を分けるための分岐処理に、`step` の `if` 条件を利用している。

### 成功通知処理

成功通知処理は以下のようになっている。

```yaml
   - name: Slack Notification Success
     uses: rtCamp/action-slack-notify@v2.0.0
     env:
        SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} # SlackのIncoming Webhooks URL
        SLACK_COLOR: '#5cb85c'
        SLACK_TITLE: 'Success to Deploy to GitHub Pages :rocket:'
        SLACK_MESSAGE: ':closed_book: ${{ github.repository }}' 
```

`if` を使用していないように見えるが、`step`はデフォルトで以下が定義されている。

```yaml
if: success()
```

そのため、特に記述しなくても、直前に実行された処理が成功していた場合、実行されるようになる。

また、もし数個前の処理が失敗し、1つ前の処理が実行されていない場合は処理がスキップされた判定なる。そのため、直前に実行されたstepは数個前の失敗した処理ということになり、成功通知処理は実行されない。

### 失敗通知処理

失敗通知処理は以下のようになっている。

```yaml
    - name: Slack Notification Failure
      if: failure() # ← この設定により失敗時にのみ実行を指定
      uses: rtCamp/action-slack-notify@v2.0.0
      env:
        SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
        SLACK_COLOR: '#dc143c'
        SLACK_TITLE: 'Failure to Deploy to GitHub Pages :boom:'
        SLACK_MESSAGE: ':closed_book: ${{ github.repository }}'
```

`if` で `failure()` を指定しているので直前に実行された処理が失敗した場合にのみ実行される。

### 処理の流れのまとめ

#### 成功時

ワークフローが成功した場合の処理の流れをまとめると

1. 処理１ ← 成功
2. 処理２ ← 成功
3. 処理３ ← 成功
4. **成功通知処理** ← 直前に実行された処理は成功（処理３）のため実行
5. 失敗通知処理 ← 直前に実行された処理は成功（成功通知処理）のためスキップ

#### 失敗時

ワークフローが失敗した場合の処理の流れをまとめると

1. 処理１ ← 成功
2. 処理２ ← 失敗
3. 処理３ ← スキップ
4. 成功通知処理 ← 直前に実行された処理は失敗（処理２）のためスキップ
5. **失敗通知処理** ← 直前に実行された処理は失敗（処理２）のため実行

## 最後に

上記のように `if` を用いてうまく分岐させることで処理の成否に応じて通知を分岐することができる。
また今回は、`step`の成否によって処理を分岐したが、もちろん`job`の成否によって通知を分岐させることもできる。