AWS CodePipelineの承認アクション有無を、AWS CloudFormationテンプレートでコントロールする

# What's？

AWS CodePipelineには、ステージ内に承認アクションを設けることができます。

https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/approvals.html

こちらは本番環境で使うのはよいのですが、開発環境では設けなくてもよいことが多く、これをAWS CloudFormationの条件分岐でコントロールするサンプルが見つからなかったので、メモ的に残しておくことにしました。

# 解法

AWS CloudFormationテンプレートの`Conditions`と、擬似パラメーター`AWS::NoValue`の組み合わせで実現します。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html

# 環境

使用したAWS CLIのバージョンは、こちら。

```shell
$ aws --version
aws-cli/2.4.29 Python/3.8.8 Linux/5.4.0-105-generic exe/x86_64.ubuntu.20 prompt/off
```

# 例

こんな感じですね。

たとえば`Parameters`で承認アクションの有無を切り替えるとして

```yaml
Parameters:
  RequireApprovalAction:
    Type: String
    AllowedValues:
      - true
      - false
```

`Conditions`を指定。

```yaml
Conditions:
  HasApprovalAction:
    !Equals
      - !Ref RequireApprovalAction
      - true
```

リソース定義（`...`の部分は省略していることを表しています）。

```yaml
Resources:

  ...

  CodePipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: ...
      RoleArn: ...
      ArtifactStore:
        Type: S3
        Location: ...
      Stages:
        - Name: GetSourceArtifact
          Actions:
            - Name: SourceAction
              ...
        - Name: ...
        # 必要なら承認アクションを配置する
        - !If
          - HasApprovalAction
          - Name: ReleaseApproval
            Actions:
              - Name: ApprovalAction
                ActionTypeId:
                  Category: Approval
                  Owner: AWS
                  Version: 1
                  Provider: Manual
                Configuration:
                  CustomData: !Sub 'Comments on the manual approval'
                RunOrder: 1
          - !Ref AWS::NoValue
        - Name: ...
          ...

  ...

```

このテンプレートの例だと、`RequireApprovalAction`パラメーターが`true`だと以下の条件分岐が`true`になり、承認アクションが追加されます。

```yaml
        - !If
          - HasApprovalAction
          - Name: ReleaseApproval
            Actions:
              - Name: ApprovalAction
                ActionTypeId:
                  Category: Approval
                  Owner: AWS
                  Version: 1
                  Provider: Manual
                Configuration:
                  CustomData: !Sub 'Comments on the manual approval'
                RunOrder: 1
          - !Ref AWS::NoValue
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/f32619e5-4c1b-9275-703f-25ed5f5d7e69.png)

> AWS CLIでのイメージでは、`aws cloudformation deploy`コマンドに、オプションとして`-parameter-overrides RequireApprovalAction=true`を指定する

RequireApprovalAction`パラメーターを`false`にすると、`AWS::NoValue`が使われることになり、承認アクションがパイプラインにいなくなります。

> `aws cloudformation deploy`コマンドに、`--parameter-overrides RequireApprovalAction=false`を指定

実際に使う時には、環境別に承認アクションの有無を分けたいという話になりやすいかと思うので、`Parameters`ではなく`Mappings`（と`Conditions`）との組み合わせで実現することが多いのかな、という気がします。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html

# 参考

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-codepipeline-pipeline-stages-actions-actiontypeid.html

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