AWSを使ってCI/CDを試してみる【初心者仕様】

## はじめに
巷で流行りのCI/CDなる手法を試してみたくなり、せっかくなのでAWSを使って
Reactで作った静的コンテンツのビルド～S3の静的ウェブサイトホスティングを自動化してみました。

## S3

### バケット作成
静的ウェブサイトホスティングを行うS3バケットを作成します。
バケット名は何でもいいので任意の値を入力します。
![bandicam 2023-08-12 13-20-17-423.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/ae6902c7-8ead-5f74-08a4-059bdb087a4d.jpeg)


今回はパブリックに静的ウェブサイトを公開するため、パブリックアクセスはすべて許可します。
![bandicam 2023-08-12 13-17-48-639.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/3b017e37-e071-29a7-f6ac-e8357bda6605.jpeg)

その他はすべてデフォルトのままバケットを作成しましょう。

### 静的ウェブサイトホスティング設定
作成したバケットのプロパティから静的ウェブサイトホスティング設定を行います。
![bandicam 2023-08-12 13-21-44-923.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/314bd145-1c24-4871-e19b-fea7d83b6646.jpeg)

下記のように設定します。
静的ウェブサイトホスティング：有効
インデックスドキュメント：index.html
その他はデフォルトのまま変更を保存します。
![bandicam 2023-08-12 13-22-48-934.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/92a07d9f-79e7-f6a2-f6bd-8476019ce15c.jpeg)

### バケットポリシー
アクセス許可 ＞ バケットポリシーを設定します。
![Snapshot_12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/f1cea9a0-cd4a-1d8f-b19a-b9134ba7340e.png)


```json
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "Statement1",
			"Principal": "*",
			"Effect": "Allow",
			"Action": [
				"s3:GetObject"
			],
			"Resource": [
			    "<s3バケットのarnを指定する>"
		    ]
		}
	]
}
```


## CodeCommit

AWS CodeCommitはgitベースのソースコードリポジトリサービスです。
標準的なgitコマンドもサポートされており、GitHub等のサービスと同じようなイメージで使用可能です。
今回はCodeCommitを変更検知用のソースに設定します。

### リポジトリの作成
まずはCodeCommitにてリポジトリを作成します。
適当にリポジトリ名を指定して作成するだけでOKです。
![bandicam 2023-08-12 02-46-40-194.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/6c069068-9ac1-3ad8-924a-5be9b8b954cb.jpeg)

### クローン
リポジトリを作成したら画面にある「URLのクローン」からURLをコピーしてローカルにクローンします。
![bandicam 2023-08-12 03-02-11-571.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/ba1b6cd9-aa11-3622-8185-f6af8193c57b.jpeg)

ローカルの適当なディレクトリでコマンドプロンプトを開いてgit cloneします。
普通にgitコマンドが使えると楽ですね。

```bash
git clone <リポジトリURL>
```
::: note info
cloneする際に認証が求められるのであらかじめIAM ＞ アクセス管理 ＞ ユーザより
任意のIAMユーザへ「AWS CodeCommit のHTTPS Git認証情報」を設定しておきましょう。
:::

### プッシュ
クローンしてきたリポジトリで適当に何かしらのソースコードを記述します。
今回は~~開発するのも面倒なので~~単純に`create-react-app`しただけのファイルをプッシュします。

```bash
# reactテンプレートを追加
cd ..
npx create-react-app sample-repo --template typescript

# CodeCommitへpush
cd sample-repo
git add -A
git commit -m "initial commit"
git push
```

## CodeBuild
AWS CodeBuildはソースコードのビルドやテスト自動化を行ってくれるサービスです。
今回はCodeBuildを使ってソースコードをビルドしていきます。

### ビルドプロジェクト作成
ソースコードをビルドするためのプロジェクトを作成します。
コンソールからCodeBuildにアクセスして「ビルドプロジェクトを作成」ボタンから作っていきましょう。
![bandicam 2023-08-12 10-59-48-739.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/b54835a8-63e7-1342-b892-dfae654af4f6.jpeg)

