DEVGRU

プログラミングと競馬予想について書きます

Amplify CLI を使わずに AWS CLI だけで Amplify Hosting にデプロイする

あらまし

GitHub ActionsGatsby.js で生成したサイトを AWS Amplify にデプロイしたいが、 Amplify CLI のインストールをしなくともデプロイする方法が見つかったので紹介する。

広告

AWS Amplify (以下 Amplify)は、AWSのホスティングフレームワークで1つのアプリに対してフロントエンド・バックエンドそれぞれをデプロイできる。 フロントエンドはブランチごとのデプロイが可能で、本番・開発・作業ブランチなど複数のデプロイをすることが可能で、本番だけ独自ドメインを割り当ているというのも可能だ。

Amplify CLI という Node.js ベースのコマンドが用意されているが、これは比較的バックエンド寄りの機能が多くデプロイのみであればこれがなくても十分だ。

本来は GitHub と連携して Amplify の CI でビルド・デプロイをするが、諸般の事情(主に速度)により、GitHub Actions からデプロイしたくなった。 GitHub Actions には AWS CLI がデフォルトでインストールされているので、これを用いる。

手順

手順は以下の通り

準備

  1. AWS CLI からアプリを作成し、 appId を取得する

デプロイ

  1. ブランチを作成
  2. デプロイを作成
  3. デプロイの zipUploadUrl にzip圧縮したコンテンツをPUT
  4. デプロイを開始
  5. ジョブの終了を待つ

準備

この手順は一度きりしか行わないので、AWSコンソールからしても良いが、その場合はなにか初回デプロイ用のファイルを用意しないと先へ進めなかった。

AWS CLI からは以下の手順でアプリを作成する。

aws amplify create-app --name my-app | tee app.json

戻り値の中に appId があるため、これを保存しておく。

デプロイ

まずはアプリの中にブランチを作成する。

aws amplify create-branch --app-id appId --branch-name my-branch-name

Amplify ではブランチごとにデプロイされURLが割り当てられ、ブランチに対してデプロイを行うとURLの内容が更新される仕組みになっている。 本番用、開発用などの用途で分けて作ると良い。

GitHub Actions の場合、PR が立っている Git ブランチへの更新でトリガーしてデプロイするとデプロイ、といった作りにするが、 その場合は、以下のように「なければ作る」ようにすれば良い。

aws amplify get-branch --app-id appId --branch-name my-branch-name || aws amplify create-branch --app-id appId --branch-name my-branch-name

次に、ブランチに対してデプロイを作成する。

aws amplify create-deployment --app-id appId --branch-name my-branch-name | tee deployment.json

デプロイを作成すると Zip ファイルをアップロードするためのURLが zipUploadUrl に、デプロイを実行するジョブの状況を取得するためのジョブ ID が jobId にそれぞれ返されるので、それを保存する。

今回は Gatsby.js だが、React でも Vue でも Angular でも、静的ウェブページと呼ばれるHTML/JS/CSS/画像の塊なら Amplify にデプロイ可能なので、それぞ Zip ファイルに固めておく(ここでは artifacts.zip としておく)。

zipUploadUrl に対して zip ファイルを PUT で送信する。

curl -X PUT zipUploadUrl --data-binary @artifacts.zip

デプロイの準備が完了したので、デプロイを開始する。

aws amplify start-deployment  --app-id appId --branch-name my-branch-name --job-id jobId

一定時間待つ必要はあるが、デプロイはさほど時間も立たずに終わる。 ジョブが終了したのを確認できれば完了となる。

while [[ "$(aws amplify get-job --app-id appId --branch-name my-branch-name --job-id jobId | jq -r '.job.summary.status')" =~ ^(PENDING|RUNNING)$ ]]; do sleep 1; done

デプロイしたあとのURLは、アプリの defaultDomain とブランチの displayName を組み合わせた URL になる。

現在は、以下のようなスクリプトを使用してデプロイを行っている。

APP_ID=app-id # aws amplify create-app で取得
BRANCH=branch-name

aws amplify get-branch --app-id $APP_ID --branch-name $BRANCH || aws amplify create-branch --app-id $APP_ID --branch-name $BRANCH
aws amplify create-deployment --app-id $APP_ID --branch-name $BRANCH > deployment.json
JOB_ID=$(jq -r .jobId < deployment.json)
ZIP_UPLOAD_URL=$(jq -r .zipUploadUrl < deployment.json)
curl -X PUT $ZIP_UPLOAD_URL --data-binary @artifacts.zip
aws amplify start-deployment --app-id $APP_ID --branch-name $BRANCH --job-id $JOB_ID
while [[ "$(aws amplify get-job --app-id $APP_ID --branch-name $BRANCH --job-id $JOB_ID | jq -r '.job.summary.status')" =~ ^(PENDING|RUNNING)$ ]]; do sleep 1; done

BRANCH_DISPLAY_NAME=$(aws amplify get-branch --app-id $APP_ID --branch-name $BRANCH | jq -r .branch.displayName)
DEFAULT_DOMAIN=$(aws amplify get-app --app-id $APP_ID  | jq -r .app.defaultDomain)
URL="https://${BRANCH_DISPLAY_NAME}.${DEFAULT_DOMAIN}/"
echo "URL: $URL"

また、PRをクローズした際にはブランチを削除する必要があるため、以下のコマンドで削除している。

aws amplify get-branch --app-id $APP_ID --branch-name $BRANCH

なお、上記を実行する際は以下の IAM Policy が必要となるので、CIで実行する際は予め用意しておく必要がある。

  • amplify:CreateBranch
  • amplify:CreateDeployment
  • amplify:DeleteBranch
  • amplify:GetApp
  • amplify:GetBranch
  • amplify:GetJob
  • amplify:StartDeployment

参考: - https://docs.aws.amazon.com/ja_jp/cli/latest/reference/amplify/index.html#cli-aws-amplify