GitHub Actions のSlack通知の最適化

## はじめに
以下のようなワークフローでいずれかが失敗した場合に一度だけSlackなどで通知することを考えます。

- 複数のJOBが needs で依存している
- matrix が使用されている
- 特定の条件でのみ実行されるJOBが含まれる

例：lint → test → publish (タグ付与の場合のみ) → GitHub Releases作成

```yaml
jobs:
  lint:
    name: ESLint
    runs-on: ubuntu-latest
    steps:
      # ...

  test:
    name: Test
    needs: lint
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: ['11', '12']
    steps:
       # ...

  publish:
    name: Publish Package
    needs: test
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/v')
    steps:
       # ...

  release:
    name: Create GitHub Release
    needs: publish
    runs-on: ubuntu-latest
    steps:
      # ...
```

簡単そうだし機能としてあっても良さそうですが結構難しいです。

## もともとやっていた方法

- すべてのJOBのそれぞれのステップの最後に失敗した場合の通知を設定
- 成功したときの通知も必要な場合は
    - 特定の条件でのみ実行されるJOBを除外
    - 通知用のJOBを最後に追加し needs を設定

先程の例では

```yaml
jobs:
  lint:
    name: ESLint
    runs-on: ubuntu-latest
    steps:
      # ...

      - uses: 8398a7/action-slack@v2
        with:
          status: failure
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

  test:
    name: Test
    needs: lint
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: ['11', '12']
    steps:
       # ...

      - uses: 8398a7/action-slack@v2
        with:
          status: failure
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

  slack:
    name: Slack
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: 8398a7/action-slack@v2
        with:
          status: success
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
```

特定の条件でのみ実行されるJOBが入っているとSKIPされた際に通知用のJOBまで到達しません。
`if: always()` を通知用のJOBに設定すればSKIPされてもいずれかのJOBが失敗しても通知用のJOBが実行されますが、`job.status` は常に `Success` になります。
また、matrix ではそれぞれ失敗の通知が発行される問題もあります。

## 最近やっている方法

最近 GitHub Actions API が公開されました。
それを利用してワークフローの結果を取得する GitHub Actions を作成したのでそれを使用します。

https://github.com/technote-space/workflow-conclusion-action

```yaml
jobs:
  lint:
    name: ESLint
    runs-on: ubuntu-latest
    steps:
      # ...

  test:
    name: Test
    needs: lint
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: ['11', '12']
    steps:
       # ...

  publish:
    name: Publish Package
    needs: test
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/v')
    steps:
       # ...

  release:
    name: Create GitHub Release
    needs: publish
    runs-on: ubuntu-latest
    steps:
      # ...

  slack:
    name: Slack
    needs: release # 最後のJOBを指定
    runs-on: ubuntu-latest
    if: always() # alwaysを指定
    steps:
      - uses: technote-space/workflow-conclusion-action@v1 # Workflow の結果を取得するアクション
      - uses: 8398a7/action-slack@v2
        with:
          status: ${{ env.WORKFLOW_CONCLUSION }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
```

変更点は最後のJOBの追加のみです。
`env.WORKFLOW_CONCLUSION` には `skipped`, `success`, `cancelled`, `failure` のいずれかが設定されます。

いずれかのJOBが失敗した時のみ通知したい場合は通知用のJOBを以下のようにします。

```yaml
  slack:
    name: Slack
    needs: release
    runs-on: ubuntu-latest
    if: always()
    steps:
      - uses: technote-space/workflow-conclusion-action@v1
      - uses: 8398a7/action-slack@v2
        with:
          status: failure
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
        if: env.WORKFLOW_CONCLUSION == 'failure'
```

これで何回も通知用のステップを書く必要がなくなり、また matrix での失敗も複数送られることがなくなります。