MiddlemanでbuildしたコンテンツをCircle CI経由でAmazon S3に同期する

この記事は“[Build and deploy static sites w/ Middleman, CircleCI and Amazon S3](https://www.theguild.nl/build-and-deploy-static-sites-w-middleman-circleci-and-amazon-s3/)”を実際にやってみた、といった内容です。

Amazon S3の画面についての説明が冗長になってしまった気もしますが、自分自身も四苦八苦した所なので記載しておきます。

必要なモノが少ないので、**とにかくCircleCIを動かしたい**という場合にはちょうどいいのではないかと思います。

# 手順

1. [Middleman](https://middlemanapp.com/jp/)のプロジェクトを作成しbuildしてGitHubにプッシュ
2. Amazon S3の各種設定を行い、(1.)でbuildしたファイルをアップロード
3. [CircleCI](https://circleci.com/)の設定を行う

結果：masterをGitHubにプッシュするとCircleCIのビルドが走り、S3のコンテンツが同期する

# Middlemanのプロジェクトを作成する

```bash
middleman init <project-name>
```

インストール済みのMiddlemanは3.3.12でした。

## middleman-s3_syncをインストール

[middleman-s3_sync](https://github.com/fredjean/middleman-s3_sync)というgemが必要なのでGemfileに追記して`bundle install`

```ruby:Gemfile
gem 'middleman-s3_sync'
```

## middleman-s3_syncの設定

`config.rb`にmiddleman-s3_syncの設定を追記します。

```ruby:config.rb
activate :s3_sync do |s3_sync|
  s3_sync.bucket                 = '<your-backet>'
  s3_sync.region                 = '<your-backet-region>'
  #s3_sync.aws_access_key_id     = '<your-access-key>' // remove
  #s3_sync.aws_secret_access_key = '<your-secret>'     // remove
end
```

`s3_sync.aws_access_key_id`と`s3_sync.aws_secret_access_key`については、あとからCircleCI側で設定するので削除します。

※`config.rb`にこれらを書いたままGitHubにプッシュすると、謎のアドレスからAWSの機密情報をリモートにプッシュしないで、という指摘のメールが届きます。すごいですね :flushed: 

## CircleCIの設定ファイル追加

CircleCIの設定ファイルを追加します。まだ、詳細はよくわかりませんが、とりあえず動いたのでよしとします。

```yaml:circle.yml
machine:
  timezone: Asia/Tokyo
dependencies:
  pre:
    - gem install bundler --pre
deployment:
  deploy:
    branch: master
    commands:
      - bundle exec middleman s3_sync
```

## バンドル作成

バンドルファイル（`build`ディレクトリの中身）が必要なので`bundle exec middleman build`しておきます。

# Amazon S3にファイルをアップロードしていろいろ設定

むかし試して放置していたS3のバケットがすでにあったので使います。たぶん左上の「バケットを作成」でできると思います。

バケットができたら、左上の「アップロード」から作成したバンドルの`build`ディレクトリの中身をアップロードします。ふと、どうして`build`だけでいいのか？と思いましたが、middleman-s3_syncはそういうgemのようです。

それから、公開ウェブサイトにするために、バケットのホームで「アクセス許可」と「静的ウェブサイトホスティング」を変更します。

<img width="1024" alt="S3_Management_Console.png" src="https://qiita-image-store.s3.amazonaws.com/0/33768/512136f5-034e-159d-612c-317b2842c219.png">

## アクセス許可

「アクセス許可」項目の「バケットポリシーの追加」からポリシーなるものを追加します。“Version”はそのままです。気を利かせたつもりで今日の日付にしたりすると、そんなバージョンないよ！とおこられます。

```json
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "PublicReadGetObject",
			"Effect": "Allow",
			"Principal": "*",
			"Action": "s3:GetObject",
			"Resource": "arn:aws:s3:::<your-backet>/*"
		}
	]
}
```

[ウェブサイトアクセスに必要なアクセス許可](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/WebsiteAccessPermissionsReqd.html)

## 静的ウェブサイトホスティング

「静的ウェブサイトホスティング」の「ウェブサイトのホスティングを有効にする」をチェックして、「インデックスドキュメント」を`index.html`、「エラードキュメント」を`error.html`とします（`error.html`は実際になくてもよい）。

「エンドポイント」が公開URLになるので表示されるかチェックしておきます。

## 認証情報の設定（IAM）

<img width="1024" alt="S3_Management_Console_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/33768/10397891-91ed-91e7-ccf5-5e735af01657.png">

### ユーザーの作成

「サービス」メニュー &raquo; 「すべてのサービス」（ &raquo; 「セキュリティ＆アイデンティティ」） &raquo; 「IAM」の「ユーザー」から新規ユーザーを作成します。作成直後にアクセスIDとセキュリティキーが表示されるのでそれをメモしておきます。

「認証情報」タブから再度作成することも可能です。「セキュリティキー」は作成時以外は二度と表示されません。

### ポリシーの作成

つづいて、「ポリシー」 &raquo; 「独自のポリシーを作成」からポリシーを作成します。ポリシー名を適当につけて、ポリシードキュメントは以下のようにします。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::<your-bucket>"
        },
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::<your-bucket>/*"
        }
    ]
}
```

作成したポリシーを表示して「アタッチされたエンティティ」タブから先ほど作成したユーザーをアタッチします。ユーザーの「アクセス許可」タブからポリシーをアタッチすることも可能です。

また、ポリシー自体、ユーザーの「アクセス許可」タブにある「インラインポリシー」から作成可能かもしれません（未確認）。

# CircleCIの設定

CircleCIはGitHubアカウントでもサインアップできます。便利ですね :laughing: 

作成したリポジトリをGitHubにプッシュします。“Add Projects”からリポジトリを選択すると、すぐさま最初のビルドが走ります。

“Project Settings”から“Environment Variables”を開き、メモしておいたアクセスIDとセキュリティキーを環境変数に追加します。

```
AWS_ACCESS_KEY_ID        <your-access-key>
AWS_SECRET_ACCESS_KEY    <your-secret>
```

これで、何か変更してプッシュすれば、CircleCIのビルドが走り、S3と同期されるはずです。