LINE NotifyでCodeCommitコミット時の通知を設定してみた

# はじめに
LINE NotifyでCodeCommitへのコミット時の通知をカスタムメッセージでLINEグループに送信するよう設定してみました。業務ではLINEを使う機会がほぼないですが、個人開発時にはLINE通知の方が色々と便利だと思って、導入してみたというのがきっかけでした。

# やりたいこと
構成は非常にシンプルです。
1. CodeCommitにコードをpushする
1. コミット通知がSNS経由でLambdaに送信される
1. Lambda関数でユーザーのLINE Notifyトークンを使い、コミット情報をnotify-apiのエンドポイントにpostリクエストを送信する
1. コミット情報がLINE Notifyの公式アカウントによって、特定のLINEグループに送信される

![Screenshot 2022-12-22 at 17.30.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/fbb8edf1-5583-7de6-61ac-9d242f0c6929.png)



ちなみに、以前LINEグループにメッセージを送信する際にMessaging APIを使っていましたが、グループIDを取得するのにWebhookを使ってイベントの通知を受ける必要があって、すこし面倒だったので、今回はLINE Notifyでやってみました。

# 事前準備
## LINEグループの作成
グループに通知を送信したいので、まずdemo用のグループ「line-notify-demo」を作成しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/82956a52-e979-5fd3-749b-61df7b1b4e1b.png)

グループ通知の場合はLINE Notifyの公式アカウントをグループに追加する必要があります。
![Screenshot 2022-12-22 at 13.22.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/6e909781-abe1-7626-f749-0cb0f86a0c65.png)

## LINE Notifyトークン取得
以下の手順でトークンを取得します。
1. [LINE Notify公式サイト](https://notify-bot.line.me/ja/)からLineアカウントでログインする
1. 「マイページ」をクリックする
![Screenshot 2022-12-22 at 13.13.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/330b7a86-2aa1-6764-c88a-d583efa3c7e5.png)
1. 「トークンを発行する」をクリックする
![Screenshot 2022-12-22 at 13.15.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/d4b20ac9-1bd4-4982-ef00-2e75d55bd39f.png)
1. トークン名を入力し、送信したいグループを選択し、「発行する」をクリックする
![Screenshot 2022-12-22 at 13.28.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/dcda5af4-2f3c-c5be-522b-5357805d986f.png)
1. トークンは再表示できないので、メモしておく
![Screenshot 2022-12-22 at 13.28.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/479b38fa-b033-6635-7d8b-b96d3ee60bca.png)


## CodeCommitリポジトリの作成と通知の設定
「line-notify-demo」という名前でCodeCommitリポジトリを作成しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/d7a39ac7-c349-f40f-2f4a-36ce56b0b90f.png)

リポジトリの設定から、通知ルールを作成します。
![Screenshot 2022-12-22 at 17.38.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/04791cd2-3dee-c1f5-0b8f-120e8b33943c.png)
内容に応じてトリガーイベントを選択可能ですが、今回はBranches and tagsのCreatedとUpdatedを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/be7f67ad-6d95-e138-20cf-fc53eaea0946.png)


SNSトピックを新規作成します。
![Screenshot 2022-12-22 at 17.39.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/8e3ede1f-3335-4354-1910-2af1c42da47d.png)



# SSMパラメータの作成
LINE NotifyトークンをSSMパラメータストアにSecureStringで保存します。必要に応じてSecrets Managerも利用可能です。
パラメータ名に「line-notify-token」と入力し、「安全な文字列」を選択します。KMSキーはCMKを選択しますので、未作成の場合は事前作成が必要です。値のところに上記LINE Notifyトークン取得手順でメモした値を入力します。
![Screenshot 2022-12-22 at 21.07.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/4c17e2ed-9a12-43b1-f815-9d0db80ecb6c.png)



