JenkinsとGitLabとAWS CodeBuildを連携する

# はじめに

JenkinsからAWS CodeBuild Plugin経由でビルドを実行しCIを実行する手順を以下にまとめます。
AWS CodeBuildはAWSが提供しているビルドサービスで、buildspec.ymlを設定すると指定したコンテナ上で処理を実行してくれます。

https://aws.amazon.com/jp/codebuild/

AWS CodeBuildはGitHubやGitBucketからは直接webhookで連携することができますが、残念ながらGitLabは対応していないため、Jenkinsとプラグインを経由して実行するようにします。

# 前提

Jenkins、GitLabがAWS上に構築されていてそれぞれお互いに連携可能な状態であることを前提とします。
JenkinsとGitLabの連携については[こちら](https://qiita.com/takamii228/items/a0f4b2ef8107d6d3cd34)をご参照ください。

# AWS CodeBuildを設定する

「ビルドプロジェクトを作成する」を選択してビルドプロジェクト作成画面へ遷移します。

以下の内容を設定します。

* プロジェクト名
  * GitLabのレポジトリ名と同じものがわかりやすくてよいでしょう
* ソース:ビルドの対象
  * 現在のソース : GitHub Enterprise(GitLabだけど)
  * レポジトリのURL : GitLabのレポジトリのURL
  * Gitクローンの深さ : 1
  * webhook : チェックを入れても入れなくてもGitLabの場合は何もおきません
  * ブランチフィルタ : 空欄のまま（正規表現が記入できるらしい）
  * Insecure SSL : 空欄のまま（SSLチェックを飛ばしたい場合はチェック）
  * セカンダリソース : 空欄のまま
* 環境:ビルド方法
  * 環境イメージ : AWS CodeBuildによって管理されたイメージの利用 or Dockerイメージの指定を選択※
    * 「AWS CodeBuildによって管理されたイメージの利用」の場合
      * AWS CodeBuildでデフォルトで用意されている以下のイメージを使ってビルドを実行します
        * OS : Ubuntu
        * Runtime : .NET Core, Android, Base, Docker, Golang, Java, Node.js, PHP, Python, Ruby
    * 「Dockerイメージの指定」の場合
      * 環境タイプ : Linux
      * カスタムイメージタイプ : Amazon ECR
      * Amazon ECR レポジトリ : ECRに登録したレポジトリを選択
    * 特権付与 : 空欄のまま
  * ビルド仕様 : ソースコードのルートディレクトリのbuildspec.ymlを使用
  * buildspec名 : buildspec.yml 
* アーティファクト
  * タイプ : S3 
  * 名前 : アーティファクトの名前
  * パス : アーティファクトのファイル名のパス
  * 名前空間のタイプ : artifactの前の命名規則を定義することができます（例 : MyPath/MyBuildID/MyArtifact.zip）
  * バケット名 : S3のロールを付与するバケットを選択する。プロジェクト設定保存時に選択したバケットに自動でAWS CodeBuildのロールが付与されます。
  * アーティファクトのパッケージ化 : Zipするか選べます
  * アーティファクトの暗号化を無効化 : 暗号化を無効化できます
  * セカンダリアーティファクト : 2つ目以降のアーティファクトを定義することができます 
* キャッシュ
  * Amazon S3
  * バケット：キャッシュ用のバケットを選択。プロジェクト設定保存時に選択したバケットに自動でAWS CodeBuildのロールが付与されます。
    * buildspec.ymlのcacheディレクティブに定義した内容が設定したS3バケットに保存されます
* ログ
  * CloudWatch Logs : チェックを選択
  * グループ名 : 空欄
  * ストリーム名 : 空欄
  * S3 ログ : 未チェック
* サービスロール
  * アカウントでサービスロールを作成
* VPC  
  * GitLab・Jenkinsと疎通可能なVPCを選択する
* 詳細設定
  * コンピューティングタイプ
     * 3GBメモリ・2vCPU / 7GBメモリ・4vCPU / 15GBメモリ・8vCPUから選択可能
  * 環境変数
      * 環境変数を定義可能

※について、AWSで用意されているランタイムはバージョンに制約があったり、ビルドやCIの中で使うツールを都度設定しないといけなかったりするので、ECRに自前のコンテナを登録して使うとよいでしょう。 

# JenkinsのAWS CodeBuildプラグインの設定

Jenkinsの管理画面からAWS CodeBuild Pluginをインストールするだけです。これを使うとAWS CodeBuildのログもJenkinsから確認できます。

https://github.com/awslabs/aws-codebuild-jenkins-plugin

# JenkinsとAWS CodeBuildのロール連携

JenkinsからAWS CodeBuildがアクセスできるようにJenkinsが動作しているAWSリソースにAWS CodeBuildのロールポリシーをアタッチします

* AWSCodeBuildDeveloperAccess

# Jenkinsfileを記述する

以下のようにJenkinsfileの中でawsCodeBuildディレクティブを記載すればよいです。
credentialsTypeはIAMロールで実行する場合でも`keys`を選択します。

```groovy
...
    stages {
        stage('codebuild') {
            steps {
                awsCodeBuild(
                    credentialsType: 'keys',
                    projectName: 'projectName', // awsCodeBuildのプロジェクト名を記入
                    region: 'aws-region', // awsCodeBuildのリージョンを選択
                    sourceControlType: 'project', //projectを選択※
                    sourceVersion: env.BRANCH_NAME,
                    envVariables: "[{BRANCH_NAME,${env.BRANCH_NAME}}]", //連携する環境変数を設定できる
                )
            }
        }
```

sourceControlTypeを`jenkins`にすると、JenkinsとAWS CodeBuildの間にS3を挟んでソースをやりとりするようになります。

# buildspec.ymlを設定する

buildspec.ymlの中で実際にビルドの中で実行する内容を記述します。レポジトリの中でシェルスクリプトでまとめておくと見やすいでしょう。
buildspec.ymlの中でJenkinsfileから連携した環境変数が利用できます。

```yml
version: 0.2

phases:
  install:
    commands: 
      - ./setup.sh
  build:
    commands:
      - ./build.sh
      - ./test.sh
  package:
    commands:
      - |
        if [ -z "${BRANCH_NAME%%release/*}" ]; then
          ./package.sh
        fi

cache:
  paths:
    - /path/to/cache/*
```

# 設定の確認

GitLabへのPush契機でJenkinsが実行され、Jenkinsのジョブ実行を契機にAWS CodeBuildが実行されれば実行成功です。

# ブランチの扱い

AWS CodeBuildではブランチの制御ができません。もしbuildspec.ymlでartifactを定義すると、featureブランチでもartifactが生成されてしまいます。
そのため、環境変数でブランチ名を伝搬させて、artifactの保存はawsのS3コマンドで実行するとよいでしょう。

# 参考資料

* https://takamii.hatenablog.com/entry/2018/09/07/234509
* https://github.com/takami228/jenkins-awscodebuild-starter
* https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/jenkins-plugin.html
* https://www.slideshare.net/AmazonWebServicesJapan/aws-black-belt-online-seminar-awsjenkins