lycheejam's tech log

チラ裏のメモ帳 | プログラミングは苦手、インフラが得意なつもり。

AWS CodeBuildのビルド結果をLambdaを使ってLINEへ通知する

概要

タイトルの通りAWS CodeBuildのビルドステータスをCloudWatchと使って監視し
イベントを検知したらLambdaを起動し自身のLINEへビルド結果を通知します。
トークに返信して自動で再ビルド実行とかは組み込んでません。純粋にビルド結果の通知です。

世間じゃSlackに通知とかなんでしょうがこちとらぼっちの個人開発なんでSlackなんぞ使ってません。
LINEに通知が来てくれたほうが気付きやすいんです。

こんな感じになります。

f:id:HM_Atlas:20190414162326p:plain

目次

参考サイト様

成果物

環境構成

下記画像の赤枠部分を実装します。

f:id:HM_Atlas:20190414153819p:plain

処理的にはざっくり以下の流れです。

  1. CloudWatchでイベントを定義しCodeBuildのビルドを監視
  2. CloudWatchがイベントを検知するとLambda関数を起動
  3. Lambda関数からLINE API ServerへAPIを叩く
  4. LINE BOTから自身のLINEアカウントへ通知

作業手順と注意事項

この手順は、AWS CodeBuildのビルドプロジェクトが作成済みであることを前提としています。
また、LINE Developersへの登録を含め使用するのは初めてです。

作業手順のを軽く整理します。

  • LINE Developersでの作業
    • LINE Developersへ登録
    • プロバイダーの作成&チャネルの作成
  • Lambda関数の作成(ローカル)
  • AWSでの作業
    • Lambda関数の作成
    • ローカルで作成したものをLambdaにアップ
    • CloudWatchでイベントの設定
    • テスト

上記の流れで作業します。

LINE Developersに登録&チャネル作成

下記リンクのLINE Developersからユーザ登録してください。

登録が済めばガイドに従ってプロバイダーの作成・チャネルの作成を実施してください。

※チャネルを作成する際はMessage APIを選択すること。

アクセストークン(ロングターム)の発行

最初はアクセストークが発行されていないので「メッセージ送受信設定」の項目にあるアクセストークンの再発行を押下してアクセストークンを入手します。

f:id:HM_Atlas:20190414153846p:plain

赤枠内のチャネルシークレット・アクセストークン(ロングターム)・ユーザIDをこのあとのLambda関数で使用します。

AWS Lambda関数の作成

まず、ローカルでLambda関数を作成しファイルをZipに固めてLambdaにアップロードします。
基本的なコードはSDKのドキュメントで丁寧に解説されているので簡単です。

ローカルでLambda関数を作成

任意の作業ディレクトリを用意してください。
カレントディレクトリは作業ディレクトリとします。

作業ディレクトリにLINE BOTのNode.js向けSDKをインストールします。

$ npm install @line/bot-sdk

インストール完了後、関数を作成しますがどうせなんでHello Worldも紹介しておきます。
不要でしたら読み飛ばしてください。

LambdaでLINE BOTHello World

インストール完了後、任意のエディタでindex.jsを作成してください。
まず、コードを簡素にするためチュートリアル的な基本形を記載します。
これはSDKのドキュメントに記載されているものをLambda向けに編集したものです。

const Client = require('@line/bot-sdk').Client;

exports.handler = (event, context, callback) => {
  //クライアント作成
  let client = new Client({
    channelAccessToken: 'CHANNEL_ACCESS_TOKEN',
    channelSecret: 'CHANNEL_SECRET'
  });

  //トーク送信APIを実行
  client.pushMessage('USER_ID', { type: 'text', text: 'Hello World' });
};

関数内の下記値は各自置き換えてください。

  • CHANNEL_ACCESS_TOKEN = チャネル管理画面のアクセストークン(ロングターム)
  • CHANNEL_SECRET = チャネル管理画面のChannel Secret
  • USER_ID = チャネル管理画面のYour user ID(ページ最下部)

以上が基本形です。

これをAWS上のLambdaにアップロードしてテスト実行するだけでLINEにHello Worldが通知されます。
※チャネル管理画面に表示されているQRコードからLINE BOTを友達追加しておく必要があります。

Lambda関数を結果通知用に編集

先程のHello Worldで使用した関数をCodeBuildの結果通知用に編集します。

  • index.js
const Client = require('@line/bot-sdk').Client;

exports.handler = (event, context, callback) => {
  //①クライアント作成
  let client = new Client({
    //アクセストークン等を環境変数としています。(Lambda内で登録)
    channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
    channelSecret: process.env.CHANNEL_SECRET
  });
  
  //②通知用のメッセージ作成。
  //通知内容にはCloudWatchから渡されるeventの内容を出力します。
  let message = event.time + '\n'
          //ビルドが実行されたプロジェクト名
          + 'プロジェクト名:' + event.detail['project-name'] + '\n'
          //ビルド完了ステータス(成功 or 失敗 or 停止)
          + 'ステータス:' + event.detail['build-status'];

  //③トーク送信APIを実行
  client.pushMessage(process.env.USERID, { type: 'text', text: message });
};

簡単なものなので説明することもあまりありませんが補足的な感じで書いておきます。

①クライアント作成

