React Typescript にて、AWSのCI/CDを使って git push → S3デプロイを実現する

クラウド

主題の通り、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 に近いイメージ

全体像

CodeCommit(git リポジトリ)① git pushEventBridge②監視→pushを検知CodePipeline(CI/CDオーケストレーション)③pushを通知(トリガー)④コードを取得⑤ビルド指示⑥コンテナ起動して、コンテナ内でビルド処理⑦ビルド生成物S3(デプロイ先)⑧デプロイ先へコピー(アップロード)CodeBuild(ビルドサーバー)

(分かりやすく描いたつもりなのに、複雑ですね・・・。なんかもっとシンプルにできないのかな・・・)

わかりにくい点としては、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」など先に決めておかないといけません

実施手順

大まかな流れは以下の通りです。

  1. 静的ホスティング設定した S3 を用意
  2. CodeCommit にてgitリポジトリを作成
  3. CodeBuild にてビルドプロジェクト(ビルド設定)を作成
  4. CodePipeline にてCI/CDのオーケストレーションのプロジェクトを作成

なお、本稿では「1.」のS3についてはCI/CDとは別の話なので説明を省略します。

CodeCommit にてgitリポジトリを作成

AWS のサービスより、「CodeCommit」で検索してサービスのページへ遷移します。

github と同じような操作感なので、リポジトリの作成方法についての説明は省略します。

問題は、CodeCommit に作成したリポジトリからの初回 fetch 時ですが、ユーザー名とパスワードを要求されます。
以下の通り、IAM から「HTTPS Git 認証情報」を作成する必要があります。

HTTPS Git 認証情報の作成方法

  1. IAM のサービスへいく
  2. 左側メニューより「ユーザー」を選択し、ログインしているユーザーを検索→選択する
  3. 「セキュリティ認証情報」タブを開く
  4. 「AWS CodeCommit の HTTPS Git 認証情報」より「認証情報を生成」を選択する
  5. 生成後、CSVファイルがダウンロードされるので、なくさないように保管する
  6. CSV内に「ユーザー名」と「パスワード」が記載されているので、git fetch 時に要求された箇所にそれぞれ入力する

CodeBuild にてビルドプロジェクト(ビルド設定)を作成

AWS のサービスより、「CodeBuild」で検索してサービスのページへ遷移します。
「プロジェクトの作成」ボタンから、プロジェクトの作成をします。

設定箇所が何か所かあるのですが、以下の点だけ入力すればよいです。

プロジェクトの設定
  • プロジェクト名に任意の値を入力

ソース
  • ソースプロバイダ: AWS CodeCommit
  • リポジトリ: 対象のリポジトリを選択
  • ブランチ: ビルド対象のブランチを選択

環境
  • オペレーティングシステム: Amazon Linux 2
  • ランタイム: Standard
  • イメージ: その時々によるのでしょうが、2023年3月時点では 4.0 が最新です。今回の案件では node v.16 を使用しているので、 4.0 を選択しました。
  • イメージのバージョン: わからないのでのですが、たぶん最新を選ぶのがいいと思います
  • 環境タイプ: 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-directorybuild となるので、そこらへんは適宜変更が必要です。(ややこしいですが、Buildspec.yml自体はリポジトリ直下固定です)

動作確認

ここでいったん、上記の Buildspec.yml が正しく動作するか確認します。

前提条件
  • CodeCommit にリポジトリがあり、ソースファイルが格納されていること
  • トリガーとなるブランチが存在すること
動作確認方法
  1. CodeBuild のサービスのトップページより、下記の通り今回作成したビルドプロジェクトを選択します。
  2. 「ビルドを開始」を押します。
  3. ビルドが開始されます。ビルド対象によるのですが、大したことないプロジェクトでも、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 トリガーでパイプラインが動いたら、成功です。

コメント

タイトルとURLをコピーしました