# Lambda関数の作成
## IAMロールとポリシーの作成
まずLambda用のIAMロールとポリシーを作成します。
CloudWatchロググループの作成、ログの出力、SSMパラメータの取得、KMSキーを使った復号、CodeCommitコミット情報取得の権限を付与します。
- ロール名：line-notify-demo-lambda-role
- ポリシー名：line-notify-demo-lambda-policy
`xxxxxxxxxxxx`のところはご自身のAWSアカウントIDに置き換えてください。kms:Decryptで許可するリソースは、ご自身の`KMSキーのARN`に置き換えてください。また本demoでは`ap-northeast-1`リージョンを使っています。
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:ap-northeast-1:xxxxxxxxxxxx:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:ap-northeast-1:xxxxxxxxxxxx:log-group:/aws/lambda/line-notify-demo-lambda:*"
        },
        {
            "Effect": "Allow",
            "Action": "ssm:GetParameters",
            "Resource": "arn:aws:ssm:ap-northeast-1:xxxxxxxxxxxx:parameter/line-notify-token"
        },
        {
            "Effect": "Allow",
            "Action": "kms:Decrypt",
            "Resource": "arn:aws:kms:ap-northeast-1:xxxxxxxxxxxx:key/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        },
        {
            "Effect": "Allow",
            "Action": "codecommit:GetCommit",
            "Resource": "arn:aws:codecommit:ap-northeast-1:xxxxxxxxxxxx:line-notify-demo"
        }
    ]
}
```
## Lambda関数の作成
次にLambda関数を作成します。
「line-notify-demo-lambda」という関数名にします。今回はPythonでコードを作成しますので、「Python3.9」を選択します。アクセス権限で「既存のロールを使用する」を選択し、上記手順で作成した「line-notify-demo-lambda-role」を選択します。
![Screenshot 2022-12-22 at 14.48.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/37176307-059b-1eda-2b3b-9fa48df95b86.png)
![Screenshot 2022-12-22 at 14.48.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/7654f4ef-fc0c-bba2-83c6-195fa02a067d.png)




## レイヤーの作成
requestsというpythonのライブラリを使いますので、Lambdaのレイヤーとして設定しておきます。以下のコマンドで該当ライブラリをダウンロードして、ZIP化します。

```bash
$ pip3 install -t python requests
$ zip -r9 layer.zip python
```

名前を入力し、上記手順で作成したZIPファイルをアップロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/a84fe50c-a827-24db-e32c-8e8cad6253eb.png)

「line-notify-demo-lambda」のLambda関数に戻って、Lambda関数の設定画面からレイヤーを追加します。上記手順で作成したレイヤーのARNを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/9fe3789e-f7e6-c904-965d-b0019d6becb9.png)



## 環境変数の設定
Lambda関数の設定画面から以下の環境変数を追加します。PARAM_KEYは上記SSMパラメータの作成手順で作成したパラメータ名です。URLは固有のAPIエンドポイントになります。
- PARAM_KEY: line-notify-token
- REGION: ap-northeast-1
- URL: https://notify-api.line.me/api/notify
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/462713f0-0c2b-69fe-d014-82f9dad0ea54.png)



## トリガーの設定
Lambda関数の設定画面からトリガーを追加します。ソースをSNSに指定し、事前準備の通知ルール作成で作成したSNSトピックを選択します。
![Screenshot 2022-12-22 at 17.59.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/e4dde891-bb98-4842-85af-53841619c8c2.png)


# コードの作成 
ソースコードを書いていきます。
ポイントは以下になります。
- LINE NotifyトークンをSSMパラメータストアから取得する
- SNSから送られたイベントからIAMユーザー、コミットID、ブランチを取得する
- コミッター、コミットメッセージはSNSから送られたイベントに存在しないため、コミットIDをもとにcodecommitのGetCommit APIで取得する
- 取得したIAMユーザー、コミットID、ブランチ、コミッター、コミットメッセージをもとに通知用メッセージを作成し、LINE NotifyのAPIエンドポイントに対してpostリクエストを送信する

出来上がったコードは下記の通りです。
```python:lambda_function.py
import os
import json

import boto3
import requests


REGION = os.environ["REGION"]
PARAM_KEY = os.environ["PARAM_KEY"]
URL = os.environ["URL"]
CODECOMMIT = boto3.client("codecommit")


def get_parameters(param_key):
    """SSMパラメータストアからtokenを取得

    :param param_key: SSMパラメータの名前
    :type: str 
    :returns: SSMパラメータの値
    :type: str  
    """
    ssm = boto3.client("ssm", region_name=REGION)
    response = ssm.get_parameters(
        Names=[
            param_key,
        ],
        WithDecryption=True
    )
    return response["Parameters"][0]["Value"]


def get_commit_info(event):
    """IAMユーザー、コミットID、ブランチ、コミッター、コミットメッセージを取得

    :param event: snsから送信されたpayload
    :type: dict
    :returns: IAMユーザー、コミットID、ブランチ、コミッター、コミットメッセージを格納したdict 
    :type: dict   
    """
    sns_info = event["Records"][0]["Sns"]
    sns_info["Message"] = json.loads(sns_info["Message"])
    sns_info = sns_info["Message"]["detail"]

    commit_info = CODECOMMIT.get_commit(
        repositoryName=sns_info["repositoryName"],
        commitId=sns_info["commitId"]
    )
    commit_info_dict = {
        "iam_user": sns_info["callerUserArn"],
        "commit_id": sns_info["commitId"],
        "branch": sns_info["referenceName"],
        "committer": commit_info["commit"]["author"]["name"],
        "commit_message": commit_info["commit"]["message"],
    }

    return commit_info_dict


def lambda_handler(event, context):
    token = get_parameters(PARAM_KEY)
    headers = {"Authorization": f"Bearer {token}"}
    commit_info_dict = get_commit_info(event)
    data = "\n"

    for key in commit_info_dict:
        data += f"{key}: {commit_info_dict[key]}\n"

    payload = {"message": data.encode("utf-8")}
    requests.post(URL, headers=headers, data=payload)

```
コードをデプロイします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/d83fdc3a-0220-8061-5b89-d9d49d6ac4ad.png)

# 動作確認
では動作確認してみます。ローカルリポジトからpushする場合はCodeCommitのSSHキーかHTTPS Git認証情報が必要なので、今回はブラウザからリポジトリにファイルを作成し、コミットすることにします。
![Screenshot 2022-12-22 at 18.14.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/6ef827e9-b87c-d098-f1d5-416146d3864f.png)

コミットすると
![Screenshot 2022-12-22 at 18.49.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/c235dbd1-980c-47dc-9946-dedf9b34f51c.png)


通知が来ましたね！