CodeBuild で Pull Request や不特定のブランチへの Push をトリガーとして CI する方法
前回は CodePipeline の使いやすい点、使いにくい箇所の紹介を行いました。
使いにくい点として挙げたのは下記の 2 点です。
Pull Request をトリガーとして指定できない
ブランチ指定なので feature ブランチなど、一時的に生成されるブランチの CI をトリガーできない
今回はこれらのに対して現時点ではどのように対処できるかを紹介します。
CodeBuild で Pull Request Trigger を実現する
CodePipeline には Pull Request や不特定のブランチに対する Push に対応する設定がないことが分かっていますので、CI/CD でよく使われる CodeBuild の CloudFormation template の reference から `Triggers` に設定する内容を確認してみます。ProjectTriggers -> FilterGroup -> WebhookFilter と辿ると下記のドキュメントにたどり着きます。
CodeBuild を起動するための手段はこのドキュメントからもわかるように CodePipeline より充実しており Pull Request にも対応できそうなことがわかります。
上記のドキュメントから設定する必要がある項目について転記します。(YAML で記載します)
ExcludeMatchedPattern: Boolean
Pattern: String
Type: String
今回の例では `Pull Request をトリガー` とするため、Type は `EVENT` となります。先程のドキュメントを見て頂ければわかりますが、EVENT 以外にも値を設定することができるため、特定のブランチや tag などをトリガーとして設定することもできます。
Pull Request に話を戻すと、次は Pattern です。こちらに関しても設定値に関する説明は先程の CloudFormation template のドキュメントに記載されており、大体は EVENT 名で想像はつくと思いますが、どの GitHub イベントが対応しているのかは下記のドキュメントを見るとより詳細に確認することができます。
https://docs.aws.amazon.com/codebuild/latest/userguide/github-webhook.html
これらのドキュメントを参考にすると Pull Request に関連するトリガーの CloudFormation 設定は下記のように作ることができます。
Type: AWS::CodeBuild::Project
Properties:
Triggers:
Webhook: true
FilterGroups:
- Type: EVENT
Pattern: "PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED, PULL_REQUEST_REOPENED"
ExcludeMatchedPattern: false
上記の設定の場合、Pull Request の 作成/更新/リオープン 時にこの CodeBuild のプロジェクトがトリガーされることになり、もともと CodePipeline では不便なポイントとして挙げていた
Pull Request をトリガーとして指定できない
という点は解消できたことになります。
CodeBuild で Feature branch への Push を検出する
次に 2 点目の不便なポイントとして挙げていた
CodePipeline はブランチ指定なので feature ブランチなど、一時的に生成されるブランチの CI をトリガーできない
こちらについてですが、先程のドキュメントを確認すると、EVENT の Pattern で指定できる値に `PUSH` というものが存在していることがわかります。この `PUSH` イベントは、GitHub でソースコードを Push したときのイベントに紐付けられるため、先程と同様に FilterGroups を下記のように設定することで、不特定多数のブランチで、ソースコードの Push をトリガーに処理を実行することができるようになります。
Type: AWS::CodeBuild::Project
Properties:
Triggers:
Webhook: true
FilterGroups:
- Type: EVENT
Pattern: "PUSH"
ExcludeMatchedPattern: false
ただし、上記の設定の場合は全ての Push のイベントでトリガーされてしまうので、stable な branch への Push は除外する必要がある場合などは、下記のように FilterGroups に追記します。
Type: AWS::CodeBuild::Project
Properties:
Triggers:
Webhook: true
FilterGroups:
- - Type: EVENT
Pattern: "PUSH"
ExcludeMatchedPattern: false
- Type: HEAD_REF
Pattern: "^refs/heads/main$"
ExcludeMatchedPattern: true
- Type: HEAD_REF
Pattern: "^refs/heads/develop$"
ExcludeMatchedPattern: true
- Type: HEAD_REF
Pattern: "^refs/tags/.*"
ExcludeMatchedPattern: true
今回、main と develop ブランチが stable なブランチ (Git-flow を想定) として想定しているので、 Type に `HEAD_REF` を指定、Pattern に該当のブランチを指定し、`ExcludeMatchedPattern` を true に設定することで指定したブランチをトリガー条件から除外します。また、同様に Tag の Push もトリガー条件から除外しておきます。
以上の設定により `Feature ブランチへの Push のみをトリガーとして CI を起動する` ことができるようになりました。
まとめ
今回は、CodePipeline では実現できなかった
feature ブランチなど、一時的に生成されるブランチの CI をトリガーできない
Pull Request をトリガーとして指定できない
これらを CodeBuild で実現する方法を CloudFormation の template を使って説明しました。
例えばユニットテストを実行するだけなど、やることがシンプルであれば今回紹介したように CodeBuild で必要な処理を実行し、結果を GitHub やチャットツールなどに通知することで開発中に CI の失敗にすぐに気づけるようになるため効率的な開発が可能になります。
しかし、ユニットテスト以外にも例えば AWS リソースの更新やアプリケーションのデプロイ、インテグレーションテストを実行するなど複数の step が存在する場合、ワークフローの途中に手動承認をはさみたい場合などは CodePipeline が向いていると思いますので、次回は CodeBuild から CodePipeline に連携する方法を紹介したいと思います。
今回の記事の中で紹介した CloudFormation の template は下記の GitHub リポジトリで公開しています。
https://github.com/t-maru078/code-build-github-trigger