CodePipelineを使って静的サイトのデプロイを自動化しよう！

## はじめに
今回は、Node.js製のHexoという静的サイトジェネレーターを使ってAWSの`S3`にデプロイします。
**ちなみに`Hexo`を知らなくても問題なくデプロイできるように構成しています。**

https://hexo.io/

そのデプロイを、`CodePipeline`と`CodeBuild`を使って自動化しましょう。

## CodePipelineとは？
AWS CodePipeline は完全マネージド型の**継続的デリバリーサービス**で、リリースを自動化します。

まぁここで疑問なのは、**「継続的デリバリーサービス」**ですよね。
AWS公式サイトでは以下のように紹介されていました。
>継続的デリバリーとは、ソフトウェア開発手法の 1 つで、コード変更が発生すると、自動的に実稼働環境へのリリース準備が実行されるというものです。最新のアプリケーション開発の柱となる継続的デリバリーは、継続的インテグレーションを拡張したもので、すべてのコード変更が、ビルド段階の後にテスト環境または運用環境 (あるいはその両方) にデプロイされます。適切に実装すると、開発者は、標準化されたテストプロセスに合格し、デプロイ準備の整ったビルド成果物を常に手元に持つことになります。 

初学者には難しすぎたので、要約するとこのような感じです。
CodePipelineは、**「コードに変更があったときにその変更内容を自動的に反映させてくれるサービス」**です。

むちゃくちゃ便利ですよね。
また設定も簡単なのでぜひ取り入れたいところです。

なお、初学者には優しいAWS無料枠の対象であり、**「1つ」しか使わないのであればずっと無料です。**
（ちなみに、料金は1つあたり$1です。なので無料枠をオーバーしてもそんなにダメージはありません。）

ということで今回のハンズオンは無料でできるので、ぜひ試してみてください。


## 流れ
どのように作成していくか軽くメモしていきます。

<ol>
<li>Hexoを使って静的サイトを作成する</li>
<li>デプロイ先のS3バケットを用意する</li>
<li>CodeBuildを使うためにbuildspec.ymlを作成</li>
<li>GitHubのmasterブランチにプッシュ</li>
<li>CodePipelineの設定</li>
<li>新しい記事をデプロイ</li>
</ol>

今回は、静的サイトジェネレーターにHexoを採用しましたが、以下のフレームワークでも可能です。

| フレームワーク | 説明                     |
| ---------- | ------------------------ |
| Next.js    | React, JavaScript ベース |
| Gatsby     | React, JavaScript ベース |
| Hugo       | Go ベース                |
| Nuxt.js    | Vue, JavaScript ベース   |
| Jekyll     | Ruby ベース              |

ちなみに、S3は、SPAはできますが、Node.jsの実行が必要なSSRはできません。
なので、SSRを使いたい場合は、ECS, EC2などにデプロイしていくことになります。

それでは実際にやってみましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/6c342aa4-a16d-d3c4-c0ad-d926aaad01c0.png)

## ハンズオン
### 1. Hexoを使って静的サイトを作成する
今回のハンズオンを行う上で、`Node.js`と`Git`の2つがインストールされていることが前提です。
ない方はインストールされてください。

ちなみに私の環境は以下となっています。

| パッケージ | バージョン |
| ---------- | ---------- |
| Node.js    | 14.17.1    |
| Git        | 2.31.0     |

それでは始めます。

#### HexoのCLIをインストール
まずはCLIをインストールしましょう。

```terminal:ターミナル
$ npm install -g hexo-cli
```

#### 新規作成
Hexoのプロジェクトを作成します。

```terminal:ターミナル
$ hexo init blog
```

#### ローカルで表示

```terminal:ターミナル
$ hexo server
```

このような感じで表示されればOKです。

![スクリーンショット 2021-09-23 9.49.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/b01c5173-84de-cc96-45f8-504ee95415d5.png)

### 2. デプロイ先のS3バケットを用意する
#### バケットの作成
まずはバケットを作成しましょう。

![スクリーンショット 2021-09-23 9.54.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/854f5c25-a63f-d921-6cc3-15e67ee0be41.png)

S3のバケット名はダブってはいけないので、下記を参考に命名されてください。

![スクリーンショット 2021-09-23 9.56.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/5fbf956b-97cf-d2d1-77c3-4e8d32e44bcb.png)

また、アクセス設定のチェックは外しておきましょう。

![スクリーンショット 2021-09-23 9.59.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/8d3fb2f8-f889-b153-3675-0c92e9630829.png)

これでバケットを作成できます。
作成されたバケットの中に入りましょう。

では、プロパティをみてみましょう。

![スクリーンショット 2021-09-23 10.02.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/ae23446f-db4a-6ed8-8368-37fce93f4ba6.png)

一番下に、**「静的ウェブサイトホスティング」**の項目があるのでこちらを**有効**にしましょう。

![スクリーンショット 2021-09-23 10.03.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/b51ece3f-047a-3a76-b884-bd6f0e63df68.png)

設定箇所は以下の2点でOKです。

