主題の通り、ReactTypescriptのプロジェクトで、S3にデプロイするのを git push から自動化することを目指しました。
自動化するにあたり、S3 を使用するということで、必然的に親和性の高い AWS 製の CI/CD を使用して実現を図りました。
概念の理解とか、使用するツール(サービス)もいろんな選択肢があって結構困ったので、備忘録します。
やりたいこと
- React Typescript を git push で自動的に S3 にデプロイしたい
- Typescript なのでビルドが必要なのだが、ビルドも自動化に組み込みたい
選択肢となるサービス
上記のやりたいことを実現する方法としては、どうやら以下の3パターンがメジャーどころのようです。
主観にはなりますが、上の方が楽度が高いです。
# | サービスの組み合わせ | 特徴 |
---|---|---|
1 | Amplify | たぶん現在一般的にはもっとも有力視されている。ほぼ自動でアプリ作成環境ができあがる。その自動化の一環でCI/CD環境も構築される。 |
2 | CodeStar | Amplifyほどではないが、こちらも自動でCI/CD付きのアプリ作成環境ができあがるサービス。(だと思う) |
3 | CodeCommit+CodeBuild+CodePipeline | アプリ作成環境はなく、CI/CDを実現するためのサービスの組み合わせ。 |
ぶっちゃけ Amplify とかのほうが良いのでしょうが、社内のアカウントの権限の問題(Amplifyは、Amplify用のIAMユーザーの作成が必須。社内で私にはIAMユーザー作成の権限がない)があったり、そもそも開発環境自体は別で用意済みだったりしたので、候補から外しました。
また、同様に CodeStar も、今回の案件では不要なことが多いので候補から外しました。CodeStar の実態は CodeCommit+CodeBuild+CodePipeline のラッパーサービスのようなので、CodeStar を開始後に CodePipeline の設定とかいじれるのですが、不要なものを手動で削除していくのは面倒という理由になります。
ということで、今回は 3.の CodeCommit+CodeBuild+CodePipeline でCI/CD環境を構築することにしました。
CodeCommit+CodeBuild+CodePipeline による CI/CD について
使用するAWSサービス
登場人物は以下の4つになります。
サービス | 概要 |
---|---|
S3 | デプロイ先。Webアプリのホスティングサービスを担う |
CodeCommit | gitホスティングサービス。github や gitlab の AWS 版みたいな感じ |
CodeBuild | ビルドやテストを実行するためのサービス。GitLab Runner に近いイメージ |
CodePipeline | CI/CDをオーケストレーションするサービス。厳密に言うと違うが、基本的には指示だけをするイメージのサービス。GitLabCI に近いイメージ |
全体像
(分かりやすく描いたつもりなのに、複雑ですね・・・。なんかもっとシンプルにできないのかな・・・)
わかりにくい点としては、CodePipeline がデプロイしているところな気がします。デプロイ用のサービスで CodeDeploy というのがあるのですが、何故なのか S3 へのデプロイは CodePipeline でないとできない仕様のようです。(CodeDeploy は S3 に非対応)
(追記)全体像の補足
調べてみると、どうやら CodeBuild だけでも目的は達成できるみたいです。
ここら辺がややこしくなっている原因な気がするのですが、サービスごとの守備範囲が被っていることが多く、じゃあどのサービス使うのが正解なのか?というベストプラクティスがわかりづらいんですよね。
少ないサービスを使用して構築する方がいいのか?(依存関係も小さくなるし、コストも安くなるし)、それとも関心ごとを分離してそれぞれ適したサービスを適宜使用したほうがいいのか?(AWS自体が推奨している感あるし、AWSサービス間は連携しやすいし)
一応、CodePipeline を使用したほうが拡張性が高い(後からデプロイ先をS3からECSに変更とした場合など、CodePipelineにCodeDeployを追加することで対応できる)ということで、CodePipeline も使用しています。
デメリット
なお、CodeCommit+CodeBuild+CodePipeline を採用した場合の主要なデメリットは以下の通りです。
- github や gitlab といった主要なgitホスティングサービスとの相性が悪い
- 後述しますが、そもそも CodeCommit 自体がは git ホスティングサービスです
- 構築作業が多い
- (たぶん)CI/CDをトリガーするブランチは先に決めておかないといけない
- →全てのブランチをトリガー対象としたCI/CD開始ってのは、たぶんできないということです。「develop」など先に決めておかないといけません
実施手順
大まかな流れは以下の通りです。
- 静的ホスティング設定した S3 を用意
- CodeCommit にてgitリポジトリを作成
- CodeBuild にてビルドプロジェクト(ビルド設定)を作成
- CodePipeline にてCI/CDのオーケストレーションのプロジェクトを作成
なお、本稿では「1.」のS3についてはCI/CDとは別の話なので説明を省略します。
CodeCommit にてgitリポジトリを作成
AWS のサービスより、「CodeCommit」で検索してサービスのページへ遷移します。
github と同じような操作感なので、リポジトリの作成方法についての説明は省略します。
問題は、CodeCommit に作成したリポジトリからの初回 fetch 時ですが、ユーザー名とパスワードを要求されます。
以下の通り、IAM から「HTTPS Git 認証情報」を作成する必要があります。
HTTPS Git 認証情報の作成方法
- IAM のサービスへいく
- 左側メニューより「ユーザー」を選択し、ログインしているユーザーを検索→選択する
- 「セキュリティ認証情報」タブを開く
- 「AWS CodeCommit の HTTPS Git 認証情報」より「認証情報を生成」を選択する
- 生成後、CSVファイルがダウンロードされるので、なくさないように保管する
- CSV内に「ユーザー名」と「パスワード」が記載されているので、git fetch 時に要求された箇所にそれぞれ入力する
CodeBuild にてビルドプロジェクト(ビルド設定)を作成
AWS のサービスより、「CodeBuild」で検索してサービスのページへ遷移します。
「プロジェクトの作成」ボタンから、プロジェクトの作成をします。
設定箇所が何か所かあるのですが、以下の点だけ入力すればよいです。
プロジェクトの設定
- プロジェクト名に任意の値を入力
ソース
- ソースプロバイダ: AWS CodeCommit
- リポジトリ: 対象のリポジトリを選択
- ブランチ: ビルド対象のブランチを選択
環境
- オペレーティングシステム: Amazon Linux 2
- ランタイム: Standard
- イメージ: その時々によるのでしょうが、2023年3月時点では
4.0
が最新です。今回の案件では node v.16 を使用しているので、4.0
を選択しました。- 以下に dotnet や python などの対応しているバージョンとイメージの対応表があります。
- https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/available-runtimes.html
- イメージのバージョン: わからないのでのですが、たぶん最新を選ぶのがいいと思います
- 環境タイプ: Linux
上記以外は変更不要です。(Buildspecやアーティファクトもデフォルトのままでいいです)
画面下部の「ビルドプロジェクトとを作成する」ボタンを押します。
Buildspec.yml の作成
肝心のビルド設定のファイルを作成します。
この設定ファイルは、ソースリポジトリの中に含める必要があります。(通常、トップ階層直下)
CodeBuild側に記載するのではなく、CodeBuildはソースのトップ階層から Buildspec.yml
を探す仕様のようです。
なので、今回は以下のように記載しました。(ChatGPTに聞きました)
version: 0.2
phases:
install:
runtime-versions:
nodejs: 16
commands:
- echo ">>> start installing..."
- npm install -g typescript
pre_build: # ビルド実行前に実行する処理等の設定
commands:
- echo ">>> start preparing..."
- cd react
- npm install
build: # ビルド実行処理等の設定
commands:
- echo ">>> start building ..."
- npm run build
- echo ">>> success ..."
artifacts:
files:
- '**/*'
base-directory: 'react/build'
これをリポジトリに含めて、コミット→CodeCommitへプッシュする必要があります。
なお、今回のリポジトリは、 react
ディレクトリ配下に package.json
がいる構成となっています。
リポジトリ直下に package.json
がある場合は、上記の base-directory
は build
となるので、そこらへんは適宜変更が必要です。(ややこしいですが、Buildspec.yml
自体はリポジトリ直下固定です)
動作確認
ここでいったん、上記の Buildspec.yml
が正しく動作するか確認します。
前提条件
- CodeCommit にリポジトリがあり、ソースファイルが格納されていること
- トリガーとなるブランチが存在すること
動作確認方法
- CodeBuild のサービスのトップページより、下記の通り今回作成したビルドプロジェクトを選択します。
- 「ビルドを開始」を押します。
- ビルドが開始されます。ビルド対象によるのですが、大したことないプロジェクトでも、2,3分程度かかると思います。
ログが出力されるので、ここで「SUCCEEDED」になるといったんOKだと思います。
CodePipeline にてCI/CDのオーケストレーションのプロジェクトを作成
AWS のサービスより、「CodePipeline」で検索してサービスのページへ遷移します。
「パイプラインを作成する」ボタンから、プロジェクトの作成をします。
こちらも設定項目が複数ありますが、ここでは最小限やりたいことが実現できる設定をしていきます。
パイプラインの設定
- パイプライン名:任意の名前
- ロール名:自動で入力されるので触らない
ソース
- ソースプロバイダー: AWS CodeCommit
- リポジトリ: 対象のリポジトリを選択
- ブランチ: トリガーとする対象のブランチを選択
(CodeBuildと同じ設定内容なので冗長に感じます。が、たぶん CodeBuild の設定は「ビルド対象」であり、CodePipelineでの設定は「トリガー」的な棲み分けがあるのかな?と想像します(想像です))
補足すると、トリガー検知は CloudWatch Events がやる仕組みのようです。Pipeline は CloudWatch Events のイベントをサブスクライブして動作する感じのようですね。
また、「アーティファクト」という単語は、イメージ的には「次のステップへ引き渡すデータ」という認識です。
構築する – オプショナル
- プロバイダーを構築する:AWS CodeBuild
- プロジェクト名:上記で作成した CodeBuild のプロジェクトを選択
デプロイ – オプショナル
ここで、デプロイ先を指定します。
ここまでは CodePipeline がオーケストレーションするサービスを選択して組み合わせていたのですが、ここだけ CodePipeline 自体が処理を実行するための設定をします。(CodePipeline がデプロイ処理をするということです)
- デプロイプロバイダー: Amazon S3
- バケット:デプロイ先となるバケットを選択
- デプロイする前にファイルを抽出するにチェックを入れる ←ここ重要
上記設定で、そのまま「パイプラインを作成する」ボタンを押します。
下記のような感じで、自動で初回パイプラインがスタートします。
設定がうまくいっていれば、この段階で S3 にビルドデータがデプロイされます!
最終動作確認
上記で設定は完了です。
後は、実際に CodeCommit あてに対象のブランチに新しいコミットをして push してみます。
push トリガーでパイプラインが動いたら、成功です。
コメント