こつつみ

コツコツ積み上げる

AWS Lambda + GraphQLでGitHubのコミット数を通知してくれるSlack botを作った

はじめに

2021年10月ごろより、出来るだけ毎日GitHubの草を生やそうと決めました。 また、Pythonのコードの書き方を身につけることも目的です。

そのために、Slackの自分のチャンネルに通知してくれるbotを作ろうと考えました。

機能

f:id:ue-sho:20211003152642p:plain

上記のように1日のコミット数をSlackに通知してくれる。

  • Lambdaと連携させたCloudWatch Eventを使って 0:00 にイベントを発火する
  • Slackの自分の #times_uesho に通知する
  • GitHubの GraphQL API を使ってコミット数を取得する
  • プライベートリポジトリのコミット数まで取得する
  • CloudFormationでインフラをコード化する ※別記事にて解説予定
  • GitHub Actions でmasterにpushしたら自動でデプロイする ※別記事にて解説予定

GitHubの GraphQL API

当初、コントリビューションからコミット数を取得していたが、どうもプライベートリポジトリの値は取れなかった。

        query (
            $name: String!,
            $from: DateTime!,
            $to: DateTime!
        ) {
            user(login: $name) {
                name
                contributionsCollection(from: $from, to: $to) {
                    totalRepositoryContributions
                    totalCommitContributions
                    commitContributionsByRepository {
                        repository {
                            nameWithOwner
                        }
                        contributions {
                            totalCount
                        }
                    }
                }
            }
        }

そこで、リポジトリごとにコミット数を調べる方法に変更した。(デフォルトブランチのコミット数しか取れなそう)

        query($date: GitTimestamp!) {
          viewer {
            repositories(last: 100) {
              nodes {
                nameWithOwner
                defaultBranchRef {
                  target {
                    ... on Commit {
                      history(since: $date) {
                          totalCount
                      }
                    }
                  }
                }
              }
            }
          }
        }

こうすることで以下のようなレスポンスが得られる。

{
        "data": {
            "viewer": {
                "repositories": {
                    "nodes": [
                        {
                            "nameWithOwner": "ue-sho/pycabook_rentomatic",
                            "defaultBranchRef": {
                                "target": {
                                    "history": {
                                        "totalCount": 0
                                    }
                                }
                            }
                        },
                        {
                            "nameWithOwner": "ue-sho/Calculator",
                            "defaultBranchRef": {
                                "target": {
                                    "history": {
                                        "totalCount": 0
                                    }
                                }
                            }
                        },
                        {
                            "nameWithOwner": "ue-sho/rent_price_forecast",
                            "defaultBranchRef": {
                                "target": {
                                    "history": {
                                        "totalCount": 0
                                    }
                                }
                            }
                        },
                        {
                            "nameWithOwner": "ue-sho/telescopic-sidebar",
                            "defaultBranchRef": {
                                "target": {
                                    "history": {
                                        "totalCount": 0
                                    }
                                }
                            }
                        },
                        {
                            "nameWithOwner": "ue-sho/git-commit-count-bot",
                            "defaultBranchRef": {
                                "target": {
                                    "history": {
                                        "totalCount": 5
                                    }
                                }
                            }
                        },
                        {
                            "nameWithOwner": "ue-sho/auto_testing",
                            "defaultBranchRef": {
                                "target": {
                                    "history": {
                                        "totalCount": 4
                                    }
                                }
                            }
                        }
                    ]
                }
            }
        }
    }

取得したレスポンスを整形し、SlackのAPIchat.postMessage を使用して自分のチャンネルに通知した。Slack Botの記事は多くあるので割愛します。

コード量はそんな多くないので、詳細をみたい人はリポジトリを見てください!Pythonです( ◠‿◠ )

github.com

AWS Lambda

構成はとても簡素です。なぜLambdaを使ったかと言うと、EC2などに上げるより簡単かつ時間のイベント発火も簡単にできるためです。しかも無料で使える!ところが決め手です。

AWS Lambda の無料利用枠には、1 か月ごとに 100 万件の無料リクエスト、および 40 万 GB-秒のコンピューティング時間が、それぞれ含まれます。 引用: 料金 - AWS Lambda |AWS

f:id:ue-sho:20211003153957p:plain

今回に必要な設定は以下です。

  • Lambda Functionの作成
  • CloudWatch Eventの定義
  • LambdaとCloudWatch Eventの連携

Lambda Functionの作成

コンソール上の「関数を作成」から作る。

  • 関数名をつける (今回は「git-commit-count-bot」(下の画像のサンプルは「test」)という名前をつけた)
  • ランタイムを選択 (今回はPython 3.9)
  • その他はデフォルトでOK

CloudWatch Eventの定義 & 連携

f:id:ue-sho:20211003161014p:plain

上記の画面のトリガーを追加からEventBridge(CloudWatch Event)を選択する。

「新規ルールの作成」を選択して今回は0時にイベントが発火するようにする。 自分はバッチ処理などでよく使われるcronコマンドの方式で設定しました。

UTC(協定世界時) になっており、日本の時刻から-9時間する必要があります。 つまり、cron(0 15 * * ? *) することで、毎日0時にイベントが発火します。

ルールのスケジュール式 - Amazon CloudWatch Events

これにて完成!

最後に

GitHubの草も9月くらいからよく生えるようになりました。

f:id:ue-sho:20211003161717p:plain

この記事はAWS初学者を導く体系的な動画学習サービス AWS CloudTech を参考に作成しました。(AWS関連)

aws-cloud-tech.com