CodePipelineのイベント通知をEメールでさくっと受け取る

CodePipelineの開始時と終了時にEメールで通知を受け取りたかったので、Terraformでさくっと構築してみた。

## SNSを作成
まずはSNSトピックを作成して、**「CloudWatchEventsからPublishされてもいいよ」というIAMポリシーを付与**する。

```sns.tf
resource "aws_sns_topic" "codepipeline" {
  name = "CodePipelineExecutionStateChange"
}

resource "aws_sns_topic_policy" "codepipeline" {
  arn    = "${aws_sns_topic.codepipeline.arn}"
  policy = "${data.aws_iam_policy_document.sns_topic_policy.json}"
}

data "aws_iam_policy_document" "sns_topic_policy" {
  statement {
    effect  = "Allow"
    actions = ["sns:publish"]

    principals {
      type        = "Service"
      identifiers = ["events.amazonaws.com"]
    }

    resources = ["${aws_sns_topic.codepipeline.arn}"]
  }
}
```

## CloudWatchEventsを作成
次にCloudWatchEventsを使って、CodePipelineのイベントが発生したときに、SNSトピックをPublishするように設定する。

```cloudwatch_events.tf
resource "aws_cloudwatch_event_rule" "codepipeline" {
  name        = "CodePipelineExecutionStateChane"
  description = "CodePipeline Pipeline Execution State Change"

  event_pattern = <<PATTERN
{
  "source": [
    "aws.codepipeline"
  ],
  "detail-type": [
    "CodePipeline Pipeline Execution State Change"
  ]
}
PATTERN
}

resource "aws_cloudwatch_event_target" "codepipeline_to_sns" {
  rule = "${aws_cloudwatch_event_rule.codepipeline.name}"
  arn  = "${aws_sns_topic.codepipeline.arn}"

  input_transformer {
    input_paths = {
      PipelineName = "$.detail.pipeline"
      State        = "$.detail.state"
    }

    input_template = "\"Pipeline [<PipelineName>] execution state changed [<State>]\""
  }
}
```

### メールの送信メッセージをカスタマイズ
CloudWatchEventsにはInput Transformerというイベントをカスタマイズできる機能がある。
Input Transformerを使わない場合、以下のようにイベントのJSONがただ送られてくるだけになる。

![df5c1936ba82ce09d3045cabd6f3d8db.png](https://qiita-image-store.s3.amazonaws.com/0/109606/2e492aaa-c3d1-f3d0-3e27-5d921a8813c6.png)


これだと味気ないため、Input Transformerでメールの内容をいい感じにする。Terraoformでは`aws_cloudwatch_event_target.*.input_transformer`を設定してあげればいい。

```
input_transformer {
  input_paths = {
    PipelineName = "$.detail.pipeline"
    State        = "$.detail.state"
  }

  input_template = "\"Pipeline [<PipelineName>] execution state changed [<State>]\""
}
```

`input_paths`には、`input_template`で使える変数を定義する。
`$.detail.pipeline`のようなイベントデータは公式ドキュメントの「[Amazon CloudWatch Events でパイプラインの状態の変更を検出](https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/detect-state-changes-cloudwatch-events.html)」にサンプルイベントとして載っているので、そちらを参照されたし。

またinput_templateは、文字列をさらにダブルクオーテーション`"`で囲む必要があるため、気を付けよう。

![7f5de837bd56eb384b87b3806d9ac965.png](https://qiita-image-store.s3.amazonaws.com/0/109606/fe02e464-250c-6fd8-a44b-27bf490a3b1f.png)

うむ。いい感じになった。

### 通知フィルター
「もっと通知の段階を増やしたい、減らしたい」という場合は、event_patternのdetail-typeを変更すれば**CodePipelineのステージやアクションごとに通知を飛ばす**ことが可能になる。

その他にもスキップするパターンなども指定することが可能だ。
詳しくは上でも貼った公式ドキュメントの「[Amazon CloudWatch Events でパイプラインの状態の変更を検出](https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/detect-state-changes-cloudwatch-events.html)」に書かれている。

またevent_patternのJSONは、Events作成画面から簡単に作成・取得できる。
https://ap-northeast-1.console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#rules:action=create

## Eメールでの購読を承認
次にSNSのコンソール画面で、トピックのサブスクリプションを作成する必要がある。
**Eメールの場合は承認が必要で、現在Terraformではサポートしていない**からだ。

手動でサブスクリプションを作成した後、確認メールの承認URLを踏んで承認しておこう。

## Eメールを受信
試しにCodePipelineを起動してみる。
すると先ほどのようなメールが、「AWS Notifications\<no-reply@sns.amazonaws.com\>」という人物から届く。

![7f5de837bd56eb384b87b3806d9ac965.png](https://qiita-image-store.s3.amazonaws.com/0/109606/cd206776-2370-fb3d-74d9-2cb678edd3ec.png)

よし。こういうのでいいんだ。