下記内容を入力していきます。
#### プロジェクトの設定
プロジェクト名に適当な値を入力します。
![bandicam 2023-08-12 11-04-46-803.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/862127e7-c95d-69bc-f7a7-28a970023372.jpeg)

#### ソース
ソースプロバイダ： AWS CodeCommitを選択
リポジトリ： 先ほど作ったリポジトリを選択
リファレンスタイプ： ブランチを選択
ブランチ：master（メインブランチ）を選択
![bandicam 2023-08-12 11-05-45-373.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/dc867b41-8a32-3a13-4343-186bdf35c870.jpeg)

#### 環境
環境イメージ：マネージド型イメージ
オペレーティングシステム：Amazon Linux2
ランタイム： スタンダード
イメージ：aws/codebuild/amazonlinux2-x86_64-standard:5.0
イメージのバージョン：このランタイムバージョンには常に最新のイメージを使用してください
環境タイプ：Linux
サービスロール：新しいサービスロール
ロール名：任意の値を入力
![bandicam 2023-08-12 11-16-15-627.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/b95f13ad-f44d-cd91-6d32-61e21ea38bd7.jpeg)

#### Buildspec
ビルド仕様：buildspecファイルを使用するを選択
![bandicam 2023-08-12 11-18-13-991.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/fc4a29e0-20f7-0e40-e134-1c960bcbacc7.jpeg)

#### アーティファクト
タイプ：Amazon S3
バケット名：適当なバケットを選択
アーティファクトのパッケージ化：なし
![bandicam 2023-08-12 11-23-22-745.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/6a613fbb-0322-d34e-aca8-a77abdb85f68.jpeg)

その他はすべて初期値のままでビルドプロジェクトを作成します。

### buildspec.yml
ここからはローカルでの作業です。
リポジトリのルートディレクトリにbuildspec.ymlを追加します。
buildspec.ymlをルートディレクトリに配置することでCodeBuildが設定を読み込んでビルドを実行してくれます。

```buildspec.yml
version: 0.2
phases:
  install:
    commands:
      - npm install
  build:
    commands:
      - npm run build
artifacts:
  base-directory: build
  files:
    - '**/*'
```

#### version
必須項目。
buildspecのバージョンを指定します。

#### phases
必須項目。
ビルドの実行時にCodeBuildが実行するコマンドを記述します。

◆install
ビルドに必要なパッケージをインストールするためのコマンドです。
今回はnpmの依存パッケージインストールのため、`npm install`を設定しています。

◆build
ビルド処理を行うためのコマンドです。
今回はpackage.jsonに記述されたビルドを実行するため`npm run build`を設定しています。

#### artifacts
ビルドされたファイルの出力結果に関する情報を記述します。

◆base-directory
オプション項目。
CodeBuild がビルド出力アーティファクトに含めるファイルとサブディレクトリを決定するために使用する、元のビルドの場所を基準とした、1つ以上の最上位ディレクトリを表します。
今回はbuild配下のファイルのみを出力したいため、buildを最上位ディレクトリに設定しています。


◆files
ビルド出力アーティファクトに含めるファイルを指定します。
今回はbuild配下のすべてのファイルを指定しています。

:::note info
base-directoryを指定せずにfilesをbuild/**/*とした場合は以下のような形で出力されます。
:::

```base-directoryを指定しなかった場合.
build
┣ index.html
┣ favicon.ico
┣ logo192.png
┣ logo512.png
┣ manifest.json
┣ robots.txt
┗ static
    ┣ css
    ┣ js
    ┗ media
```

```base-directoryを指定した場合.
index.html
favicon.ico
logo192.png
logo512.png
manifest.json
robots.txt
static
  ┣ css
  ┣ js
  ┗ media
```

## CodePipeline

AWS CodePipelineはAWS上の様々なサービスや外部サービスと連携し、
リポジトリの更新を検知してビルドからテスト・デプロイまでのプロセスを構築できるサービスです。

