【Github Actions】reusable workflowを使って、エラー時にslack通知する

## はじめに

GitHub Actionsを色々使っていると、「このフロー、他のワークフローでも使いたいな・・・」と言う場面が出てきました。
具体的にいうと、ワークフローがこけた時、slack通知してくれるワークフローを使い回したい。ということで、そのやり方を記録しておきます。

## GitHub Actionsの設定

### 呼び出される側の設定（slack通知）

共通のslack通知のワークフローを、以下の通り作成します。
これが「呼び出される側」のワークフローになります。
```.github/workflows/error-notifications.yml
on:
  workflow_call:
    inputs:
      detail:
        type: string
        required: true

jobs:
  notification:
    runs-on: ubuntu-latest
    steps:
      - name: Slack Notification on Failure
        uses: rtCamp/action-slack-notify@v2.0.2
        env:
          SLACK_COLOR: danger
          SLACK_MESSAGE: ${{ inputs.detail }}
          SLACK_WEBHOOK: "" # TODO:任意の値に変更する
```

一つ一つの設定を詳しく見ていきましょう。

```
on:
  workflow_call:
    inputs:
      detail:
        type: string
        required: true
```

この`on.workflow_call`が、「呼び出される側」を意味してます。
これがないと再利用ができないとのこと。

また、[on.workflow_call.inputs](https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#onworkflow_callinputs)は、ワークフローの呼び出し時に指定する、「引数」のような役割を果たしてくれます。

この例では、string型の`detail`という引数を要求しています。
エラーの内容・slackに載せたい情報は、呼び出し元のワークフローによって異なるので、呼び出し時に指定できるようにしよう、という考えです。


```
jobs:
  notification:
    runs-on: ubuntu-latest
    steps:
      - name: Slack Notification on Failure
        uses: rtCamp/action-slack-notify@v2.0.2
        env:
          SLACK_COLOR: danger
          SLACK_MESSAGE: ${{ inputs.detail }}
          SLACK_WEBHOOK: "" # TODO:任意の値に変更する
```
こちらがこのワークフローの核となる部分、「slack通知する」アクションです。
marketplaceにある[Slack Notify](https://github.com/marketplace/actions/slack-notify)を使用しています。

`SLACK_WEBHOOK`には、通知先チャンネルのslack webhookのURLを入れます。

このワークフローを使うと、以下のような形でslack通知されます。

![スクリーンショット 2022-01-25 11.45.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311681/bb72b506-612b-52dd-615b-311579dbf374.png)

## 呼び出し側の設定

呼び出し側では、`jobs`内で呼び出し先のワークフローを指定します。

### 例

※このワークフローについては[別記事](https://qiita.com/suuu/items/ee0a54054ae8fea07a52)で解説してます。

```pr-reviewer-assign.yml
name: PR Reviewer Auto Assignment

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
    branches: 
      - master
      
jobs:
  reviewer-assign:
    runs-on: ubuntu-latest
    env:
      API_BASE_URL: "https://api.github.com"
      COMMON_HEADER: "Accept: application/vnd.github.v3+json"
      ORG: "ORG" # TODO:任意の値に変更する
      TEAM_SLUG: "TEAM_NAME"　 # TODO:任意の値に変更する
    
    if: github.event.pull_request.base.ref == 'master' && github.event.pull_request.draft == false
    steps: 
      - name: Get Members List
        id: get-members-list
        run: |
          response=$(curl -X GET \
               -H "$COMMON_HEADER" \
               -H "Authorization: token ${{ secrets.ORG_TOKEN }}" \　# TODO:任意の値に変更する
               $API_BASE_URL/orgs/$ORG/teams/$TEAM_SLUG/members)
          members=$(echo $response | jq '[.[].login | select(. != "${{ github.actor }}")]')
          echo ::set-output name=members::$members
          
      - name: Set Reviewers
        id: set-reviewers
        run: |
          curl -X POST \
               -H "$COMMON_HEADER" \
               -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
               $API_BASE_URL/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers \
               -d '{ "reviewers": ${{ steps.get-members-list.outputs.members }} }'
 # 上記処理が失敗した場合、slack通知    
  error-notifications:
    if: failure()
    needs: reviewer-assign
    uses: REPO/.github/workflows/error-notifications.yml@master # TODO:任意の値に変更する
    with: 
      detail: "レビュアーのアサインに失敗しました。"
```

`steps`から呼び出すと、以下のようなエラーが出て呼び出しができません。

```
reusable workflows should be referenced at the top-level `jobs.*.uses' key, not within steps
```

## さいごに

複数のGitHub Actionsを使っていると、同じような処理をいくつかのワークフローで使いたい場面はよくあると思います。
そんなときに、こうして共通化できるのは便利ですね。

最後までお読みいただき、ありがとうございました！