[小ネタ]レビュー用URLにビルド結果を組み込む

2022.06.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは!AWS事業本部コンサルティング部のたかくに(@takakuni_)です。

今回は、CodePipelineの手動承認アクションで使用するレビュー用URLにCodeBuildのビルド結果を組み込んでみようと思います。

先に結論

  • ビルド結果は、ビルド変数「CODEBUILD_BUILD_URL」から取得できる。
  • ビルド変数の出力には、「名前空間」と「エクスポートされた環境変数」を使用する。

ビルド実行URLの規則性について

初めに、ビルド履歴のURLには規則性があることをご紹介します。

URLは以下のように生成されています。

https://【リージョン】.console.aws.amazon.com/codesuite/codebuild/【アカウントID】/projects/【ビルドプロジェクト名】/build/【ビルドプロジェクト名】%3A【ビルドID】/?region=【リージョン】

「%3A」とは

URLの「【ビルドプロジェクト名】%3A【ビルドID】」で、「%3A」という文字が使われてます。「%3A」は、URLエンコードされた「:(コロン)」に該当します。

つまり、「【ビルドプロジェクト名】%3A【ビルドID】」は、「【ビルドプロジェクト名】:【ビルドID】」となります。

エクスポートされた環境変数とは

CodePipelineではCodeBuildプロジェクトでエクスポートされた環境変数を名前空間を使って各アクション間で受け渡すことができます。

環境変数は、buildspecの「exported-variables」で値をエクスポートできます。

以下は、「exported-variables」を使用して環境変数をエクスポートする一例です。

「BuildID」と「BuildTag」を「exported-variables」で定義して、「post_build」フェーズで変数をエクスポートしていることがわかります。

  version: 0.2
  env:
    exported-variables:
      - BuildID
      - BuildTag
  phases:
    install:
      runtime-versions:
        golang: 1.14
      commands:
        - "git clone https://github.com/tfutils/tfenv.git ~/.tfenv"
        - "ln -s ~/.tfenv/bin/* /usr/local/bin"
        - "tfenv install $TF_VERSION"
        - "tfenv use $TF_VERSION"
    pre_build:
      commands:
        - "terraform init -input=false -no-color"
    build:
      commands:
        - "terraform plan -input=false -no-color"
    post_build:
      commands:
        - "export BuildID=`echo $CODEBUILD_BUILD_ID | cut -d: -f1`"
        - "export BuildTag=`echo $CODEBUILD_BUILD_ID | cut -d: -f2`"

名前空間とは

名前空間とは、CodePipelineの各アクションに名前をつける機能になります。名前空間を使用してアクション間で値を受け渡すことができます。

以下の画面の場合、アクション名は「Terraform_Security_Analysis」ですが、環境変数の受け渡し時は名前空間の「TFSEC」が使用されます。

値の受け渡し方法

CodeBuildプロジェクトの場合、「#{名前空間.エクスポートされた環境変数}」で値を受け渡します。

「#{TFSEC.BuildID}」の場合、名前空間「TFSEC」のビルドプロジェクトでエクスポートされた環境変数「BuildID」を取り出します。

CodeBuildプロジェクト以外にも、アクションタイプごとに様々な値を取り出すことができます。かなり便利な機能なためぜひパイプランを組む際はオススメです。

パイプラインアクションで使用できる変数

やってみた

今回は、CodeBuildのビルド結果を手動承認アクションのレビューURLに組み込もうと思います。

CodeBuildで使用されている「CODEBUILD_BUILD_URL」を「BUILD_URL」としてエクスポートして、手動承認アクションで名前解決を行います。

CodeBuildプロジェクトの情報は以下の通りです。

  • アクション名:Terraform_Security_Analysis
  • アクションプロバイダー:AWS CodeBuild
  • リージョン:アジアパシフィック
  • 入力アーティファクト:Artifact_Source_CodeCommit_Source
  • プロジェクト名:developers-io-2022-tf-build-tfsec-project
  • 環境変数:設定なし
  • 変数の名前空間:TFSEC

buildspecで変数のエクスポート

先程紹介した「exported-variables」を使用する方法で、変数をエクスポートします。

buildspecは以下の通りです。

buildspec.yaml

version: 0.2
env:
  exported-variables:
    - BUILD_URL
phases:
  pre_build:
    commands:
      - "echo Executing tfsec"
      - "mkdir -p reports/tfsec/"
  build:
    commands:
      - "tfsec -s --no-color --config-file exclude.yml ."
      - "tfsec -s --no-color --config-file exclude.yml . --format junit > reports/tfsec/report.xml"
  post_build:
    commands:
      - "export BUILD_URL=`echo $CODEBUILD_BUILD_URL`"
reports:
  reports:
    files:
      - "reports/tfsec/report.xml"
    file-format: JUNITXML

ビルド履歴から変数がエクスポートできていることがわかります。

