LoginSignup
1
0

More than 3 years have passed since last update.

CodeCommitにcommit/pushしたらLambda経由でSlackにcommentつき通知を飛ばす

Last updated at Posted at 2020-07-03

AWS CodeCommit上で管理しているリポジトリに、誰かがcommit/pushしたらSlackで通知を受け取りたいと思って試行錯誤したときのメモになります。Lamda関数はNode.jsで記述しています。

スクリーンショット

screenshot.jpg

※ アイコンとCodeCommitの太字はSlack Incomming Webhookのカスタマイズで変更しています。

前置き

  • CodeCommitやLamda、Slackの細かい話は書きません。
  • Lamda関数のNode.jsのサンプルコードや注意点だけを書きます。
  • 以下はすべてAWS Console上からの操作です。

処理の流れ

CodeCommit → トリガー → Lambda → Slack Incomming WebhookのURLにPOST → Slackからスマホアプリ等に通知が飛ぶ

Lamda関数

適当な名前でLamda関数を作成します。以下のサンプルコードをindex.jsに上書きします。optionsのIncomming WebhookのURLと、中程にあるSlack上に表示するメッセージのBlock Kitテンプレートはお好みに合わせて修正します。

codeCommitToSlackWebhook
const AWS = require('aws-sdk');
const codecommit = new AWS.CodeCommit({
    region: 'ap-northeast-1'
});
const https = require('https');
//const util = require("util");
const options = {
    hostname: 'hooks.slack.com',
    path: '/services/*******/*******/*******',
    method: 'POST',
    headers: {
        "Accept" : "application/json",
        "Content-Type" : "application/json; charset=UTF-8"
    }
};

exports.handler = function(event, context) {
    let repository = event.Records[0].eventSourceARN.split(":")[5];
    let references = event.Records[0].codecommit.references;
    let funcArr = references.map((x) => {
        return new Promise((resolve,reject) => {
            let params = {
                commitId: x.commit,
                repositoryName: repository
            };
            codecommit.getCommit(params, function(err, data) {
                if (err) reject(err);
                else resolve({params:params,data:data});
            });
        });
    });
    Promise.all(funcArr)
        .then((values) => {
            //console.log(util.inspect({
            //  values:values
            //},{colors:true, depth: null}));
            return new Promise((resolve,reject) => {
                let blocks = [];
                blocks.push({
                    type: 'section',
                    text: {
                        type: 'mrkdwn',
                        text: `new commit pushed to \`${references[0].ref}\`\n\n*Repository:* "${repository}"`,
                    }
                });
                let v = values.map((x) => {
                    let tmp = new Date(x.data.commit.committer.date.split(' ')[0]*1000);
                    tmp = `${tmp.getFullYear()}/${('0'+(tmp.getMonth()+1)).slice(-2)}/${('0'+tmp.getDate()).slice(-2)} ${('0'+tmp.getHours()).slice(-2)}:${('0'+tmp.getMinutes()).slice(-2)}:${('0'+tmp.getSeconds()).slice(-2)}`;
                    return {
                        type: 'section',
                        fields: [
                            {
                                type: 'mrkdwn',
                                text: '*CommitId:*\n'+x.params.commitId
                            },
                            {
                                type: 'mrkdwn',
                                text: '*Comment:*\n'+x.data.commit.message
                            },
                            {
                                type: 'mrkdwn',
                                text: '*Committer:*\n'+x.data.commit.committer.name
                            },
                            {
                                type: 'mrkdwn',
                                text: '*When:*\n'+tmp
                            }
                        ]
                    };
                });
                values = {blocks:blocks.concat(v)};
                resolve(values);
            });
        }).then((value) => {
            //console.log(util.inspect({
            //  value:value
            //},{colors:true, depth: null}));
            let req = https.request(options, (res) => {
                let body = '';
                //console.log('statusCode: '+res.statusCode);
                res.setEncoding('utf8');
                res.on('data', (chunk) => {
                    body += chunk;
                });
                res.on('end',() => {
                    //console.log({body:body});
                    context.done(null,body);
                });
            });
            req.on('error',(e) => {
                //console.log({e:e});
                context.fail(e);
            });
            req.write(JSON.stringify(value));
            req.end();
        }).catch((err) => {
            //console.log({err:err});
            context.fail(err);
        });
};

Lambdaのアクセス権限

  1. Lambda アクセス権 → 実行ロール → IAMロールの設定が別ウィンドウで開く
  2. 「ポリシーをアタッチします」でAWSCodeCommitReadOnlyをアタッチ

Lambdaのトリガー

  1. Lambda 設定 → デザイナー → トリガーの追加
  2. トリガーの設定 → CodeCommitを選択
  3. リポジトリ名選択、トリガー名にslackWebhookTriggerなど入力、ブランチ名をすべてのブランチを選択
  4. 追加

通知のテスト

  1. CodeCommit リポジトリ選択
  2. 設定 → トリガー → slackWebhookTriggerなどトリガー名のリンク
  3. ページ下部 → トリガーのテスト

Lambdaの注意点

環境変数を設定しないと通知内容に含まれる時刻がUTCになってしまいます。以下を設定します。

  • Lambda 設定 → 環境変数 → キー: TZ、値: Asia/Tokyoを追加

デバッグ

Lambda関数内のconsole.logのコメントアウトを外し、CloudWatch Logsでどこでエラーが発生しているか確認します。

参考URL

例: AWS Lambda 関数の AWS CodeCommit トリガーを作成する
https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/how-to-notify-lambda.html

以上です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0