GitHub WebhooksとAWS Lambdaを連携してデプロイとSlack通知を同時に行う


はじめに

プルリクがdevelopブランチにマージされたとき、ステージング環境へのデプロイとSlack通知を同時に行う機能を以下の構成(GitHub Webhooks, Slack Incomming Webhooks, API Gateway, Lambda, OpsWorks)で実装しました。

各設定についてまとめましたので、参考にしていただければ幸いです(OpsWorksの設定については記載しません)。

*Webhookとは、Webサービスがサービス内で起こったイベントをトリガーに、所定のURLにパラメータを渡してコールしてくれる機能です。

実施事項

1. SlackのIncoming Webhooksで通知先のチャンネルを登録し、Webhook URLを発行する。
2. Lambdaの関数コードにOpsWorksの自動デプロイとSlack通知の内容を記述する。
3. API Gatewayでエンドポイントの発行とLambdaの登録を行う。
4. GitHubのWebhooksでGitプッシュイベントが起こったときのエンドポイントにAPI Gatewayを指定する。

Slack Incomming Webhooksの設定

SlackのアプリケーションからIncomming Webhooksを選択します。
投稿したいチャンネルを選択してIncomming Webhookインテグレーションの追加を押します。

Webhook URLを控えます。Lambdaの関数コードで通知先を指定するときに使用します。

名前やアイコンのカスタマイズを行なって設定を保存します。

Lambda関数の作成

AWS Lambdaで関数の作成をクリックします。
関数名を入力して、既存のロール(lambda_basic_execution)をアタッチし、関数を作成します。

以下の画面になるので、関数コードに実行したい内容を記述します。

Slackへの送信内容についての記述はこちらのサイトを参考にしました。
ここでSlack Incomming Webhooksの設定で取得したWebhook URLを記述します。

 let options = {
    host: "hooks.slack.com",
    path: "[Webhook URLのパス]",
    port: 443,
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
  };

また、postDataについてもカスタマイズしました。

        fields: [
          {
            title: "Webhook Repository",
            value: repo,
            short: true,
          },
          {
            title: "Repository Branch",
            value: branch,
            short: true,
          },
          {
            title: "OpsWorks Stack",
            value: stack,
            short: true,
          },
        ],
        footer: "Pushed by " + uname,

デプロイするソースコードのリポジトリとブランチをStackId、StackName、AppIdと紐付けます。

var deployMap = {
  '[リポジトリ名]': {
    "refs/heads/[ブランチ名]": {
      StackId: '[StackId]',
      StackName: '[StackName]',
      AppId: '[AppId]',
    }
  },
};

以下でデプロイとSlack通知を実行します。
eventはGitプッシュ時にGitHub Webhooksから取得されるデータとなります。

var opsworks = new aws.OpsWorks();

exports.handler = async (event, context, callback) => {
                      .
                      .
                      .
    const data = await opsworks.createDeployment(params).promise();

    let message = "デプロイするよ〜〜〜!!!";
    let repo    = event.repository.name;
    let branch  = event.ref;
    let stack   = deployMap[event.repository.name].StackName;
    let uname   = event.pusher.name;
    let log_url = '[log出力先URL]' + params.StackId + '/deployments/' + data.DeploymentId;

    await postToSlack( message, repo, branch, stack, uname, log_url );

API Gatewayの設定

API GatewayでGitHubでのプッシュイベントのPOST先のエンドポイント(WEB APIを利用するときのURI)を作成します。

リソースの作成を行います。

POSTメソッドを作成しLambda関数の名前を入力して保存します。

最後にリソースのアクションでAPIのデプロイを実行してエンドポイントを作成します。
ステージでURLが作成されたことを確認することができます。

GitHub Webhooksの設定

リポジトリのSettings→WebhooksからAdd webhookを押します。

Webhooksの設定をします。
Payload URLには前工程で作成したエンドポイントのURLを入力し、Content typeにはapplication/jsonを選択します。

おわりに

以上の設定を行うことで、デプロイと同時にこんな感じでSlackに通知を飛ばすことができます。
LambdaとAPI Gatewayを使ったのは初めてだったので勉強になりました。