TerraformでCodeBuildのレポート機能を使ってみる

# はじめに
昨年5月に CodeBuild のレポート機能が追加されたが、自分の所属するプロジェクトでは自動テストやカバレッジのレポートは既に別のソリューションを導入していたのであまり触っていなかった。
今回、別の記事を書くにあたり、この辺りの機能を試してみたくなったので、併せて使ってみた。

なお、本記事の前提知識として、

- CodeBuild のプロジェクトを IaC で書いたことがある
- CodeBuild のレポート機能の概要を知っている

ことが前提となる。
※CodeBuild のレポート機能の概要は例によって[クラスメソッド先生](https://dev.classmethod.jp/articles/codebuild-test-reporting-ga/)が分かりやすい

# 必要な Terraform リソース
必要なリソースは、```aws_codebuild_report_group``` だ。
テストレポートとカバレッジレポートで出力が違うため、```type``` プロパティで指定ができる。

一癖あるのが ```name``` プロパティで、[AWS公式ドキュメント](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/report-create.html)によると、

```
「CodeBuildのプロジェクト名」-「Buildspec の reports セクションで指定するグループ名」
```

という名前が適用されるらしい(変更できるかはよく分からない)。
そんな感じなので、以下のように定義する。

```HCL
################################################################################
# S3                                                                           #
################################################################################
resource "aws_s3_bucket" "test" {
  bucket        = local.s3_testreport_bucket_name
  acl           = "private"
}

resource "aws_s3_bucket" "coverage" {
  bucket        = local.s3_coveragereport_bucket_name
  acl           = "private"
}

################################################################################
# CodeBuild                                                                    #
################################################################################
resource "aws_codebuild_report_group" "test" {
  name = "${local.codebuild_project_name}-${local.codebuild_test_reportgroup_name}"
  type = "TEST"

  export_config {
    type = "S3"

    s3_destination {
      bucket              = aws_s3_bucket.test.id
      encryption_disabled = false
      encryption_key      = data.aws_kms_key.aws_s3.arn
    }
  }
}

resource "aws_codebuild_report_group" "code_coverage" {
  name = "${local.codebuild_project_name}-${local.codebuild_codecoverage_reportgroup_name}"
  type = "CODE_COVERAGE"

  export_config {
    type = "S3"

    s3_destination {
      bucket              = aws_s3_bucket.coverage.id
      encryption_disabled = false
      encryption_key      = data.aws_kms_key.aws_s3.arn
    }
  }
}
```

そんなに難しいことはないが、[公式ドキュメント](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codebuild_report_group)によると、

>  Note: the API does not currently allow setting encryption as disabled

とのことで、encryption_disabled が無効にできないんだとか。

ということは、KMS が必要になるが、ここは別に AWS マネージドな KMS でも良いので、お手軽にやるなら

```HCL
data "aws_kms_key" "aws_s3" {
  key_id = "alias/aws/s3"
}
```

な感じで S3 バケット用のエイリアスを引っ張ってきて設定しよう。
当然ながら、S3 バケットに PutObject をするための権限を CodeBuild のサービスロールに付与するのを忘れないように。

ちなみに、```export_config``` で ```NO_EXPORT``` を指定することも可能だが、エラーが出たときにプレーンなファイルが残っていないと調査が困難なので、最初は出力しておくのがオススメ。

# Buildspec での指定
レポートを出力するには、出力形式に合わせたフォーマットで Buildspec 上でファイルを渡してあげなければいけない。
テストとカバレッジであれば以下ように両方を指定する。

```YAML
reports:
  ${TEST_REPORTGROUP_NAME}:
    files:
      - "report/report.xml"
    file-format: "JUNITXML"
  ${COVERAGE_REPORTGROUP_NAME}:
    files:
      - "report/coverage.xml"
    file-format: "COBERTURAXML"
```

環境変数になっている部分が、グループ名だ。
↑で作ったグループ名の書き換え忘れがないように、CodeBuild の環境変数で渡すようにしている。

```HCL
################################################################################
# CodeBuild                                                                    #
################################################################################
resource "aws_codebuild_project" "test" {
  (中略)
  environment {
    environment_variable {
      name  = "TEST_REPORTGROUP_NAME"
      value = local.codebuild_test_reportgroup_name
    }
    environment_variable {
      name  = "COVERAGE_REPORTGROUP_NAME"
      value = local.codebuild_codecoverage_reportgroup_name
    }
  }
  (後略)
```

実際に出力するファイルの形式については、言語によっても異なるので、それぞれの言語に合わせて対応してもらいたい。
詳細は [AWS の公式ドキュメント](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/test-reporting.html)に書かれている。

# いざ、動かす！
さて、これで CodeBuild を実行すれば、レポートのタブから以下のように結果が確認できるようになる。

![キャプチャ6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/85dcf1f2-f912-1e63-f428-37f721081385.png)

さらに、ここからレポートに飛ぶことで、以下のようにテストとカバレッジのレポートを確認できる。

## テストレポート
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/cbdcf86d-72da-fdba-c314-166e2ddd3a36.png)
![キャプチャ5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/a7da0e85-d47c-dd40-5b1d-95b76b961b74.png)

また、グループのトップに行けば、エラーの推移等も確認可能だ。

![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/e2b08f3a-d765-5b86-460e-57f0fb198581.png)

## カバレッジレポート
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/348f965a-fdfb-2e99-449a-b5710befd6e4.png)

こちらもグループのトップから推移の確認が可能。

![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/2620c289-c1ad-2c21-bf68-5ee00851bc14.png)

# 余談
ちなみに、レポートグループにレポートが残っていると、```aws_codebuild_report_group``` の ```destroy``` 時に

```
 InvalidInputException: Report group could only be deleted after its reports are deleted
```

なエラーが出て消せない。S3バケットの ```force_destroy``` プロパティみたいなものが出てほしい……。
※実運用上ではこのリソースを消すことはあまりなさそうなので、実質問題ないとは思うが。