見出し画像

CodePipeline と CodeBuild を連携する

※この記事については、t_maruさんの許可をいただいて、Buildサービスチームのアカウントにて転載させていただいております

前回は CodeBuild を使って Pull Request や不特定多数のブランチへの Push をトリガーする方法について説明しました。
CodeBuild は柔軟にトリガー条件を設定できる反面、成功失敗以外の状態 (どこまで処理が完了しているのか) を確認するにはログを確認する必要があり、処理の流れや進捗を直感的に把握することが難しいという課題があります。
今回は CodeBuild と CodePipeline を連携することにより、双方のいいとこ取りをした形で feature ブランチのような不特定多数のブランチのコードに対して CI/CD のワークフローを流す方法について考えてみたいと思います。

役割分担をする

冒頭でも書いたように、今回は CodeBuild と CodePipeline のいいとこ取りをするため、それぞれの得意なものは何か改めて書き出してみようと思います。
CodePipeline の良い点

  • ワークフローが可視化され、どこまで処理が実行されているのか直感的に理解できる

CodeBuild の良い点

  • トリガー条件を柔軟に設定できる

これ以外にもそれぞれのサービスでメリットになる事項はあると思いますが、一旦今回の内容にフォーカスすると上記の通りですので、CodeBuild で GitHub への Push をトリガーして、その後 Pipeline でワークフローを実行する形で役割分担する方向で話を進めます。
CodeBuild から CodePipeline への連携ですが、CodePipeline で設定できる Action type を下記の公式ドキュメントを参照して調べてみると、Action category が `Source` の行に `Amazon S3` という表記があることがわかります。
https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#actions-valid-providers
では、上記の資料からリンクされている S3 source action の詳細を確認してみます。
https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-S3.html
こちらを確認すると CodePipeline を CloudFormation template 上で設定する場合の Action type としては下記のような設定がされれば良いことがわかります。

Stages:
  - Name: Source
    Actions:
      - ActionTypeId:
          Category: Source
          Owner: AWS
          Version: "1"
          Provider: S3


Action type の他にも必須のパラメータとなっている Configuration には `S3Bucket` と `S3ObjectKey` があります。
ここまで来ると何がしたいのかわかる方もらっしゃるかもしれませんが、CodeBuild で GitHub への Push イベントをトリガーしコンテナを起動した後、コンテナ上で GitHub からソースコードを取得し、S3 に圧縮して保存。S3 へのファイル保存をトリガーとして CodePipeline を起動させようというのが今回やりたいことです。
CloudFormation template の話に戻すと、必須パラメータも含めると下記のように設定を書くことができます。

Stages:
  - Name: Source
    Actions:
      - ActionTypeId:
          Category: Source
          Owner: AWS
          Version: "1"
          Provider: S3
        Configuration:
          S3Bucket: <S3 バケット名>
          S3ObjectKey: <Object の保存パス or ファイル名>
          PollForSourceChanges: false


必須パラメータでは紹介しませんでしたが、今回は CloudWatch Events と CloudTrail、Lambda を使って S3 ファイルの変更を検出するため、`PollForSourceChanges` の設定は false に設定します。
細かい処理に関してはこの記事の最後にサンプルソースコードの保管先を記載しておりますのでそちらを参考にしていただきたいですが、上記までの設定で CodeBuild -> CodePipeline のつなぎ部分は間に S3 を置くことで連携が可能なことがわかりました。

Build の結果が GitHub 上で確認できるようにする

GitHub と CI ツールを連携して開発を行った経験のある方は、GitHub 上に Build 結果が表示されているのを見たことがある方がいらっしゃるのではないでしょうか?

このように GitHub 上で CI の成功/失敗が可視化されると開発/レビューの際にとても便利だと思います。ただ、この部分に関しても今回のように CodeBuild -> CodePipeline という連携を行う場合、少し工夫が必要になってきます。

上記に、簡単な構成図を示しましたが、処理の流れとしては以下のような順で進んでいきます。
※ 大まかな流れを知っていただくために簡単な説明にとどめています。詳細は本記事最下部のリンクからソースコードを参照してください。

  1. GitHub から webhook の event が飛び CodeBuild が起動される

  2. CodeBuild は GitHub からソースコードを取得し、zip ファイルに圧縮したものを S3 に Put する

  3. CodeBuild は S3 に Put 後、DynamoDB に BuildID と Status を書き込み、定期的に Status を確認

  4. S3 への zip file Put をトリガーに CodePipeline が起動

  5. CodePipeline の execution status 変更を CloudWatch Events Rule が検知して Lambda を起動

  6. Lambda が DynamoDB 上に保管されている Status を更新

  7. CodeBuild は Status に応じて GitHub に 成功/失敗 の結果を返却する

status 反映の部分に関しては今回紹介する方法以外にも、例えば GitHub Apps を使って同様の結果を得る仕組みを作ることもできますが、AWS のリソースをコマンド 1 つでデプロイするだけで使える仕組みを作りたかったため、GitHub への status 反映は 成功/失敗 のみのレガシーな方法ではありますが、あえてこのような作りとしました。
サンプルコードの注意事項にも記載しましたが、この方法を使った場合は Pipeline の処理実行が完了するまで GitHub からの Webhook で起動したコンテナが実行され続けることになるため、テストやビルド時間が長いアプリケーションの CI/CD を実行する場合は CodeBuild の料金がかさむ可能性がありますのでご注意ください。

まとめ

CodeBuild と CodePipeline の良い点を組み合わせることにより、柔軟なトリガーで起動され、処理内容や進捗が視覚的にすぐに分かる CI/CD フローを構築することができました。
前項の最後でも説明しましたとおり、今回はできるだけインフラに関連する設定を自動化したかったので GitHub webhook により起動するコンテナは Pipeline 処理が完了するまで待機させその結果を GitHub に戻すという形を取りましたが、インフラの設定が追加で必要になってもコストを極限まで減らした構成が適切な場合もありますので、用途に応じて適切な構成を考えていただければと思います。
今回の記事の中で紹介した CloudFormation の template は下記の GitHub リポジトリで公開しています。
https://github.com/t-maru078/code-pipeline-github-webhook


みんなにも読んでほしいですか?

オススメした記事はフォロワーのタイムラインに表示されます!