Ledge Tech Blog

We're the data scientists and AI engineers behind Ledge.

GCP Cloud Functionsを使用して新チャンネル作成通知Slack Appを作る方法

こんにちは。レッジインターン生の大熊です。 今回はSlackで誰かが新しいチャンネルを作成したときに通知するAppを、Google Cloud Functions(以下Cloud Functions)を通じて作成する方法をご紹介します。

弊社ではSlack上で誰かが新しいチャンネルを作成すると、「新しいチャンネルの名前」と「チャンネル作成者」をパブリックのチャンネルに通知するようにしています。新しいチャンネルができたことを可視化できると、組織の中でどんな動きがあるのかを把握しやすくなります。

手順としてもそこまで複雑でないため、是非参考にしてみてください。

大まかな手順

今回はSlackに新しいチャンネルが作成された時、以下のように通知するようにします。

今回はチャンネル作成をキャッチしてからSlackへ通知するまでを、大きく分けて以下の4つのステップで説明します。

  1. Slack appの作成と設定
  2. Cloud Functions上で実行する.pyの作成
  3. Cloud FunctionsとGithub Actionsの設定
  4. SlackのEvent Subscriptionsの設定

1. Slack appの作成と設定

1-1. Appの作成

まず、チャンネル内で通知するappの作成を行います。Slack appのページの右上にある「Create New App」をクリックし、Appの名前とワークスペース決定してAppの作成を行います。

1-2. Scopeの設定

チャンネルへ通知するために、Appに権限を渡す必要があります。「OAuth & Permissions」の「Scopes」からincoming-webhookchat:writeとScopeに追加します。

Scopeを変更すると「Please reinstall your app for these changes to take effect」と言われるので、「Reinstall to Workspace」をクリックし、通知を送りたいチャンネルを選択してインストールします。

(この時、「権限がありません」のような表記が出てインストールできない場合があります。その際は「App Home」の「Your App’s Presence in Slack」の中身を設定することで解消されることがあります。)

1-3. Webhook URLの取得

Slack側にPOSTリクエストをするために必要なURLを取得します。「Incoming Webhooks」の「Webhook URL」からURLをコピーしてどこかにメモしておきます。

Appの設定は一旦ここまででOKです。また後でCloud functions側の設定を行うときに連携するための設定を行います。

2. Cloud Functions上で実行する.pyの作成

Slack通知を行う関数を記入する.pyファイルを作成します。この時、ファイル名は「main.py」である必要があります。

main.pyに以下のように記入して、保存します。

import os
import requests

url = os.getenv('WEBHOOK_URL')

def get_slack_event(request):
    request_json = request.get_json()

    if 'challenge' in request_json:
        return request_json.get("challenge")

    if "event" in request_json:
        request_json = request.get_json()

        channel_name = request_json['event']['channel'].get('name') # チャンネル名
        channel_id = request_json['event']['channel'].get('id') # チャンネルID
        user_id = request_json['event']['channel'].get('creator') # ユーザーID

        payload = '{"text":"New public channel :point_right: <#' + str(channel_id) + '|' + str(channel_name) + '> \n Created by <@' + str(user_id) + '> "}'

        headers = {
            'Content-Type': 'application/json'
        }

        response = requests.request("POST", url, headers=headers, data=payload)

        return print(response.text.encode('utf8'))

if 'challenge' in request_json:の箇所は、Slack AppにエンドポイントのURLを認証させる為のChallenge認証を行っています。送られたchallengeの値をそのまま送り返せばOKです。

次にif "event" in request_json:の箇所でSlackへ通知するための処理を書いていきます。今回の仕様では、「チャンネル名」と「作成ユーザー」を表示したいので、「チャンネル名」、「そのチャンネルのID」、「チャンネルを作成したユーザーのID」の3つをJSONから取得します。Slack app経由でリンクやメンションを行う際には、チャンネルやユーザーのIDを<#channel_id>、<@user_id>の形式で記述する必要があります。またSlack上での表記をカスタムしたいときは各IDの後ろにパイプ(|)を置き、それに続く形で記入します。(公式HP

3. Cloud FunctionsとGithubの設定

次に、Slackからのリクエストを受け取り、それに応じて通知を送り返すためにCloud Functionsの設定を行います。

また今回はGitHub actionsからCloud Functionsへデプロイする方法で行います。

3-1. ローカルでの設定