LINE BOT用のクライアントを作成します。
先程のHello Worldでも記述しましたがアクセストークンなどの値は適宜置き換えてください。

let client = new Client({
  channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
  channelSecret: process.env.CHANNEL_SECRET
});

今回はLambdaで環境変数を登録し、その環境変数をコードに記載しています。
process.env.XXの部分)
環境変数の登録については後述します。

②通知用のメッセージ作成

文字列結合でメッセージを作成します。
CloudWatchで検知されるイベントは成功・失敗・停止の3種類です。
後述しますが、このイベント種類はCloudWatchのイベント作成時に指定します。

let message = event.time + '\n'
            //ビルドが実行されたプロジェクト名
            + 'プロジェクト名:' + event.detail['project-name'] + '\n'
            //ビルド完了ステータス(成功 or 失敗 or 停止)
            + 'ステータス:' + event.detail['build-status'];

CloudWatchから渡されるイベントデータのjsonにハイフンが入っているので面倒な書き方をしています。

トーク送信APIを実行

作成したメッセージを載せてAPIを実行します。

トーク送信先であるユーザIDについてもアクセストークンと同様に環境変数としてLambdaに登録したものを使用します。

AWSコンソールからLambdaで関数の作成&アップロード

AWSの管理コンソールからLambda関数を作成し、先程ローカルで作成した関数をアップロードします。

Lambda関数の作成

Lambdaのダッシュボードから関数を作成します。
ランタイムはnode.jsを選択します。

f:id:HM_Atlas:20190414153932p:plain

ローカルで作成した関数のアップロード

AWSでLambda関数の作成完了後、ローカルで作成した関数をアップロードするためにZIPで固めます。
対象はindex.jsnode_modulesディレクトリです。
(zipファイルの名前は展開されて消えるのでなんでもいいです)

Lambda関数の管理画面から「関数コード(エディターが表示されている部分)」の「コードエントリタイプ」を.zipファイルをアップロードに変更します。
すると、zipファイルがアップロード可能となるので先程固めたzipを選択してアップロードします。
アップロードが完了するとzipが展開され作成した関数がエディタに表示されます。

f:id:HM_Atlas:20190414154001p:plainf:id:HM_Atlas:20190414154004p:plain

環境変数の設定

関数内で使用している下記3つの値をLambdaに環境変数として登録します。

  • CHANNEL_ACCESS_TOKEN = チャネル管理画面のアクセストークン(ロングターム)
  • CHANNEL_SECRET = チャネル管理画面のChannel Secret
  • USER_ID = チャネル管理画面のYour user ID(ページ最下部)

Lambda関数管理画面のエディタ下に「環境変数」と言う項目があるのでLINE Developerで取得した各種値を登録します。
環境変数入力後、画面右上の保存で保存すること

f:id:HM_Atlas:20190414154044p:plain

Lambda関数のDesignerによるトリガーの追加について

Lambda関数のトリガー設定については私の環境(IAMユーザ)では不要でした。
後述するCloudWatchイベントを作成すると自動でトリガーが設定されます。

AWS CloudWatchのイベント設定

上記までのLambda関数の設定が完了したらLambda関数を起動するためのイベントを設定します。

Amazon CloudWatch EventsのトップページからGet startedでイベントを作成します。

下記画像の通りイベントパターンを設定します。

f:id:HM_Atlas:20190414154110p:plainf:id:HM_Atlas:20190414154115p:plainf:id:HM_Atlas:20190414154118p:plain
  • 「イベントパターン」を選択(デフォルト)
    • 「サービス別のイベントに一致するイベントパターンの構築」を選択(デフォルト)
      • サービス名:「CodeBuild」を選択
      • イベントタイプ:「CodeBuild Build State Change」を選択
      • 「特定の状態」を選択
      • CloudWatchで検知するイベントを選択
        • 必要なものを選択してください。

右側のターゲットで先程作成したLambda関数を指定します。
その他の項目はデフォルトのままです。

また、後のテストで使用するために「サンプルイベントの表示」を展開して
サンプルテキストをコピーしてメモ帳にでも貼り付けておいてください。
※これは作成完了後でもイベントの編集画面から確認できます。

ここまで滞りなくすべてうまく行っていればCodeBuildを走らせると結果がLINEに通知されるはずです。
ただバカスカCodeBuildを動かすのももったいないのでLambda関数のテストで本当に動くかテストします。

Lambda関数のテスト

先程コピーしたサンプルイベントのテキストをイベント毎に分割してLambdaのテストとして登録します。
※サンプルのテストデータをGitHubにあげておきました→linebot_cb/tests at master · Lycheejam/linebot_cb

f:id:HM_Atlas:20190414162243p:plainf:id:HM_Atlas:20190414162246p:plain

登録したテストイベントを選択してテストを実行してください。
するとラインに通知が来るはず!

f:id:HM_Atlas:20190414162326p:plain

Lambda関数を一通りテストしたあと、私の場合は反映したいコミットもあったので実際にCodeBuildを動かしました。

雑感

静的サイトジェネレータなのでほぼほぼコケることはありませんが
1つLambda関数作っておけば他のビルドプロジェクトにも使えるので便利そうですね。
通知オンリーで詳細情報とか何もないのでまあアレなんですが...