CodeCommitの変更をBacklogの課題に連携

BacklogとCodeCommitを使ってる場合に、CodeCommitへのcommitをBacklogの課題コメントへ反映する方法

※PJT管理ツールや開発管理ツールとCodeCommitの連携方法って探してもまだあまりHitしないので投稿。


## 連携の構成
`1. CodeCommit --> 2. Lambda --> 3. Backlog API`

CodeCommitのイベントをLambdaで拾い、BacklogのAPIで課題コメントの追加をします。


### 1. CodeCommitのコミットコメント

　Backlogの課題番号（プロジェクト名－連番）を含めた形でコミットコメントを記入します。
　Lambda内でコミットコメントを解析するのでルール化したほうが良い。
　
　今回は以下のようなルールとしてます。
<pre>
課題番号1,課題番号2[改行]
コメントコメントコメントコメント	
</pre>　カンマ区切りで複数課題に紐づけられるようにルール付けします。


### 2. Lambdaの作成
自分がlambda初心者なのでここから細かくいきます。

　1.Lambdaの作成
![1_lambda_create1.png](https://qiita-image-store.s3.amazonaws.com/0/241566/f712b530-9fe9-9763-3277-e6e20eb71e45.png)
　　

　2.ロールの作成
![2_lambda_role.png](https://qiita-image-store.s3.amazonaws.com/0/241566/c4bdedb2-57da-1959-22fe-d7b4be47c4f7.png)

![3_role_create.png](https://qiita-image-store.s3.amazonaws.com/0/241566/c6bfbfca-87a8-db00-37e8-f35b394abb5f.png)

![4_lambda_role2.png](https://qiita-image-store.s3.amazonaws.com/0/241566/41bd74e9-ac1c-a264-0bad-9f843022c04d.png)
　
　3.コード作成
![4_lambda_create3.png](https://qiita-image-store.s3.amazonaws.com/0/241566/01718059-37bf-a25a-a172-9e4a52d85bca.png)

　　コードを書く
<pre>
const aws = require('aws-sdk');
const codecommit = new aws.CodeCommit({ apiVersion: '2015-04-13' });

const querystring = require('querystring');
const http = require('https');
const url = require('url');

const backlog_endPoint = process.env.BACKLOG_ENDPOINT;
const backlog_apiKey = process.env.BACKLOG_API_KEY;

const codeCommit_consoleUrl = "console.aws.amazon.com/codecommit/home";

function postComment(issueKey, commitMessage) {
        // Backlog APIの課題コメント追加のURLを生成
        const endpoint = backlog_endPoint + '/issues/' + issueKey + '/comments' 
            + '?apiKey=' + backlog_apiKey;

        const req_opts = url.parse(endpoint);
        req_opts.method = 'POST';
        req_opts.headers = {'Content-Type': 'application/x-www-form-urlencoded'};

        const req =
            http.request(
                req_opts,
                (res) => {
                    if (!(res.statusCode == 200) && !(res.statusCode == 201)) {
                        console.log('error, status: ' + res.statusCode);
                        res.on('data', (chunk) => {
                            console.log('BODY: ' + chunk);
                        });
                    }
                }
            )
        ;
        req.on('error', (error) => {
          console.log('probrem with request: ' + error.message);
        });
        
        const postData = querystring.stringify({
            content: commitMessage,
            notifiedUserId: [],
            attachmentId: []
        });

        req.write(postData);
        req.end();  
}

exports.handler = function(event, context) {
    console.log("Request JSON: " + JSON.stringify(event), null, "    ");

    const repositoryName = event.Records[0].eventSourceARN.split(":")[5];
    const region = event.Records[0].eventSourceARN.split(":")[3];
    const references = event.Records[0].codecommit.references;

    for(let reference of references) { 
        let params = {
            commitId: reference.commit,
            repositoryName: repositoryName
        };
        
        codecommit.getCommit(params, function(err, commitInfo) {
            if (err) {
                console.log(err, err.stack);
            } else {
                // コミットコメントから課題番号を抽出
                let issueKeys = commitInfo.commit.message.replace(/\r?\n/g, ":").split(":")[0].replace(/\s+/g, "").split(",");
                for(let issueKey of issueKeys) { 
                    let diffUrl = "https://" + region + "." + codeCommit_consoleUrl + 
                        "?region=" + region + '#/repository/' + repositoryName + "/commit/" + commitInfo.commit.commitId;
                    // Backlogへ連携するコメントの編集
                    let commitMessage = 
                        "CodeCommit Push通知<br/>" +
                        "<br/>&ensp;・Committer : " + commitInfo.commit.committer.name +
                        "<br/>&ensp;・Repository : " + repositoryName +
                        "<br/>&ensp;・Reference : " + reference.ref +
                        // Markdown記法
                        "<br/>&ensp;・CommitId : " + "[" + commitInfo.commit.commitId + "](" + diffUrl + ")" +
                        "<br/>&ensp;・Message : " + commitInfo.commit.message
                    ;
                    postComment(issueKey, commitMessage);    
                }
            }
        });
    }
};
</pre>

　4.トリガーの設定
![5_Lambda_edit1.png](https://qiita-image-store.s3.amazonaws.com/0/241566/d1a068f6-3a45-8781-1228-489b2ec69367.png)

![6_Lambda.png](https://qiita-image-store.s3.amazonaws.com/0/241566/55db6f20-f4c3-e50e-5747-2b0c3f22f61b.png)

![7_Lambda.png](https://qiita-image-store.s3.amazonaws.com/0/241566/079b72f1-191b-3002-2933-5dc6e2b829e2.png)

　　再度、左側のリストからCodeCommitを選択すれば複数リポジトリも設定できる
![8_Lambda.png](https://qiita-image-store.s3.amazonaws.com/0/241566/f6167d72-c69b-1987-24b0-8f9ab2015110.png)

![9_Lambda.png](https://qiita-image-store.s3.amazonaws.com/0/241566/47523f50-18e1-b01b-f72e-4ec0a90e144b.png)

　　トリガーを設定するとCodeCommit側からも確認できる
![10_CodeCommit.png](https://qiita-image-store.s3.amazonaws.com/0/241566/7f0a97ae-9401-6069-b4cb-6535fe79ab95.png)

　5.ポリシーの追加
　　IAMコンソールからロールにCodeCommit関連のポリシーをアタッチする
<img src=https://qiita-image-store.s3.amazonaws.com/0/241566/39673bec-fca7-a5e5-44e5-4a2d47fd73df.png "11_IAM.png" width=100% >

![12_IAM.png](https://qiita-image-store.s3.amazonaws.com/0/241566/612ed1cd-5340-8386-4a84-af5e596529f5.png)
　　イベントを拾うだけなのでReadOnlyポリシーで十分

![13_Lambda.png](https://qiita-image-store.s3.amazonaws.com/0/241566/a3d5afc0-c9dd-f8ed-75cc-a9886135526d.png)

　6.BacklogのAPIキーの設定
　　Backlog側でAPIキーを発行する。
　　[Backlogを使いこなそう (APIキーの設定)](https://backlog.com/ja/help/usersguide/personal-settings/userguide2378/)
　　
　　その際、APIキーはユーザに紐づいており、課題コメントを登録する際もそのユーザアカウントで登録されるので専用ユーザを作成したほうがわかりやすい。

![15_Lambda.png](https://qiita-image-store.s3.amazonaws.com/0/241566/0e8ba0eb-378c-92c7-73e4-32ecce41b7bc.png)
　　発行したAPIキーとエンドポイントをLanbdaの環境変数に設定する。
　　エンドポイントは `https://[スペース名].backlog.com/api/v2` でOK

　7.Lambdaの動作確認
　　CodeCommitからトリガーのテスト
![16_CodeCommit.png](https://qiita-image-store.s3.amazonaws.com/0/241566/ecc443b0-9278-e7f5-ba6f-23666ba2e4b1.png)

　　Lambdaでテストイベントを作成してテスト
![17_Lambda.png](https://qiita-image-store.s3.amazonaws.com/0/241566/ae49dd4d-002d-0087-f925-d823dcb2b75d.png)
![18_Lambda.png](https://qiita-image-store.s3.amazonaws.com/0/241566/7426fd00-820c-a5b8-724d-924699cdb54f.png)
![19_Lambda.png](https://qiita-image-store.s3.amazonaws.com/0/241566/fe8cfe01-3f08-21c3-1fd4-f925c0772cc5.png)


### 3. Backlog API
　Lambdaテストイベントの結果をBacklog側で確認してみる。
![21_Backlog.png](https://qiita-image-store.s3.amazonaws.com/0/241566/e9cdbcd7-0903-1c15-4178-a62a4c846167.png)
　コメント内のCommitIdからCodeCommitコンソールのコミットDiffへリンクさせてる。

![22_CodeCommit.png](https://qiita-image-store.s3.amazonaws.com/0/241566/732c6063-062f-0f32-f2ee-a47b59dde817.png)
　
　
　
#### 展望
- BacklogはAPIから課題更新できるので課題操作もできそう。
[Backlog 小技集： Gitのコミットから課題の状態を更新する](https://nulab-inc.com/ja/blog/backlog/backlog-tips-5/)
- CodeCommitのプルリクエストのイベントを拾えるのか未検証
- Lanbdaを使うのでBacklog以外でもAPI連携機能があれば流用できるはず。

　
#### 参考記事
- [[GithubとBacklogの連携] Backlogでissue管理して、Githubへのコミット内容をBacklogにも反映させる様に連携する方法](https://qiita.com/colorrabbit/items/5cdadc55996e89e4a4c4)
- [LambdaとAPIGatewayを使ってgitbucketでのcommitをbacklogに送る方法](https://qiita.com/AkihiroTakamura/items/64ec209ab953e5d578e4)