TOP>コラム一覧>CodePipeline と CodeBuild で開発のスタイルに合わせた CI/CD 環境を実現する ~ Pipeline のトリガー編 ~

CodePipeline と CodeBuild で開発のスタイルに合わせた CI/CD 環境を実現する ~ Pipeline のトリガー編 ~

はじめに

こんにちは、Build サービスでソリューションアーキテクトをしている丸山です。

私が普段業務で携わるソフトウェア開発の現場ではプログラムのソースコードを Git を使ってバージョン管理することが多く、開発/リリースを円滑に進めていくにあたり Git のブランチ戦略と CI/CD 環境も事前に関係者と合意を取って進めています。

Git のブランチ戦略には今回ご紹介する Git-flow 以外にも GitHub flow、 GitLab flow などいくつか種類がありますので興味を持っていただけましたら詳しく調べていただければと思います。

今回は、Git-flow というブランチ戦略を AWS の Code シリーズを使って実現する例を使って、Pipeline のトリガー条件について解説します。

Git-flow とは?

まず、Git-flow について簡単に説明をします。

Git-flow とは Git を使って開発をする場合のブランチ戦略の一つです。
下記に Git-flow での各ブランチの流れを図示します。


こちらの図は下記のサイトを参考に、一部表現を変えて記載させていただきました。

出典: https://nvie.com/posts/a-successful-git-branching-model/

上記では main、 develop が名前が予め決まっているブランチ、それ以外のものが必要に応じて作成/削除が繰り返し行われるブランチです。
ブランチとは `目的ごとに作成された作業スペース` と捉えていただけると理解が進みやすいのではないかと思います。

全てを説明すると長くなってしまいますので、main、 develop、 feature ブランチに絞ってそれぞれの用途を整理します。

  • main ブランチ
    プロダクトとしてリリースするソースコードを管理するためのスペース
  • develop ブランチ
    開発が終わった機能を管理しておくためのスペース
  • feature ブランチ
    機能開発を行うためのスペース
    作業開始時に外時点の develop ブランチから分岐して作成する
    開発/テスト/レビューが完了したら develop ブランチに merge する

このようにそれぞれのブランチは用途が明確に分かれており、ブランチで行った変更は merge というソースコードを合流させる作業をしない限りはそれぞれのブランチで独立して存在しているため、複数の開発者が同時に作業をしていても作業時点では競合が発生せずに開発を進めることができます。

アジャイル開発では機能を小さな単位に分けて短期間で開発を進めていきますので、feature ブランチを使った機能開発が頻繁に発生することになります。

私の担当したアジャイル開発案件では 1 人の開発者が 1 つの機能を担当して順次開発を行っておりましたので、それぞれの開発者は自分自身が担当になっている機能を feature ブランチを各自で作成して開発していました。

Git-flow で必要になる CI/CD の機能

Git-flow の流れについて説明しましたが、 Git-flow に従って開発を進めて行く場合にどのような CI/CD の機能が必要となるのか、まず CI/CD のフローを考えてみます。

個々の機能開発で使われる feature ブランチは図の一番上の flow です。
各開発者は develop ブランチから作業用の feature ブランチを作成し、そのブランチ上で機能開発を行いながら必要なユニットテストなども書いて行きます。
これを Git のリポジトリに Push した際には build、 test、 deploy などの作業が必要になります。

feature ブランチでの機能開発が完了したものは develop ブランチに merge されることになります。
このときにも build、 test、 deploy の作業が必要となります。

最後にリリース時に使用することになる main ブランチですが、こちらは develop から release branch を介して merge と tag 付けがされたときに build、 test、 deploy が必要となってきます。

これらのワークフローを手動で実施することもできなくはありませんが、アジャイル開発のように開発/テスト/リリースを短い期間で繰り返す (私の携わった案件では 2 週間) ような状況を考えると、手動でこれらのワークフローを回すのは現実的ではないと思われます。

CodePipeline のトリガーに CodeBuild を使用する

さて、いよいよ AWS サービスの出番がやってきました。

AWS には Code シリーズと呼ばれるツールがあり、それらを適切に組み合わせる事により開発に関連するワークフローの自動実行環境を構築することが可能になります。

