CodeCommitのプルリクエストをTeamsに通知する

前回の内容の応用です。
https://qiita.com/aocm/items/0eced705bde216b17919
※Teamsの通知の下準備の方法や、その他のチャットツールにプルリクエストを通知したい人は参考にしてください。

## はじめに
とつぜんわいた疑問
**CodeCommitって通知とばせないの？**

「GithubにしろGitlabはメールとか届いてくれるんだけれどCodeCommitはなんか無いのだろうか。」
「チャットでいちいち伝えるの流れちゃいそう」
「実はいろいろ不便じゃないか？」

そんな声が上がり、不便で終わらせるのももったいない気がするので
なにかできることはないかと考えた結果、「とりあえずプルリクエストをTeamsで飛ばすぞ！」となりました。

もっとうまいやり方に心当たりある方はコメントいただけるととっても嬉しいです。

## 概要
CodeCommitの特定のイベント（コメント、プルリクエストの作成）をTeamsに通知する。
サンプルプログラムと使い方（仕込み方）をこの記事に書きます。

### 対象読者
- 同じような疑問が湧いた人
- CodeCommitのトリガーをもとになにかやりたい人
- AWS Lambdaのコードサンプルが見たい人

## 準備
1. AWSアカウントの準備(今回は持ち合わせのアカウントのを利用するので、初めて作る方は別の記事を参考にしてください)
2. サンプルのリポジトリを作成（すでに通知を飛ばしたいリポジトリがあればそれで大丈夫です。作り直す必要はありません。）
3. 通知したいTeamsのチャネルとWebhookURLの準備（もしくは他の通知したいチャットツールの下準備）

今回はサンプルリポジトリなので、手動で作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/7b0d273b-43e8-d072-0824-7bba2753897b.png)

適当なファイルを追加しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/1fa0e56a-fa51-b548-c0cd-c0355e3425dc.png)

## 通知するために仕込む
### 流れ
1. ローカルでソースコードを準備
2. CodeCommitのリポジトリに通知ルールを作成
3. Lambdaを作成

### 1. ローカルでソースコードを準備
macでやっていますが、なんでも大丈夫です。何ならnode_modulesごと(.gitignoreで除外せずに)Githubに公開しておくので、こちらのようにZipでダウンロードして2に進んでも大丈夫です。
https://github.com/aocm/lambda-codecommit-notify

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/2aa1b882-8327-ed39-1b6c-28cccad06e70.png)



```
% mkdir lambda-codecommit-notify
% cd lambda-codecommit-notify 
% git init
略
% npm init
略
```

lambda用のhandlerとTeamsに通知するためのfunctionを並べたindex.jsを作ります。
作ったものがこちら

```javascript:index.js
const axios = require('axios')
const url = process.env.TEAMS_URL 

exports.handler = async (event, context) => {
    const response = {
        statusCode: 200,
        body: 'codecommitのイベントをTeamsに通知しました',
    }
    
    let message = ""
    console.log("event ... ", event)
    console.log("Sns ... ", event.Records[0].Sns)
    try{
      // ★地味にハマりどころ。MessageにはCodeCommitからの情報が入るらしく、ここでJSON.parseする必要がある。
      let SnsMessageObj =JSON.parse(event.Records[0].Sns.Message)
      switch (SnsMessageObj.detailType) {
        case 'CodeCommit Pull Request State Change':
          message = pullRequestMessage(SnsMessageObj)
          break;
        case 'CodeCommit Comment on Pull Request':
          message = pullRequestCommentsMessage(SnsMessageObj)
          break;
          default: 
          message = `PR#${SnsMessageObj.detail.pullRequestId} 不明な通知です`
      }
      await teamsPost(message, url)

    } catch (e) {
      console.log(e)
      await teamsPost("CodeCommitNotifyが失敗しました", url)
    }
    return response
}

