CodePipelineを使わずに、GitHubEnterprice→CodeBuild→CodeDeploy(Blue Green Deploy)のCICDフローを構築した(その1)

# *この記事はこんな人におすすめ*
<br>

* オンプレ環境のGHEからAWS上にソースコードを取得し、CICD環境を構築したい人
* CodePipelineを使いたくない人 or GitHubEnterpriseに対してのアクセスを、会社のセキュリティ上単一IPで絞っているため使えない等の理由で使えない人
* CodeBuildとCodeDeployだけでCICD環境を構築したい人
* buildspec.ymlからCodeDeployを実行したい人
* CodeBuildの実行起因を細かく設定したい人

# 構成
* その1：CodeBuildとGithub Enterpriseの連携(本記事)
* その2：buildspec.ymlとECS、ECR、CodeDeployの設定(後日記載します)

# はじめに
CodeCommitの新規顧客の受け入れが停止されるという[悲報](https://aws.amazon.com/jp/blogs/news/how-to-migrate-your-aws-codecommit-repository-to-another-git-provider/)が届いたのは記憶に新しいですよね。勤務先のソースコード管理ツールは、CodeCommit or GitHub Enterpriseのほぼ2択で、CodeCommitが新規で使えなくなった今、GitHub Enterpriseしか選択肢がなくなってしまいました。事業の関係上セキュリティが厳しく、GHEのIPの穴あけをできるかぎり最小限(/32)にする必要があります。そういう背景もあり、なるべくGHEをAWS上のCICDのフローに組み込みたくはなかったのですが、上記の理由によりやむ追えなくなりました。この記事ではCodePipelineを使わずに、CodeBuildとCodeDeployのみで、GitHubEnterpriseへのpush起因で動くCICD環境の構築方法を記載していきます。


# CICDフロー構成図
![名称未設定ファイル.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3656226/3eca4a09-94ce-33fb-35ae-9568aed24899.png)

### CICDフローの説明

1. GitHub Enterpriseへのpush起因(特定ブランチマージ起因とかでも可)で、Webhookが動作し、CodeBuildを実行します
2. CodeBuildはbuildspec.ymlを参照し、プライベートサブネット内にEC2を立ててGHEからコードをプル、ビルドを行います
3. ビルド後、作成したコンテナをECRにpushします
4. CodeDeployを起動し、S3にあるappspec.jsonを参照しCodeDeployの詳細設定を行います。CodeDeployはECRのlatestを参照しECS上にブルーグリーンデプロイを行います


# この構成にした理由
2点理由があり、

* IPの穴あけが1つだけで済むから
* 無駄なCodePipelineを作らずに済むから

です。

1点目に関しては、CodeBuildをプライベートサブネットで立つEC2にてビルドするように設定することで、GHEにアクセスするIPアドレスが常にNat Gatewayのelastic IPに固定できるからです。
2点目に関しては、CodePipelineでソースを取得しようとすると、毎回AWSのIPレンジの中でIPが変化してしまう。無理やりCodePipelineを使おうとすると、ソース部分にダミーのソースを設定する必要があります....
それならわざわざCodePipeline作る意味ないよねってことでCodePipelineは使わない方針でCICDフローを作成しました。

# 構築方法
### GitHub Enterprise上の設定

1. GitHub Enterpriseに行き、自分のアイコンをクリック
2. Setting→Developer Settings→Personal access tokens (classic)を選択(注：classicじゃないとAWSと連携できません)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3656226/43a1a979-affa-b0b5-507a-17aca0605b36.png)
3. Repoだけ選択し、有効期限を設定、Noteにわかりやすい名前を入力し作成
4. 作成後の画面に表示されるTokenをコピーしてメモっておきます(あとで使用します)
5. Secret Managerにて画像のように入力してTokenを保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3656226/462c8031-f432-fe52-b981-71a2eb218cb7.png)


### CodeBuildの設定

1. AWSのCodeBuildコンソールに移動し、プロジェクトを作成
2. 下記を参考に設定項目を設定
3. 下記表の項目を設定したのちビルドプロジェクトを作成するを押下
4. ウェブフックの作成というホップアップが出てくるので、ペイロードのURLとシークレットをコピーします

