Notionのタスクのステータス変更をDiscordでメッセージを送る【Discord.py,Notion API,GitHub Actions,cron-job】

はじめに

チーム開発を行っているときのタスク管理はいろいろ方法があるかと思います。
私が参加しているインディーズゲームのチームの一つでは、Notionでのタスク管理を行っています。 このときにタスクのステータス(対応中・確認中、担当者へのFB)などが変わった際に、チャットで送るのはわりと手間になります。
今回はこちらの作業を自動化してチームの生産性をあげていこうと考えました

完成物

Discord側の通知メッセージ

  1. タスクステータス変更時

  2. タスク期限が迫っている時

Repositoryは以下で 公開しています。

github.com

やりたいこと

  1. Notionの特定のタスク状態が変更されたときに担当者及び確認者 Discordに通知を送る

  2. 一日一回タスクの期限が3日以内のタスクをDiscordで担当者及び確認者に知らせる

  3. タスクの変更状態をなるべくリアルタイムで監視する

(4. お金をかけずに無料で行う(インディーズゲームのため) )

前提として、Notionのタスクボードは以下の感じにわけられています。

準備

まずは今回使っていくAPI等の作成や登録準備を行います。

Notionの インテグレーション(API)の作成と登録

以下のサイトで Notionのアプリを作成します。

www.notion.so

タスク監視用に作成した インテグレーション情報は以下です。内部で使うだけであれば、 インテグレーションの種類は、内部インテグレーション で大丈夫です。

このときシークレットトークンは後ほど使うので、控えておいてください。

次に Notionのタスクページの share (日本語の場合は 共有 ) に先ほど作成した インテグレーションを以下のように追加します。

DiscordのWebHookの作成

今回は Discordのメッセージを送るだけなので、Botではなく 準備・導入が簡単な WebHookを使っています。

サーバー設定 → 連携サービス → ウェブフック から以下のように作成します。

WebHookのURLは後ほど使うため、控えておいてください。

GitHub のpersonal tokenの作成

Setting → Developer settings → personal access tokesから以下のように workflow にチェックを入れて アクセストークンを作成します。

自動化内容と実装

1. Notionの特定のタスク状態が変更されたときに担当者及び確認者 Discordに通知を送る

2. 一日一回タスクの期限が3日以内のタスクをDiscordで担当者及び確認者に知らせる

基本的に以下の記事とRepositoryをそのまま使っています。 細かい実装等や Notion APIについては、以下の記事でも解説していますのでご覧ください

ayousanz.hatenadiary.jp

github.com

3. タスクの変更状態をなるべくリアルタイムで監視する

実行環境の構築周辺について

今回 上記の二つの処理を定期的に実行するために、お金をかけたくない・なるべつ楽をしたい(開発・運用)ということでいろいろ調べました。 方法としては、だいたい以下があるではないかと考えました。 1. IaaS(EC2やGCE) で環境構築をして、cronコマンドで定期時的に実行する。 2. FaaS(lambdaやCloud Functions) + 監視系(Cloud Watchや schedule、AWS Batch) 3. Google Script Appでの実行 4. GitHub Actionsでの定期実行(cron) 5. その他 cronサービス

結果から言うと今回は、4 + 5の組み合わせで構築を行いました。 インディーズゲームでは、運用メンバーが技術に詳しいわけではない可能性が高いことや将来的にほかのサービスに移行する際に version管理されていてDockerなどにも載せやすいように考えています。

構築図は以下のようになっています。

Notionのタスク変更履歴の取得

まずNotionのタスク状態を監視するには、変更履歴を取得する必要があります。

そこで、NotionAPIのSearchを使って変更された内容を取得します。

Queryの書き方は以下のようになります。→ GitHubのソースコード

        db = self.notion.search(
            **{
                "sort": {
                    "direction": "descending",
                    "timestamp": "last_edited_time"
                },
                "filter": {
                    "value": "page",
                    "property": "object"
                },
                "page_size": 100,
            }
        )

次にその中から 変更されたタスクを探すのですが、一つ問題があります。定期実行では厳密にはリアルタイムでの監視ではないため、処理中などにタスクが移動された場合は監視できなくなります。