masterへpushしたときにデプロイを実行するような設定をします。まず、以下のようなディレクトリを準備します。

work
├── .github
│   └── workflows
│       └── function.yml
└── main.py

次に、function.ymlの中身を以下のように記述します。

name: Build and Deploy to Cloud Run

on:
  push:
    branches:
      - master

env:
  PROJECT_ID: ${{ secrets.RUN_PROJECT }}

jobs:
  setup-build-deploy:
    name: Setup, Build, and Deploy
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      # Setup gcloud CLI
      - uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
        with:
          version: "290.0.1"
          service_account_key: ${{ secrets.RUN_SA_KEY }}
          project_id: ${{ secrets.RUN_PROJECT }}

      - name: Deploy
        run: |-
          gcloud functions xxxx

gcloud functions xxxxにはgcloudコマンドでデプロイするときのコマンドに設定します。gcloudコマンドの使い方は公式のリファレンスをご参照ください。

またデプロイのコマンドの中に、ランタイム環境変数として、先ほどメモしたWebhook URLを指定します。

3-2. サービスアカウントの作成・権限の付与・鍵の取得

Github Actions上でgcloudコマンドを実行するためにはGCPのサービスアカウントが必要になります。

まずgcloudコマンドで以下のように実行しアカウントを作成します。

gcloud iam service-accounts create slack-channel-created-notification \
--description="GitHubAction" \
--display-name="SLACK CHANNEL CREATED NOTIFICATION"
  • slack-channel-created-notification:アカウント名になるのでやることに応じて適宜設定。
  • descriptionとdisplay-nameは必要に応じて適宜内容を書きます。

アカウントを作成したら、次にロールを追加します。roles/cloudfunctions.developerroles/iam.serviceAccountUserを以下のコマンドで追加します。

gcloud projects add-iam-policy-binding (プロジェクトID) \
--member="serviceAccount:slack-channel-created-notification@(プロジェクトID).iam.gserviceaccount.com" \
--role="roles/cloudfunctions.developer"
gcloud iam service-accounts add-iam-policy-binding \
(プロジェクトID)@appspot.gserviceaccount.com \
--member='serviceAccount:slack-channel-created-notification@(プロジェクトID).iam.gserviceaccount.com' \
--role=roles/iam.serviceAccountUser

(プロジェクトID)にはプロジェクト名を記入します。すなわちmemberの箇所は、{アカウント名}@{プロジェクト名}.iam.gserviceaccount.comのようにして記述します。

最後に、GithubのSecretsに登録するためのjson鍵を取得する。以下のコマンドで取得できます。

gcloud iam service-accounts keys create ~/key.json --iam-account slack-channel-created-notification@(プロジェクト名).iam.gserviceaccount.com

3-3. GithubのSecretsにプロジェクト名と鍵を登録

以下のようにsettings -> secretsの画面で、プロジェクトIDと鍵を登録します。NameとValueは以下のように設定します。

  • RUN_PROJECT:プロジェクトID
  • RUN_SA_KEY:前節で取得したjson

これで大まかな設定は完了です。ここでデプロイしておきます。

4. SlackのEvent Subscriptionsの設定

チャンネル作成時をトリガーとしてCloud Functionsにデータを送るために、Event Subscriptionsを設定します。

まずCloud Functionsの管理画面の中で、先にデプロイした関数の編集画面にいき、トリガーURLを取得します。

次にSlack Appの設定画面に戻り、「Event Subscriptions」で「Enable Events」を「On」にし、「Request URL」に先ほど取得したトリガーURLを記述します。

この時、「Varified」と表示されればOKです。

完成

以上で、新しいチャンネルを作成するとSlackに通知が行くようになるはずです。

視認性担保のためにアイコン等は適宜変えると良いと思います(Slack Appの設定画面の「Basic Infomation」の下の方に設定するところがあります)。

まとめ

今回はSlackで誰かが新しいチャンネルを作成したときに通知するAppを、Cloud Functionsを通じて作成する方法をご紹介しました。

通知されるようにすると、新しいチャンネルが意外と日々作成されていることに気づきました。そして全体の動きがわかることで、「あの部署の人は何やっているんだろう」と思っていたのが、出社せずとも「今こういうプロジェクトに取り組んでいるのか!」ということがすぐにわかるようになりました。そのため、テレワーク下での組織の動きの把握には持ってこいの機能ではないかなと感じています。

参考資料