| 設定項目 | 設定値 | 補足 |
|:------| :----- | :---- |
| プロジェクト名　| 任意の名前を入力 | |
| パブリックビルドアクセス |チェックしません | |
| ビルドバッチを有効にする |チェックしません | |
|同期ビルド制限の有効化|チェックしません|元々アカウントの制限は20個なので特に意識しなくて良いです|
| **ソース** | ---- | ---- |
| ソース1 | GitHub Enterprise |  |
| 認証情報 | カスタムソース認証情報 | |
| 認証情報タイプ| 個人用アクセストークン | |
| 接続 | 先ほどSecret Managerに保存した認証情報を選択 | |
|リポジトリ|GitHub Enterpriseアカウントのリポジトリを選択| |
|リポジトリのURL|CICDに組み込みたいレポジトリのURLを記載||
|追加設定なし|||
| **プライマリソースのウェブフックイベント** | ---- | ---- |
|ウェブフック|コードの変更がこのレポジトリにプッシュされるたびに再構築する||
|ビルドタイプ|単一ビルドを選択||
|**フィルタグループ1**|---|---|
|イベントタイプ||※1で説明|
|これらの条件でビルドを開始する||※1で説明|
|これらの条件でビルドを開始しない||※1で説明|
|**環境**|---|---|
|プロビジョニング|オンデマンドを選択||
|環境イメージ|マネージド型イメージを選択||
|コンピューティング|EC2||
|オペレーティングシステム|Amazon Linux||
|ランタイム|Standard||
|イメージ|最新のを選択||
|サービスロール|常に最新のイメージを使用してください||
|**追加設定**|----|----|
|特権付与|チェックする|コンテナをCodeBuildでビルドする場合は特権付与が必要です|
|証明書||証明書を使う場合は設定|
|VPC|EC2を起動するVPCを選択||
|サブネット|プライベートサブネットを選択|IP固定のためにNATを経由するプライベートサブネットでEC2を起動するようにします|
|セキュリティグループ|CodeBuildのビルドのEC2にアタッチする使用するセキュリティグループを選択||
|コンピューティング|最適なスペックを選択||
|**Buildspec**|----|----|
|ビルド仕様|buildspecファイルを使用するをチェックします||
|Buildspec名|buildspec.yml|レポジトリにあるBuildspec.ymlの場所を指定。左記だとレポジトリ直下にbuildspec.ymlを置いています|
|**バッチ設定、アーティファクト、ログの設定**||必要であればします|
|**サービスロールのアクセス許可**|||
|サービスロール|CodeBuildにアタッチするロールを選択||
|AWS CodeBuildにこのサービスロールの編集を許可し、このビルドプロジェクトでの使用を可能にします|チェックする||

### ※1 CodeBuildのトリガーを詳細に設定できます
#### 主なイベントタイプ
何をトリガーにCodeBuildを起動するか設定できます。
| PULL_REQUEST_CREATED |プルリクエスト作成時 |
| ---- | ---- |
|push|プッシュ起因|
| PULL_REQUEST_UPDATE | プルリクエストアップデート時 |
| PULL_REQUEST_REOPEN | プルリクエスト再オープン時 |
| PULL_REQUEST_MERGED | プルリクエストマージ時 |
| PULL_REQUEST_UPDATE | プルリクエストアップデート時 |
| PULL_REQUEST_ClOSED | プルリクエストクローズ時 |

#### これらの条件でビルドを開始する/これらの条件でビルドを開始しない
→HEAD_REFとBASE_REFでビルドが動くプルリクエストの条件を詳細に設定できます。
HEAD_REFに^refs/heads/sandbox$、
BASE_REFに^refs/heads/main$を設定すれば、sandboxからmainのプルリクに置いて、イベントタイプで設定した条件でCodeBuildを動かすように設定できます。


### Githubのwebhookの設定

1. 連携させるレポジトリに行きます
2. setting→hooksをおしてhooks登録画面に移行します(下記図)
3. 先ほどコピーしたペイロードのURLとシークレットをペーストします
4. Send me everythingを選択します
5. add webhookを押下しwebhookを作成します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3656226/9fd17e58-3140-2813-7fbc-258e68df562a.png)


以上で、イベントタイプで設定した条件を満たした時に、CodeBuildがレポジトリのbuildspec.ymlを読み込んで、立ち上がるように設定できます。注意点はbuildspecに記載する際、他サービスにCodeBuildがアクセス等するときは、CodeBuildにアタッチするロールに対して他サービスの権限を付与してあげる必要があります。そうしてあげないとCodeBuildがコマンドを実行し、他サービスを動かす際に権限不足で動かせなくなってしまいます。