S3とCloudFrontでホストしたNuxt.js(SPA)アプリをGitHub Actionsでデプロイする

S3とCloudFrontで静的サイトを配信

こちらは割愛します。



SPAリロード対策の403リダイレクトは入れておきましょう。

GitHub Actionsの設定

デプロイ用のIAMユーザーを作成

先にGitHub Actionsが使う、デプロイ用のIAMユーザーを作成しアクセスキーを発行しておきます。

ポリシーには以下をセット。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::my-nuxt-app",
                "arn:aws:s3:::my-nuxt-app/*"
            ]
        },
        {
            "Sid": "CloudFront",
            "Effect": "Allow",
            "Action": [
                "cloudfront:CreateInvalidation",
                "cloudfront:GetDistribution",
                "cloudfront:GetInvalidation",
                "cloudfront:GetStreamingDistribution",
                "cloudfront:GetDistributionConfig",
                "cloudfront:ListDistributions",
                "cloudfront:ListInvalidations",
                "cloudfront:ListStreamingDistributions"
            ],
            "Resource": "*"
        }
    ]
}
デプロイ時に必要となる対象のS3バケットへの操作とCloudFrontへのインバリデーションを許可しています。

デプロイ定義

デプロイ定義を作成しNuxt.jsアプリの入ったリポジトリにプッシュします。

.github/workflows/deploy.yml
name: deploy

on:
  push:
    branches:
      - main
      - master
  pull_request:
    branches:
      - main
      - master

jobs:
  ci:
    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os: [ubuntu-latest]
        node: [14]

    steps:
      - name: Checkout 🛎
        uses: actions/checkout@master

      - name: Setup node env 🏗
        uses: actions/setup-node@v2.1.2
        with:
          node-version: ${{ matrix.node }}

      - name: Get yarn cache directory path 🛠
        id: yarn-cache-dir-path
        run: echo "::set-output name=dir::$(yarn cache dir)"

      - name: Cache node_modules 📦
        uses: actions/cache@v2
        id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-

      - name: Install dependencies 👨🏻‍💻
        run: yarn

      - name: Run linter 👀
        run: yarn lint

      - name: Generate dist 🔨
        run: yarn generate

      - name: S3 Sync
        # You may pin to the exact commit or the version.
        # uses: jakejarvis/s3-sync-action@be0c4ab89158cac4278689ebedd8407dd5f35a83
        uses: jakejarvis/s3-sync-action@v0.5.1
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
          AWS_REGION: 'ap-northeast-1'
          SOURCE_DIR: 'dist'

      - name: invalidate cloudfront
        uses: chetan/invalidate-cloudfront-action@master
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          DISTRIBUTION: ${{ secrets.AWS_CF_DISTRIBUTION }}
          PATHS: '/*'
mainかmasterブランチへプッシュまたはプルリクマージが入ると、ビルドが走り、distディレクトリに出来上がった静的ソースをS3にsync、最後にCloudFrontディストリビューションをインバリデーションするという流れです。

シークレットの設定

GitHub Actionsで使うシークレット情報を登録します。

作ったIAMのアクセスキーとS3バケット、CloudFrontディストリビューションIDを設定します。


これで設定は完了です。

ブランチにプッシュするとデプロイが走り、プッシュしたコードがサイトに反映されれば成功です。
他のSPAフレームワークでもデプロイするディレクトリを変えればそのまま使えるはずです。多分。