/** プルリク時のメッセージ形成 */
function pullRequestMessage(SnsMessageObj){
  let repositoryName = SnsMessageObj.detail.repositoryNames
  let prId = SnsMessageObj.detail.pullRequestId
  let title = SnsMessageObj.detail.title
  let pullRequestStatus = SnsMessageObj.detail.pullRequestStatus
  let from = SnsMessageObj.detail.sourceReference
  let to = SnsMessageObj.detail.destinationReference
  let body = SnsMessageObj.detail.notificationBody

  let message = 
    `${repositoryName}：PR#${prId} "${title}" is ${pullRequestStatus}  \n` + 
    `${from} → ${to}  \n` + 
    `${body}`
 return message
}
/** コメント時のメッセージ */
function pullRequestCommentsMessage(SnsMessageObj){
  let message =''
  let repositoryName = SnsMessageObj.detail.repositoryName
  let prId = SnsMessageObj.detail.pullRequestId
  let file = SnsMessageObj.additionalAttributes.filePath
  if (SnsMessageObj.additionalAttributes.commentedLine){
    let lineMessage = SnsMessageObj.additionalAttributes.commentedLine
    let lineNum = SnsMessageObj.additionalAttributes.commentedLineNumber
    message = `${repositoryName}：PR#${prId} ${file}:${lineNum}行目( ${lineMessage} )に対して新しいコメントがあります。`
  } else {
    message = `${repositoryName}：PR#${prId} ファイル：${file}に対して新しいコメントがあります。`
  }
  
 return message
}

/**
 * Teamsに通知する
 * @param {*} message 投稿するメッセージ
 * @param {*} teams_url Incoming WebhookのURL
 */
async function teamsPost (message, teams_url){
  try{
    const url = teams_url
    const text = message
    await axios(
      {
        method: 'post',
        url,
        headers: {
          'Content-Type': 'application/json',
        },
        data: {
          "type": "message",
          "text": text
      },
    }).then(response => {
        console.log('res:', response.data)
    }).catch(error => {
        console.log(error)
    })
  }catch(e){
    console.log(e)
  }
}
```

つくったディレクトリごとZipに固めます。（やり方はなんでも。）

### 2. CodeCommitのリポジトリに通知ルールを作成
CodeCommitの通知を指定したいリポジトリを開き、左メニューの「設定」を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/decf0f88-cb13-10c7-bbe3-c0132976c431.png)


通知ルールの作成をおします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/c0ecf992-e7a3-11ba-858b-93cf1ae075a3.png)

すると以下のような画面になるので、通知をトリガーするイベントに必要なチェックをいれ、
ターゲットの作成からSNSトピックを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/93a3d4e0-6570-7d96-378c-7676464d9380.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/346c73d1-322e-6d04-8750-5d50cdab959e.png)
Submitしたら以下のような画面になります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/ea3e2dc7-9543-4b13-10a6-c65dae775ba8.png)


### 3. Lambdaを作成
以下のように作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/aad867d0-57a9-9bc0-d7d6-5e98dafc0a00.png)
すると、このような状態になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/05e137c7-3c72-e32b-d999-81a830f15e61.png)

「トリガーを追加」から、先程つくった通知ルール（SNS）を登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/13d07d19-47a5-919f-0c86-5bea8124eb76.png)

### 4. Lambdaに用意したZipファイルをアップロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/de7c5943-0905-d31c-0883-49b7866b58c0.png)

zipファイルをそのままアップロードすると、階層が一つ深くなってしまうので右図のように修正します。

<img width="300" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/965f43da-dbd6-7a49-fdfc-9c3a262dbb5a.png"><img width="300" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/841266f3-dd8d-ce29-40e2-19633fad5885.png">

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/c0c64bed-454b-d964-baa9-abd4778320c6.png)
環境変数の「TEAMS_URL」を設定して「デプロイ」ボタンを押したら完成です。
※TEAMS_URLにはTeamsのWebhookのURLを設定してください。くわしくは[前回の記事](https://qiita.com/aocm/items/0eced705bde216b17919)にて


## 動作確認
プルリクエストをつくってみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/936fe204-2a1a-5115-3711-adb68174b6a1.png)
以下のメッセージが届いていました！大丈夫そうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417134/4e70a057-8208-bf84-e644-a7cc7d2c7e05.png)


## おわりに
突貫工事で作ってみたのですが、何もないよりかはマシだなと思いました。
よければ参考にしてください。