🎍

Next.jsで作成したLPをGithubActionsでS3にアップする方法

2023/01/02に公開

個人開発のアプリの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プロバイダの作成に関しては以下の記事が分かりやすいのでご確認ください。
https://zenn.dev/kou_pg_0131/articles/gh-actions-oidc-aws#1.-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 は以下のようにしました。

.github/workflows/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については以下参照

https://qiita.com/mstssk/items/8759c71f328cab802670

  • aws s3 syncコマンドに--size-onlyを指定
    --size-onlyオプションなしだとファイルの作成時刻で更新が必要か判断するらしく、変更を加えてない画像や動画が毎回更新されていたので--size-only オプションをつけてサイズが変わってなければ更新しないようにしました。
    詳細は以下参照

https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html

まとめ

以上でNext.jsで作成したLPをGithubActionsでS3にアップする方法のまとめは終わりです。

GithubActionsを使う前はローカルでビルドしてそれを手動でS3にアップしてCloudFrontのキャッシュを削除してとやっていました。それがGithubActionsを使うとマージするだけで全てやってくれるのでかなり楽になりました。しかも時間制限はあれど無料で使えるのはありがたいですね。

https://docs.github.com/ja/billing/managing-billing-for-github-actions/about-billing-for-github-actions

最後に今回紹介した方法でデプロイしているLPのリンクを貼っておきます。
https://tm-board.hj-pg.com/jp
アプリはReactNativeで作成しています。もし良ければ使ってみてください。

Discussion