Code シリーズには下記のようなサービスが存在しておりますが、今回は CodeBuild と CodePipeline を連携させる例をご紹介します。

  • CodeCommit
  • CodeArtifact
  • CodeBuild
  • CodeDeploy
  • CodePipeline

それぞれの詳細なサービス説明は公式のドキュメントに記載がありますので、今回は Git-flow の仕組みを実現させるために必要な特徴に絞ってご紹介します。

ご紹介する例の全体の構成図です。

今回はソースコードリポジトリとして GitHub を使い、Pipeline のトリガーのために CodeBuild と S3 Event Notification などを組み合わせ、ワークフローは Pipeline で実行する例となっています。

まずワークフロー全体をオーケストレーションする CodePipeline ですが、ビルド、テスト、デプロイに関連する様々な処理をどのような順番、並列度で行うかなどを設定することができ、Pipeline の処理状況が AWS Management Console 上でわかりやすく可視化されます。

指定できる処理の中には手動承認フローも存在しており、例えば本番環境にデプロイする前には責任者が内容や状況を確認して許可を出すまではデプロイを待機する、といったことも可能です。

以下が Pipeline を Management Console で見たときの例です。今回は Pipeline トリガーに関する説明なので簡素化のため Pipeline 内部は Unit test と Manual Approval のみのワークフロー構成となっておりますが、実際にはこれ以外にも CodeDeploy、 CloudFormation を使った処理など、実際の開発/テスト/デプロイ戦略に従って必要な処理を追加して使用していくことになります。

ワークフローは CodePipeline を使って定義することにしましたが、ワークフローの実行開始の条件を指定しなければ毎回手動で実行することになってしまいます。

Pipeline の実行トリガーとなる処理は Source Action と呼ばれ、ECR、 S3、 CodeCommit、 CodeStarConnection(BitBucket、 GitHub) などが指定可能です。

それぞれのサービスで Source Action を定義する際の設定値については下記のアクション構造リファレンス (公式ドキュメント) に記載がありますのでそちらをご確認ください。

https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/action-reference.html

以下に CodePipeline で GitHub を CodeStartConnection 経由で使用する場合の CloudFormation 設定の一部を掲載します。

※ この記事では Pipeline V1 について解説しています。2024 年 2 月現在、Pipeline V2 を使用している場合は Git の tag に基づいたトリガーは可能になっています。

Stages:
  - Name: "Source"
    Actions:
      - Name: "Fetch"
        ActionTypeId:
          Category: "Source"
          Owner: "AWS"
          Version: "1"
          Provider: "CodeStarSourceConnection"
        Configuration:
          ConnectionArn: "CodeStar connection の ARN"
          FullRepositoryId: "GitHub のリポジトリ名"
          BranchName: "ブランチ名"

詳しい設定値については下記の公式ドキュメントをご確認ください。

https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/action-reference-CodestarConnectionSource.html#action-reference-CodestarConnectionSource-type

この設定で注目すべきポイントは Configuration 以下で設定される `FullRepositoryId` と `BranchName` です。

FullRepositoryId は GitHub のリポジトリが保管されている場所を表すもので、`〈GitHub ユーザ名 または Organization 名〉/〈リポジトリ名〉`というような形でリポジトリの所有者とリポジトリ名を合わせたものを設定します。

BranchName は変更検知を行う Git のブランチ名を指しており、例えば develop ブランチへの Push をトリガーにワークフロー起動する場合は `develop` と指定をします。

ここで改めて Git-flow で使われるブランチを思い出してみます。

  • main ブランチ
    プロダクトとしてリリースするソースコードを管理するためのスペース
  • develop ブランチ
    開発が終わった機能を管理しておくためのスペース
  • feature ブランチ
    機能開発を行うためのスペース
    作業開始時に外時点の develop ブランチから分岐して作成する
    開発/テスト/レビューが完了したら develop ブランチに merge する

main、 develop については最初からブランチ名は明確なので CodePipeline でトリガーすることができそうですが、毎回名前が変更される feature ブランチへの対応は難しそうです。

※ CodePipeline の設定で指定する BranchName にワイルドカードは使えませんので、例えば feature ブランチの名前には `feat-` という prefix を付けるという運用を取り入れたとしても BranchName で `feat-*` という指定をすることはできません。

