あらまし
GitHub Actions で Gatsby.js で生成したサイトを AWS Amplify にデプロイしたいが、 Amplify CLI のインストールをしなくともデプロイする方法が見つかったので紹介する。
広告
AWS Amplify (以下 Amplify)は、AWSのホスティングフレームワークで1つのアプリに対してフロントエンド・バックエンドそれぞれをデプロイできる。 フロントエンドはブランチごとのデプロイが可能で、本番・開発・作業ブランチなど複数のデプロイをすることが可能で、本番だけ独自ドメインを割り当ているというのも可能だ。
Amplify CLI という Node.js ベースのコマンドが用意されているが、これは比較的バックエンド寄りの機能が多くデプロイのみであればこれがなくても十分だ。
本来は GitHub と連携して Amplify の CI でビルド・デプロイをするが、諸般の事情(主に速度)により、GitHub Actions からデプロイしたくなった。 GitHub Actions には AWS CLI がデフォルトでインストールされているので、これを用いる。
手順
手順は以下の通り
準備
- AWS CLI からアプリを作成し、 appId を取得する
デプロイ
- ブランチを作成
- デプロイを作成
- デプロイの
zipUploadUrl
にzip圧縮したコンテンツをPUT - デプロイを開始
- ジョブの終了を待つ
準備
この手順は一度きりしか行わないので、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