CodeBuildの実行トリガーに曖昧なブランチ(feature/*)を指定する方法

2021.10.22

いわさです。

Git-flow運用など行うとfeature/hogerelease/piyoなどといったfeatureブランチ、releaseブランチなどが作成されていくと思います。
この運用で「featureブランチはプッシュ時に自動テストやビルド、セキュリティチェックを行う必要がある」という場合で、かつCodeBuildでそれを実現しなければいけない場合、どうしたら良いでしょうか。

先日、以下の記事で、CodeBuildで任意のリポジトリ・ブランチでAWS CLIを使ってビルド実行する方法を紹介しました。
この方法を使うと既存のCodeBuildプロジェクトに対して、動的なソースプロバイダー設定を指定することが出来ます。

今回はこの機能を使って、指定した子ブランチがプッシュされたタイミングでビルドを実行するというワークフローを構築してみます。

実装ですが、EventBridgeで条件に該当するブランチのプッシュを検知した時に、Step FunctionsからCodeBuildを実行するという流れになります。
CodeCommitとCodeBuildのプロジェクトは前回の記事のものを使います。

なお、CodePipelineはパラメーターのオーバーライドが出来ないので今回のアプローチでは実現出来ません。
CodePipelineの場合は以下のようにリポジトリの変更を検出したタイミングでCodePipelineをCloudFormationスタックで都度生成する方法が紹介されています。

CodePipelineに関する情報は匿名で網走の方から頂きました。ありがとうございます。

Step Functions

Workflow StudioにてCodeBuildのStartBuildのアイテムを配置しAPIのパラメータを設定します。

ステートマシン定義は以下となります。
各パラメータは冒頭でご紹介した前回の記事を参考にしていただければと思いますが、SourceVersionは動的にする必要があるので入力パラメータの値を利用しています。

この入力パラメータは、後述のEventBridgeのパラメータを想定しているので、$.detail.referenceNameを指定しています。

{
  "Comment": "This is your state machine",
  "StartAt": "CodeBuild StartBuild",
  "States": {
    "CodeBuild StartBuild": {
      "Type": "Task",
      "Resource": "arn:aws:states:::codebuild:startBuild",
      "Parameters": {
        "ProjectName": "empty-build",
        "SourceTypeOverride": "CODECOMMIT",
        "SourceLocationOverride": "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/hoge-repo",
        "BuildspecOverride": "buildspec.yml",
        "SourceVersion.$": "$.detail.referenceName"
      },
      "End": true
    }
  }
}

今回は、Step Functionsを使ってみましたが、AWS CLI/APIを叩ければ何でも良いのでBoto3なLambdaなどでも良いです。

EventBridge

EventBridgeでは、「指定したリポジトリの条件に該当するブランチがプッシュされた場合」をトリガーにします。
条件部分はコンテンツフィルタリング機能を使うことが出来ます。
今回は「プレフィックスマッチング」で「"feature/"で始まるブランチ名」を指定しましたが、他にも例えば「mainブランチ以外」という指定の仕方も出来ます。
また、カスタムイベントパターンでブランチを指定しなければ、リポジトリにプッシュされたすべてのブランチを対象にすることも出来ます。

{
  "source": ["aws.codecommit"],
  "detail-type": ["CodeCommit Repository State Change"],
  "resources": ["arn:aws:codecommit:ap-northeast-1:123456789023:hoge-repo"],
  "detail": {
    "event": ["referenceCreated", "referenceUpdated"],
    "referenceType": ["branch"],
    "referenceName": [{
      "prefix": "feature/"
    }]
  }
}

ターゲットにStep Functionsステートマシンで、先程作成したものを指定します。

Step Functions側でのブランチ判断も可能ですが、その場合はビルド不要なブランチでもStep Functionsは実行されてしまうので、実行回数を抑制したいのであれば極力EventBridge側で実行抑制出来たほうが良いと思います。
とはいえStep Functionsの実行コストは低い部類だと思いますので想定回数を見積もった上で決めても良いでしょうかね。

なお、EventBridgeではターゲットにCodeBuildを指定することも出来ますが今回の要件(動的なブランチ)では動作しませんでした。
静的な設定でスケジューリング実行する場合などに使うためのものと推測します。

featureブランチを新規作成し動作確認

では、設定が完了したので作成してみましょう。
あらたにfeatureブランチを作成し、リモートプッシュするケースを想定してやってみます。

buildspec.ymlの文言をこのブランチのものだとわかるように変更し、プッシュしました。

iwasa.takahito@hoge hoge-repo % git branch
* develop
  feature/iwasa1
  feature/iwasa2
  main
iwasa.takahito@hoge hoge-repo % git branch feature/iwasa-hoge
iwasa.takahito@hoge hoge-repo % git checkout feature/iwasa-hoge
Switched to branch 'feature/iwasa-hoge'
iwasa.takahito@hoge hoge-repo % vi buildspec.yml 
iwasa.takahito@hoge hoge-repo % git add .
iwasa.takahito@hoge hoge-repo % git commit -m "hogehoge"
[feature/iwasa-hoge 41cb4c0] hogehoge
 1 file changed, 2 insertions(+), 2 deletions(-)
iwasa.takahito@hoge hoge-repo % git push --set-upstream origin feature/iwasa-hoge
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 363 bytes | 363.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/hoge-repo
 * [new branch]      feature/iwasa-hoge -> feature/iwasa-hoge
Branch 'feature/iwasa-hoge' set up to track remote branch 'feature/iwasa-hoge' from 'origin'.

プッシュ後、CodeBuildのビルド履歴を見てみましょう。
ビルド実行が開始されています。

ビルドログを確認し、中身を見てみましょう。

先程作成したブランチのものでビルド実行されていることが確認出来ました。

まとめ

標準のCodeBuildの機能だけでは実現出来ませんでしたが、いくつかのサービスを組み合わせることで実現出来ました。
ただ、これをやるべきかどうかは議論したほうが良いと思います。
ちょっとシンプルじゃなさすぎる気がしますし、特にCodePipelineが担うべき部分をStep Functionsで実現しているのでパイプラインというかワークフローの管理が出来そうかという点でしょうか。

CodeBuild以外は使えない環境下などもあるかもしれませんので、選択肢のひとつとして知っておいたら良いかも、くらいでしょうか。