また、CodeCommit や GitHub など Git のマネージドサービスを利用した開発をする場合、ソースコードのレビュー時に Pull Request (追加した変更の差分を可視化して確認する機能) を使う場合が多いと思いますが、CodePipeline 単体ですと Pull Request をトリガーとしてワークフローを起動することができないため何らかの工夫が必要になってきます。

CodePipeline だけで解決が難しいのであれば、他のサービスを組み合わせて解決しようというのが今回のアプローチです。
今回は Webhook によるトリガーを使用する際に条件を柔軟に設定可能な CodeBuild を使用してみようと思います。

先程の CodePipeline 例と同様に CloudFormation 設定値で CodeBuild の設定も確認してみます。

以下は `feature ブランチへの Push イベントのみをトリガーに処理を開始する` という条件を実現するために必要な CodeBuild の Project 設定の一部です。

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

CodeBuild の GitHub Webhook 連携に関する詳しい仕様について下記の公式ドキュメントをを参照ください。

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/github-webhook.html

CodeBuild の Webhook 設定には FilterGroup というものが存在しており、これを指定することでどのような条件のときにトリガーするのか (ExcludeMatchedPattern が false の設定)、またはどのような条件のときはトリガーしないのか (ExcludeMatchedPattern が true の設定) を設定することができます。

上記では 4 件の条件が指定されておりますが、これらを日本語で記載すると以下のような意味になります。

  • Event が PUSH (GitHub へのソースコードの Push) である場合に実行する
  • ただし、ブランチが main である場合は実行しない
  • ただし、ブランチが develop である場合は実行しない
  • ただし、tag の push である場合は実行しない

これら FilterGroup の条件を合わせて評価すると main、 develop 以外のブランチ、すなわち feature ブランチへの Push に対して処理がトリガーされることになりますので、CodePipeline 単体では実現できなかったトリガーを実現することができました。
(今回単純化のため hot-fix や release ブランチについては考慮しておりません)

まとめ

今回は Git のブランチ戦略の一つである Git-flow を題材として、CodePipeline と CodeBuild の実行トリガーの違いについて解説しました。

CodePipeline は開発からリリースまでの様々な作業をワークフローとして定義/可視化することが魅力ですが、ワークフローの起動条件が要件にマッチせず採用できなかったという方や、運用でカバーされている方もいらっしゃるのではないかと思います。

Management Console 上のボタン 1 クリックで簡単にできあがるような仕組みではありませんが、今回のように CodeBuild を CodePipeline の前段で使用することでトリガー条件を柔軟に設定することができるようになり、開発のサイクルにあった CI/CD パイプラインを構築できるようになると思いますので参考にしていただければ幸いです。

今回紹介した CodeBuild と CodePipeline 組み合わせる例以外にも、具体的なソースコードを掲載しながら AWS のサービスの使い方や案件で得た知見などを Build サービスの note にて公開しています。興味のある方はこちらの記事もご覧いただければ幸いです。

CTCは、AWSのビジネス利活用に向けて、お客様のステージに合わせた幅広い構築・運用支援サービスを提供しています。
経験豊富なエンジニアが、ワンストップかつ柔軟にご支援します。
ぜひ、お気軽にお問い合わせください。

Build サービス note 「Build の AWS ナレッジ通信」

https://note.com/build_service/m/m8220a76aed15

関連サービス

https://www.ctc-g.co.jp/solutions/build_sales/

お問い合わせ



【著者プロフィール】

丸山 貴嗣(まるやま たかし)

伊藤忠テクノソリューションズ株式会社 ソリューションアーキテクト

自社 Cloud サービスの企画開発からプログラマーに転向し、モバイルアプリ、Web アプリ、API 開発など様々な開発プロジェクトに従事。 現在は Build サービスのソリューションアーキテクトとして Cloud を活用したシステム/アプリの設計/開発の領域で活動中。

丸山 貴嗣(まるやま たかし)

TOP>コラム一覧>CodePipeline と CodeBuild で開発のスタイルに合わせた CI/CD 環境を実現する ~ Pipeline のトリガー編 ~

pagetop