名前解決

「#{TFSEC.BUILD_URL}」で名前解決を行います。

レビュー画面からエクスポートされた環境変数が解決できていることがわかります。

もちろん、URLを踏むとCodeBuildの実行履歴に遷移します。

方法は1つだけではない

先日、公開した「TerraformのCI/CDパイプラインを実装してみた」では、「【ビルドプロジェクト名】%3A【ビルドID】」の部分をcutコマンドで抽出してURLを生成していました。

具体的には以下のコマンドです。

CodeBuildで使用されている環境変数「CODEBUILD_BUILD_ID」からビルドプロジェクト名とビルドIDを抽出し、新しい環境変数にエクスポートしています。

export BuildID=`echo $CODEBUILD_BUILD_ID | cut -d: -f1`
export BuildTag=`echo $CODEBUILD_BUILD_ID | cut -d: -f2`

コードが少し長いですが、エクスポートした環境変数、名前空間を使用してURLを生成しています。

  CodePipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: !Sub "${PrjPrefix}-tf-pipeline"
      ArtifactStore:
        EncryptionKey:
          Id: !GetAtt KeyS3Arthifact.Arn
          Type: "KMS"
        Location: !Ref BucketArtifacts
        Type: "S3"
      RoleArn: !GetAtt RoleTfPipelne.Arn
      Stages:
        - Name: "Source"
          Actions:
            - Name: "CodeCommit_Source"
              ActionTypeId:
                Category: "Source"
                Owner: "AWS"
                Provider: "CodeCommit"
                Version: "1"
              Configuration:
                RepositoryName: !GetAtt CodeCommit.Name
                BranchName: !Ref BranchName
                PollForSourceChanges: false
              OutputArtifacts:
                - Name: "Artifact_Source_CodeCommit_Source"
              RoleArn: !GetAtt RoleTfPipelne.Arn
              RunOrder: 1
        - Name: "tfsec_Stage"
          Actions:
            - Name: "Terraform_Security_Analysis"
              Namespace: TFSEC
              ActionTypeId:
                Category: "Build"
                Owner: "AWS"
                Provider: "CodeBuild"
                Version: "1"
              Configuration:
                ProjectName: !Ref ProjectTfsec
              InputArtifacts:
                - Name: "Artifact_Source_CodeCommit_Source"
              RoleArn: !GetAtt RoleTfPipelne.Arn
              RunOrder: 1
        - Name: "Terraform_Stages"
          Actions:
            - Name: "Terraform_Security_Analysis_Manual_Review"
              ActionTypeId:
                Category: "Approval"
                Owner: "AWS"
                Provider: "Manual"
                Version: "1"
              Configuration:
                CustomData: "tfsec review"
                ExternalEntityLink: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codebuild/${AWS::AccountId}/projects/#{TFSEC.BuildID}/build/#{TFSEC.BuildID}%3A#{TFSEC.BuildTag}/?region=${AWS::Region}"
              RoleArn: !GetAtt RoleTfPipelne.Arn
              RunOrder: 1
            - Name: "Terraform_Plan"
              Namespace: "TERRAFORM"
              ActionTypeId:
                Category: "Build"
                Owner: "AWS"
                Provider: "CodeBuild"
                Version: "1"
              Configuration:
                ProjectName: !Ref ProjectTfplan
              InputArtifacts:
                - Name: "Artifact_Source_CodeCommit_Source"
              RoleArn: !GetAtt RoleTfPipelne.Arn
              RunOrder: 2
            - Name: "Terraform_Plan_Manual_Review"
              ActionTypeId:
                Category: "Approval"
                Owner: "AWS"
                Provider: "Manual"
                Version: "1"
              Configuration:
                CustomData: "Terraform plan review"
                ExternalEntityLink: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codebuild/${AWS::AccountId}/projects/#{TERRAFORM.BuildID}/build/#{TERRAFORM.BuildID}%3A#{TERRAFORM.BuildTag}/?region=${AWS::Region}"
              RoleArn: !GetAtt RoleTfPipelne.Arn
              RunOrder: 3
            - Name: "Terraform_Apply"
              ActionTypeId:
                Category: "Build"
                Owner: "AWS"
                Provider: "CodeBuild"
                Version: "1"
              Configuration:
                ProjectName: !Ref ProjectTfapply
              InputArtifacts:
                - Name: "Artifact_Source_CodeCommit_Source"
              RoleArn: !GetAtt RoleTfPipelne.Arn
              RunOrder: 4

終わりに

以上、「レビュー用URLにビルド結果を組み込む」でした。

CodeBuildプロジェクトでは様々な環境変数が使用されているため、ぜひ一度プロジェクトで使用しているDockerイメージをprintenvしてみてはいかがでしょうか。

この記事がどなたかの参考になれば幸いです。

以上、AWS事業本部コンサルティング部のたかくに(@takakuni_)でした!