![スクリーンショット 2021-09-23 10.04.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/a944fe08-e3f4-dac4-79d5-dd712cdadab3.png)

#### バケットポリシーの設定
次はバケットポリシーの設定です。

![スクリーンショット 2021-09-23 10.06.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/bca3eae6-a595-2fc9-59d3-485e7ca34158.png)

バケットポリシーで設定する内容は以下の通りです。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadForGetBucketObjects",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::(バケット名)/*"
        }
    ]
}
```

バケット名は任意の値に上書きしてください。

![スクリーンショット 2021-09-23 10.08.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/6fb6f06c-ac6e-d809-be1e-a72ada548270.png)

このように編集できればOKです。

### 3. CodeBuildを使うためにbuildspec.ymlを作成
Hexoで作成したファイルをビルドする必要があるので、`CodeBuild`が必要になります。

`CodeBuild`を使うには、`buildspec.yml`が必要になるので作成していきましょう。

```diff_yaml:blog/buildspec.yml
version: 0.2

# CodeBuild でのビルドの各段階で実行するコマンドを定義
phases:
  # ビルド前に実行するコマンド
  install:
    # どのランタイムを使用するか定義
    runtime-versions:
      nodejs: 12
    commands:
      - npm install -g hexo
      - npm install
  # ビルド時に実行するコマンド
  build:
    commands:
      - hexo generate
# 以下のフォルダをS3にアップロードする
artifacts:
  files:
    - '**/*'
  base-directory: 'public'
```

他のフレームワークを使用する場合は、ランタイムの修正が必要になります。
こちらを参考にされてください。

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/available-runtimes.html

### 4. GitHubのmasterブランチにプッシュ
GitHubの`master`ブランチにプッシュしましょう。
私はこんな感じでリポジトリを作成しました。

https://github.com/ssk9597/AWS-CodePipeline-Hexo-Blog

### 5. CodePipelineの設定
それでは、パイプラインの作成をしましょう。

![スクリーンショット 2021-09-23 11.01.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/9582c12b-ac1b-80c2-07a5-ebdca4ae7fc9.png)

パイプライン名を設定しましょう。

![スクリーンショット 2021-09-23 11.02.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/773c1b61-07c7-5d98-0471-99404d2fb16e.png)

それでは、GitHubと接続しましょう。

![スクリーンショット 2021-09-23 11.03.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/ef9540b9-e616-d757-2eff-1a480929f74f.png)

接続名は適当で構いません。

![スクリーンショット 2021-09-23 11.05.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/1241c2d4-a797-f073-de31-749bac1163f8.png)

では、**「新しいアプリをインストール」**して接続しましょう。

![スクリーンショット 2021-09-23 11.06.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/a1c71cb3-8870-307f-1192-0dc43ad28be5.png)

これでGitHubとパイプラインの接続はできました。

![スクリーンショット 2021-09-23 11.08.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/8394d007-c8cc-f138-5b21-56180abb2deb.png)

次にビルドステージの設定です。

![スクリーンショット 2021-09-23 11.11.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/fcb802f4-1155-c936-2ec3-fb3cf46bd193.png)

プロジェクトの作成をしましょう。

![スクリーンショット 2021-09-23 11.13.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/e528f4f0-f96a-5299-e958-06f8d8e8ac8a.png)

![スクリーンショット 2021-09-23 11.14.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/65816fce-af3d-7603-8047-62452cb0ff15.png)

最後にデプロイステージの設定です。

![スクリーンショット 2021-09-23 11.19.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/a63344dc-74ae-ee7d-5fb1-97378d587a08.png)

**⚠️上記のリージョンにミスがあります。こちらは東京リージョンにしてください。**

変更すれば、以下のようにすべて成功します。

![スクリーンショット 2021-09-23 11.26.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/450cc92c-b975-296d-f07e-76d0aae76d70.png)

アクセスしてみましょう。

![スクリーンショット 2021-09-23 11.26.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/75fcc3c9-a4df-cfcd-5af3-2ad73d32b201.png)

![スクリーンショット 2021-09-23 11.27.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/59443721-3738-62e2-3e95-980e12e57827.png)

問題ないですね！

では、最後に新しい記事を入れてデプロイしてみましょう。

### 6. 新しい記事をデプロイ
記事を作成しましょう。

```terminal:ターミナル
$ hexo new test
```

マークダウンファイルが作成されるので修正しましょう。

```md:source/_posts/test.md
---
title: test
date: 2021-09-23 11:32:27
tags:
---

テスト記事です。
```

これをGitHubにプッシュしましょう。

またパイプラインを確認します。

![スクリーンショット 2021-09-23 11.33.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/d5bcda9d-cf46-9099-5a59-1bf698ebd5c1.png)

全部成功してますね！

ではサイトを確認しましょう。

![スクリーンショット 2021-09-23 11.37.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838372/19af25e8-ddc0-366b-833c-bebd645a67cd.png)

更新されてますね！
これで終わりです。

めちゃくちゃ簡単ですね！
ぜひCodePipeline使ってみてください！