Next.jsで作成したLPをGithubActionsでS3にアップする方法
個人開発のアプリのLPをGithubActionsでS3にアップしてCloudFrontのキャッシュ削除までできるようにしたので、その方法をまとめます。
package.json修正
まずはpackage.jsonのbuildコマンドを以下のように修正します。
"build": "next build && next export",
こうすることで、npm run build
を実行するとroot直下にout
ディレクトリが生成されるようになります。このout
ディレクトリの中身をS3に上げます。
build後に、npx serve out
を実行し、画面にアクセスできればOKです。
AWS設定① IDプロバイダを作成
GitHubActionsでOIDCを使用したAWSの認証を行うため、AWSのコンソールにログインし、IDプロバイダを作成します。
※ OIDCを使用した認証の方が従来のアクセスキー等を環境変数に設定して使用する方法よりセキュリティ面で良いです。
IDプロバイダの作成に関しては以下の記事が分かりやすいのでご確認ください。
AWS設定① GitHubActionsで使用するIAMロールを作成
GitHubActionsでS3にアップしたりCloudFrontのキャッシュを削除したりするために、その権限を持ったIAMロールを作成する必要があります。権限は以下のようにしました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3Upload",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::{バケット名}",
"arn:aws:s3:::{バケット名}/*"
]
},
{
"Sid": "CloudFrontDeleteCache",
"Effect": "Allow",
"Action": [
"cloudfront:GetDistribution",
"cloudfront:GetDistributionConfig",
"cloudfront:ListDistributions",
"cloudfront:ListStreamingDistributions",
"cloudfront:CreateInvalidation",
"cloudfront:ListInvalidations",
"cloudfront:GetInvalidation"
],
"Resource": "arn:aws:cloudfront::{アカウントID}:distribution/{CloudFrontのID}"
}
]
}
さらにGithubActionsでこのロールを使用するため、信頼ポリシーを以下のように設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Federated": "{↑で作成したIDプロバイダのARN}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:{githubのユーザー名}/{githubのレポジトリ名}:ref:refs/heads/main"
}
}
}
]
}
GithubActionsのワークフロー作成
最後にワークフローを作成します。root直下に .github
ディレクトリを作成し、その下にworkflows
ディレクトリを作成、そしてその下にbuild-and-deploy.yml
を作成しました。これだけでgithub actionsが動くようになります。
build-and-deploy.yml
は以下のようにしました。
name: build-and-deploy
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
id-token: write
contents: read
steps:
- name: Setup aws
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: 'ap-northeast-1'
role-to-assume: '{↑で作成したIAMロールのARN}'
- name: Checkout
uses: actions/checkout@v2
- name: Cache
uses: actions/cache@v3
with:
path: |
~/.npm
${{ github.workspace }}/.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
- name: Setup node
uses: actions/setup-node@v3
with:
node-version-file: .nvmrc
cache: npm
- name: Install package
run: npm ci
- name: Build
run: npm run build
- name: Deploy
run: |
aws s3 sync --region ap-northeast-1 ./out s3://{S3のバケット名} --delete --size-only
aws cloudfront create-invalidation --region ap-northeast-1 --distribution-id {CloudFrontのid} --paths "/*"
ちょっとした解説や注意点を以下に箇条書きでまとめます。
- mainブランチにマージされたときにワークフローが実行されるように以下のようにしています。
on:
push:
branches:
- main
- 無料枠で使えるのは1ヶ月2000時間なので万が一に備えtimeout-minutesを設定
- .nvmrcの値にあったnodeのバージョンを指定
以下のようにnode-version-file
に.nvmrc
を指定している。普通にnode-version: 16
みたいに指定することも可能
- name: Setup node
uses: actions/setup-node@v3
with:
node-version-file: .nvmrc
cache: npm
- npm ciでインストール
npm install
でも大丈夫。npm ci
については以下参照
-
aws s3 sync
コマンドに--size-only
を指定
--size-only
オプションなしだとファイルの作成時刻で更新が必要か判断するらしく、変更を加えてない画像や動画が毎回更新されていたので--size-only オプションをつけてサイズが変わってなければ更新しないようにしました。
詳細は以下参照
まとめ
以上でNext.jsで作成したLPをGithubActionsでS3にアップする方法のまとめは終わりです。
GithubActionsを使う前はローカルでビルドしてそれを手動でS3にアップしてCloudFrontのキャッシュを削除してとやっていました。それがGithubActionsを使うとマージするだけで全てやってくれるのでかなり楽になりました。しかも時間制限はあれど無料で使えるのはありがたいですね。
最後に今回紹介した方法でデプロイしているLPのリンクを貼っておきます。
アプリはReactNativeで作成しています。もし良ければ使ってみてください。
Discussion