### パイプライン作成
まずはコンソールのCodePipeline画面からパイプラインを作ります。
![bandicam 2023-08-12 14-54-54-498.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/bf31909a-09bf-128a-a0ff-75852ff25adc.jpeg)

#### パイプラインの設定
パイプライン名：任意の値を入力
サービスロール：新しいサービスロールを選択
その他はデフォルトのまま次へ進みます。
![bandicam 2023-08-12 14-57-54-461.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/1abcb3a2-769f-6819-3385-8a3465c852dc.jpeg)


#### ソースステージ
アプリケーションのソースに関する情報を設定します。
今回はCodeCommitでソースを管理しているので以下のように設定していきます。

ソースプロバイダー：AWS CodeCommit
リポジトリ名：先ほど作成したリポジトリ
ブランチ名：master（メインブランチ）
その他はデフォルトのまま次へ進みます
![bandicam 2023-08-12 14-58-24-209.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/106a5dc2-6fce-d109-a84a-62b91a0e2720.jpeg)

#### ビルドステージ
ビルド処理関連の設定を行います。
今回はCodeBuildを用いてビルドを行うので以下のように設定します。

プロバイダー：AWS CodeBuild
プロジェクト名：先ほど作成したCodeBuildプロジェクトを選択
その他はデフォルトのまま次へ
![bandicam 2023-08-12 15-00-02-000.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/f33cfabc-6f45-9e5a-61b8-d88a76007037.jpeg)

#### デプロイステージ
ビルド結果のデプロイに関する設定を行います。
今回はビルド結果をS3へ格納するため以下のように設定します。

デプロイプロバイダー：Amazon S3
バケット：先ほど作成したホスティング用バケットを選択
デプロイする前にファイルを抽出する：チェック
その他はデフォルトのまま次へ進みパイプラインを作成します。
![bandicam 2023-08-12 15-05-23-373.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/25962752-e5bf-2348-28c8-670960fc9011.jpeg)

## 実行してみる
ここまでの設定でmasterブランチへのプッシュをトリガーにしてビルド～S3バケットへのデプロイを行ってくれるはずなのでやってみましょう。

ローカルでindex.htmlの`<title>`を変更してpushします。
```public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>タイトルを変更しました。</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>
```

```bash
git add -A
git commit -m "タイトルを変更"
git push
```

コンソールからCodePipelineを確認
なんかうまいこと行ってそうな雰囲気を感じる。
![bandicam 2023-08-12 15-17-48-746.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/cc0d3bf2-dc0e-0948-955b-d1b5cca5d397.jpeg)

バケットを見に行くとbuild配下にいそうなファイル達がいますね。
![bandicam 2023-08-12 15-22-54-946.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/0882244a-3b68-72b0-f235-9dc9b3ff8fb2.jpeg)

バケットのウェブサイトエンドポイントにアクセスしてみましょう。
![bandicam 2023-08-12 15-32-30-157.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125818/79b784b4-89f9-83cf-cf6a-433f488879b0.jpeg)

しっかりタイトルの変更が反映されていますね。
これでmasterブランチが更新されると自動的にビルドしてデプロイするCI/CDパイプラインの構築ができました。


## おわりに

さて、今回はReactで作った静的ウェブサイトをS3でホスティングするまでをとってもシンプルな構成で自動化してみましたが意外とお手軽に構築できましたね。

とはいえテストを自動化したり、デプロイ先の環境をいい感じに変更したり、ECRを絡ませたり、状況に応じて通知を飛ばしたりといった複雑なことはまだまだ分からないので今後はその辺りにも触れつつお勉強をしていきたい所存であります。

## 参考
https://blog.denet.co.jp/deploy-from-codecommit-to-s3-via-codepipeline-env/#CodePipeline%E3%81%AE%E3%83%91%E3%82%A4%E3%83%97%E3%83%A9%E3%82%A4%E3%83%B3%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B

https://qiita.com/NorihitoYamamoto/items/a463c5641bc3401a4439