GitHub と AWS CodeBuild を連携させるサーバーレスなツールを作りました [紹介編]

夏休みをゲットしたのでサーバーレスなツールを作ってみました.

前々から気になっていた AWS CodeBuild をさわってみて、不足してるなと感じた部分を補完するツールです.

TL;DR

toricls/github-codebuild-integration | GitHub

どんなものを作ったか

こんなものです.

Overview

説明はいいからとりあえず使ってみたいんだけど、という方は下の方までスクロールしてもらって「とりあえず使ってみたい」セクションをご覧ください.

図の左下からフローが流れ、

  • GitHub リポジトリへの Push/Pull-Request を Webhook で SNS が受け取る
  • CodeBuild のビルドジョブを実行する
  • ジョブの完了を待つ
  • ビルド結果を GitHub Status API で GitHub に記録する
  • GitHub の画面にいい感じでステータスが表示される

という感じでになります. 一連の流れは Serverless なコンポーネント群で構成されています.

以下、いい感じです.

プルリクの画面 プルリクの画面

コミット履歴の画面 コミット履歴の画面

AWS CodeBuild ってなに?

そもそも AWS CodeBuild ってなんですかという方はリンク先をぜひご覧いただきたいんですが、誤解を恐れずに言いますと要は Travis CI や CircleCI がちょっと不器用になった感じの AWS 謹製ビルドサービスです.

ビルドに利用したマシンスペックに応じて分単位でビルドの実行時間に対して課金されるモデルになっているため、そんじょそこらの CI サービスではプランの金額的にためらわれるような並列実行数でブイブイ言わせることができます(と聞いてます)1.
また、プリセットのマシンイメージも用意されてはいますが、自前の Docker イメージを利用したビルドもできるようです.

なぜこのツールを作ったか

1. 現状の AWS Code シリーズ2では Pull Request をサポートできる仕組みがない

例えば「フィーチャーブランチを作成して PR を使ってマージ」という GitHub ユーザーにとって当たり前なワークフローが AWS Code シリーズではできません.
(いろいろ頑張ればできそうな気はしますが、そこまで頑固ならわしゃ CircleCI 使うわい、という感じ)
とは言え Pull Request という概念自体は Git 由来のものではなく GitHub プロプライエタリなものであるため、AWS としても安易にはサポートし難いという気持ちはなんとなく分かります.

2. AWS CodeBuild のジョブの結果を GitHub 側の Protected branches の仕組みと併用したい

GitHub には Protected branches という機能があり、特定のブランチ(例えば master)が壊れることを防ぐための仕組みがあります. この機能を使うと

  • 強制プッシュの禁止
  • レビューされていないブランチからのマージの禁止
  • CI をパスしていないブランチからのマージの禁止

といったことができます.

CI をパスしたかどうかについては GitHub API を利用して GitHub 側に通知できます. AWS CodeBuild 側のジョブ結果をいい感じに GitHub に通知できる仕組みがあれば、AWS CodeBuild を使いながらも GitHub の Protected branches の恩恵をむさぼれる!というわけです.

3. CI 用の AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY の話

これはなぜメジャーな CI サービスではなく AWS CodeBuild を使うのか?の理由の一つでもあります.

CircleCI や Travis CI などのサービスから AWS のサービスを呼び出すためには IAM ユーザーを作成して AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY を発行する必要があります. ニーズの例としては CI サーバー側から S3 へのファイルアップロードや Amazon ECS を通したコンテナのデプロイなどが考えられます. 発行されたキー情報は CI サービスの環境変数などの形で登録して利用することが一般的だと思います.

AWS CodeBuild であれば Build project が利用する IAM ロールに権限を足しておけばいいだけなので、アクセスキーの発行が不要になり、管理方法やローテートについての心配とも無縁になれます.
(このツールでも GitHub から Amazon SNS を呼び出すためにアクセスキーを発行しますが、sns:Publish だけなので許して...!)

(そもそも AWS によるビルドサービスをリクエストした人たちはこの辺りに敏感な企業やプロジェクトの方たちで、EC2 x Jenkins などの形でビルドサーバーを自前運用していたのではないかと推測しています)