そこで、Notion側に タスクの移動前に状態を持たせて変数の代わりにしました。Propertyの preStatus という名前で隠しパラメータを作成しています。

移動前のパラメータがあるので、こちらを使ってフィルターをしていきます。

    def is_task_status_doing_from_confirm(self, result) -> bool:
        status = result['properties']['ステータス']['select']['name']
        pre_status = result['properties']['preStatus']['select']['name']
        if status == '対応中' and pre_status == '確認依頼':
            self.update_task_preStatus(result['id'], status)
            return True
        else:
            return False

    def is_task_status_confirm_from_doing(self, result) -> bool:
        status = result['properties']['ステータス']['select']['name']
        if status == '確認依頼':
            self.update_task_preStatus(result['id'], status)
            return True
        else:
            return False

これで変更されたタスクのみが取得できます。

定期実行サービスから GitHub Actionsを実行する

GitHub Actionsを手動実行するだけであれば、on: workflow_dispatch: をymlファイルに入れれば Actions画面から実行することができます。 しかし、これをほかのサービスから呼び出したい場合は少し設定する必要があります。

まずは workflowのidを取得する必要があるので、

curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/org-name/repository-name/actions/workflows 

を叩いて情報を取得します。

以下のような情報が取得できるかと思います。

{
    "total_count": 3,
    "workflows": [
        {
            "id": 25677508,
            "node_id": "W_kwDOHTP_Hc4Bh87E",
            "name": "CodeQL",
            "path": ".github/workflows/codeql-analysis.yml",
            "state": "active",
            "created_at": "2022-05-08T13:11:13.000Z",
            "updated_at": "2022-05-08T13:11:18.000Z",
            "url": "https://api.github.com/repos/astilbestudio/Notion-Watch-Task-Notification-discord/actions/workflows/25677508",
            "html_url": "https://github.com/astilbestudio/Notion-Watch-Task-Notification-discord/blob/main/.github/workflows/codeql-analysis.yml",
            "badge_url": "https://github.com/astilbestudio/Notion-Watch-Task-Notification-discord/workflows/CodeQL/badge.svg"
        },
        {
            "id": 25677510,
            "node_id": "W_kwDOHTP_Hc4Bh87G",
            "name": "watch-deadline-task",
            "path": ".github/workflows/watch-deadline-task.yml",
            "state": "active",
            "created_at": "2022-05-08T13:11:13.000Z",
            "updated_at": "2022-05-08T13:11:21.000Z",
            "url": "https://api.github.com/repos/astilbestudio/Notion-Watch-Task-Notification-discord/actions/workflows/25677510",
            "html_url": "https://github.com/astilbestudio/Notion-Watch-Task-Notification-discord/blob/main/.github/workflows/watch-deadline-task.yml",
            "badge_url": "https://github.com/astilbestudio/Notion-Watch-Task-Notification-discord/workflows/watch-deadline-task/badge.svg"
        },
        {
            "id": 25782832,
            "node_id": "W_kwDOHTP_Hc4BiWow",
            "name": "watch-task-status",
            "path": ".github/workflows/watch-task-status.yml",
            "state": "active",
            "created_at": "2022-05-10T04:35:43.000Z",
            "updated_at": "2022-05-10T04:35:43.000Z",
            "url": "https://api.github.com/repos/astilbestudio/Notion-Watch-Task-Notification-discord/actions/workflows/25782832",
            "html_url": "https://github.com/astilbestudio/Notion-Watch-Task-Notification-discord/blob/main/.github/workflows/watch-task-status.yml",
            "badge_url": "https://github.com/astilbestudio/Notion-Watch-Task-Notification-discord/workflows/watch-task-status/badge.svg"
        }
    ]
}

これで 実行したい workflowのIDを取得できました。

次にIDを使って外部から Actionsを実行します。

curl -XPOST -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/org-name/repository-name/actions/workflows/workflow-id/dispatches -d '{"ref": branchName"}' 

後からこれを任意の定期実行サービスで実行すれば定期的にタスクのステータス変更を監視することができます!

参考にさせていただいたサイト

swfz.hatenablog.com