GitHubActions+S3+CloudFrontでキャッシュクリアしてSPAをデプロイする


はじめに

ここでやってること

  1. 前回はDockerでsvelteの開発環境を作成しました
  2. 今回は、svelteをGitHubにpushしたら、GitHubActionsがbuildしてS3にアップロード & CloudFrontのキャッシュ消去して配信します(svelteでなくても設定自体は可能です)

AWSの設定

1. S3にアップロード用のバケットを作成

今回はCloudFrontで配信するので「パブリックアクセスをすべてブロック」して作成します。
この記事ではsvelte-spaというバケット名で作成しています。
(よくこのシンプルな名前で取れたな...

2. CloudFrontを設定

Create Distribution > Web(Get Startedボタンクリック)

  • Restrict Bucket Access : S3へのアクセスを不可にするためYesを選択
  • Grant Read Permissions on Bucket : CloudFrontからS3バケットへの読み取りを許可する権限設定をしてもらうためYesを選択

3. デプロイ用のIAMポリシーを作成

  • Action
    • s3:PutObject : S3にbuildした成果物をアップロードするため
    • s3:ListBucket : アップロード先のバケットを取得するため
    • cloudfront:CreateInvalidation : キャッシュクリアするため。Invalidationは無効化という意味
  • Resource
    • arn:aws:cloudfront : 先に設定したCloudFrontの詳細でARNを確認できます
    • arn:aws:s3 : 先に作成したバケットそのものとその配下すべて
IAMポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:ListBucket",
                "cloudfront:CreateInvalidation"
            ],
            "Resource": [
                "arn:aws:cloudfront::123456789012:distribution/EDFDVBD6EXAMPLE",
                "arn:aws:s3:::<INPUT-YOUR-BUCKET>/*",
                "arn:aws:s3:::<INPUT-YOUR-BUCKET>"
            ]
        }
    ]
}

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

  1. 先に作成したIAMポリシーをアタッチしたグループを作成(ここではsvelte-deployグループとする)
  2. 先のグループに属するIAMユーザーを作成(ここではsvelte-deployerユーザーとする)
    • 作成時に表示されるAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYは後で使うのでメモしておいてください

5. GitHubに設定するSecrets情報をメモ

  1. デプロイ用のIAMユーザーsvelte-deployerAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY
  2. CloufFrontのDistribution ID
  3. 上記のAWSリソースを作成したAWSリージョン

GitHubのの設定

Secrets情報の設定

Settings > Secrets から追加

  • AWS_ACCESS_KEY_ID : IAMユーザー作成時に取得した値
  • AWS_SECRET_ACCESS_KEY : IAMユーザー作成時に取得した値
  • DISTRIBUTION : CloudFrontの詳細画面から取得したDistribution IDの値
  • AWS_REGION :

Actionsの設定

ついに来ました...

Github Actions > set up a workflow yourself をクリック

ymlに下記の設定をします。

.github/workflows/main.yml
name: CI

# トリガーの設定
on:
  push:
    branches: [ master ]

# ジョブの設定(直列に動かしたり並行に動かしたり指定できる)
# 今回はbuildジョブとdeployジョブの2つを設定します
jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [14.5.0]

    steps:
    # masterブランチをチェックアウト
    - uses: actions/checkout@v2
    # nodeでパッケージをインストール&ビルド
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    - run: npm install
    - run: npm run build
    # ビルド結果をdeployジョブに渡すためにアップロード
    - name: Upload build result
      uses: actions/upload-artifact@v1
      with:
        name: build
        path: public/

  deploy:
    # ジョブは並行で動くので前後関係の指定が必要
    needs: build

    runs-on: ubuntu-latest

    steps:
    # ビルド結果をダウンロード
    - name: Download build result
      uses: actions/download-artifact@v2
      with:
        name: build
        path: public/
    # S3にアップロード
    - name: Publish to AWS S3
      uses: opspresso/action-s3-sync@master
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        AWS_REGION: ${{ secrets.AWS_REGION }}
        FROM_PATH: "public/"
        DEST_PATH: "s3://svelte-spa"
    # CloudFrontのキャッシュクリア
    - name: Clear cache in CloudFront
      uses: chetan/[email protected]
      env:
        DISTRIBUTION: ${{ secrets.DISTRIBUTION }}
        PATHS: "/*"
        AWS_REGION: ${{ secrets.AWS_REGION }}
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

動作確認

何かしらmasterに変更を加えてプッシュしてみます。

GitHub Actionsのページを確認

  • 成功したことを確認できます
  • 失敗した場合、ログを確認しながら調整してください

S3にビルド結果が保存されていることを確認

CloudFrontのエンドポイントにブラウザからアクセス

CloudFrontのドメイン名+index.htmlでアクセス

  • 成功です!
  • 再度、masterに変更を加えても自動デプロイされてることが確認できました!!

結びの言葉

何でこれしたの?

技術を触れるにつけて、ただやってみたい!という想いだけだと、現場の推進力にはなれないなと、自分の中で最近思うようになりました。やはり、どうやって導入するの?とかリリース作業はどうするの?とか、、、技術単体で完結しない難しさがあります。
じゃあ、自分にそのスキルがあるか?と自問すると、、、無かった。
なので、まずはミニマムでもリリースするまでの感覚を養いたいなと思い着手しました。

後日、テストのジョブを組み込んで、エラーならチャット通知をして、CI/CDのレベルアップが必要だなと思います。

参考