4. その他

  • AWS Management Console を開かずに GitHub の画面で CI のステータスが知れると楽
  • AWS CodeBuild なら Amazon ECR (Docker Hub 的なやつ)に配置したカスタム Docker イメージを使ったビルドもやりやすい

などなど.

どんな構成になっているか

使っている AWS のサービスは以下のとおりです.

Amazon S3
AWS SAM で作成されるパッケージの置き場
Amazon SNS
GitHub からの Webhook を受け取る
AWS Lambda
ビジネスロジックは全部ここ
AWS Step Functions
ビルドジョブが終わるのを待ったり、Lambda をいい感じにつないだり分岐したりループしたり
AWS IAM
Lambda から CodeBuild 呼んだりするための IAM ロール、GitHub から SNS を呼び出すための IAM ユーザーなどなど
AWS CloudFormation
上述のサービス群をプロビジョンする
AWS CodeBuild
主役

また、デプロイだったりビルドだったりのためにローカルで使っているツールが以下のとおりです.

GNU Make
ローカルで使うコマンドの取りまとめ役
Node.js
Lambda~
Yarn
依存解決、テスト実行など
AWS-CLI
デプロイスクリプトの中から CloudFormation の API 蹴ったりとか
curl
ユーザーに設定してもらう GitHub Personal Access Token が要件を満たしているかのバリデーション

とりあえず使ってみたい

具体的な手順は README.md#Installation にありますが、ざっくりと以下の流れで使えるようになります.

  1. まずは AWS CodeBuild に Build project を一つ作成します. Build project の設定で Source providerGitHub を選ぶとご自身が所有するリポジトリが読み込まれますので、ビルドしたいリポジトリを選んでください
    これ含めてコマンド一発でデプロイできるようになってるとかっこいいですが、実際のところアプリケーションによって必要なマシンイメージは異なるため、このツールの機能スコープからは外しました
  2. S3 バケットを一つ作ります
  3. toricls/github-codebuild-integration をローカルにクローンします
  4. GitHub の Personal Access Token を発行します. 必要なスコープは admin:repo_hookrepo:status です. 発行されたトークンは次に作成する設定ファイルの中に記述します.
  5. サンプルの設定ファイル(env/example.env)をコピーして自分用の設定ファイルを作ります
  6. デプロイ!

デプロイが完了したら全ての準備が整います. 指定した GitHub リポジトリにプッシュすると AWS CodeBuild を使ったビルドが実行され、GitHub へのステータスのセットも行われます :)

FAQ

Q. なんで SNS なの? Webhook 使うなら API Gateway じゃないの?

A. 僕も最初はそう思ってましたが、無防備な API Gateway を作って放置するほどハートが強くないので、GitHub が IAM 権限を利用して Webhook を飛ばしてくれる SNS を利用しました. 同じく GitHub がネイティブでサポートしている AWS サービスとして SQS もありますが、こちらも Lambda でのロングポーリングとかが必要になったりなんだったりと何かと無理をする構成になるので見送りました.

使う際に困りそうなことは README.md#FAQ に書いてみましたのであわせてご覧ください.

今後

先々やりたいなーと思っていることは GitHub Issues にちょこちょこあげていってるので、もし機能リクエストとか不具合とかあったら気兼ねなくご連絡ください :)

開発時に工夫したこととか困ったこととかについても触れる予定だったんですが、長くなったので次の記事で書こうと思います.

2017.08.28 追記: 中身の話を書きました!


  1. builderscon tokyo 2017 での @ssig33 さんによるセッション『Amazon CodeBuild でテストをめっちゃ並列実行する話(スライド) が楽しかったです. セッション概要と動画は builderscon 公式サイト内で公開されているようです. [return]
  2. AWS CodeBuild 以外にもいろんな Code なんとかシリーズがあります. Git リポジトリの AWS CodeCommit、デプロイツールの AWS CodeDeploy、CI/CD パイプラインの AWS CodePipeline、これらをとりまとめるプロジェクト管理ツール的な AWS CodeStar、などなど. [return]