GitHub Actionsを使ってnuxt.jsで作成した静的WebページをS3に自動デプロイする

# はじめに
`Nuxt.js` で作成した業務用のWebアプリを、S3の `Static website hosting` で運用しているのですが、個人メンテナンス & 更新頻度が少ないといった理由で、1.手元で `yarn generate` → 2.手動でS3にアップロード → 3.手動で全ファイルを公開、というひどい運用をしていました。
そこで、先日正式リリースされたGithub Actionsを使って、自動デプロイの環境を整えたのでその備忘録です。
![deploy.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265206/f2399c6f-6fd4-fbfb-bab7-c0b41f2e5f01.gif)

# 自動デプロイの手順
1. Githubの `release` ブランチへのプッシュをトリガーにGithub Actionsを実行
2. `release` ブランチをチェックアウト
3. `python` のセットアップ
4. `awscli` のインストール
5. `nuxt` のビルド
6. 生成ファイル `dist` をS3にコピー
7. 完了をSlackに通知

# 全体の構成
実際に使用した設定ファイルを載せ、それぞれについて簡単に説明していきます。
基本的には初期テンプレートの `Node.js` および `python package` を参考にしています。
<img width="1294" alt="tempate.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265206/4fcb79b2-8c01-b852-d5f0-e66b3cb150f4.png">
また、yamlの書き方とslackへの通知方法は下記記事を参考にさせていただきました。
参考：[【GitHub】新GitHub Actionsを使ってAWS ECRにイメージをプッシュするCIを作ってみた](https://qiita.com/homines22/items/af96baa6ba51b1d59124)
参考：[GitHub Actionsを使ってAWS Lambdaへ自動デプロイ (詳説＋デモ手順付きver)](https://qiita.com/homines22/items/412d4e81b24804d75205)

```deploy.yaml
name: Auto Deploy to AWS S3

on:
  push:
    branches:
      - release

jobs:
  deploy:
    name: Deploy

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1

    - name: Setup Python 3.7 for awscli
      uses: actions/setup-python@v1
      with:
        version: '3.7'
        architecture: 'x64'

    - name: Install awscli
      run: pip install --upgrade pip awscli

    - name: Build
      run: |
        yarn install
        yarn generate

    - name: Copy to s3
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      run: aws s3 cp ./dist ${{ secrets.S3_UPLOAD_PATH }} --recursive --acl public-read

    - name: Notify to Slack
      run: curl -X POST -H 'Content-type:application/json' --data '{"text":"'"${GITHUB_REPOSITORY}"'\n【Deploy Success】"}' ${{ secrets.SLACK_WEBHOOK }}
```

# デプロイ手順とyamlの対応
## 1. 特定ブランチへのプッシュをトリガーにGithub Actionsを実行
```deploy.yaml
on:
  push:
    branches:
      - release
```
push以外にも様々なトリガーを設定することができます。
参考：[Events that trigger workflows](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows)

## 2. プッシュしたブランチをチェックアウト
```deploy.yaml
    steps:
    - uses: actions/checkout@v1
```
`uses: actions/hogehoge` は公式が用意しているアクションになります。
参考：[GitHub Actions](https://github.com/actions/)

## 3. pythonのセットアップ
```deploy.yaml
    - name: Setup Python 3.7 for awscli
      uses: actions/setup-python@v1
      with:
        version: '3.7'
        architecture: 'x64'
```

## 4. awscliのインストール
```deploy.yaml
    - name: Install awscli
      run: pip install --upgrade pip awscli
```

## 5. nuxtのビルド
```deploy.yaml
    - name: Build
      run: |
        yarn install
        yarn generate
```
複数行のコマンドは `run |` の下に続けて書くことができます。
`yarn generate` により、Webページの静的ファイルが `dist` に生成されます。


## 6. 生成ファイルdistをS3にコピー
```deploy.yaml
    - name: Copy to s3
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      run: aws s3 cp ./dist ${{ secrets.S3_UPLOAD_PATH }} --recursive --acl public-read
```
事前に`awscli` でS3にアップロードするために必要な権限を持つユーザーを作成し、そのアクセスキーIDとシークレトキーIDを使用してアップロードします。
`env` の環境変数にそれらのキーIDを設定できますが、セキュリティ上yamlに載せるのが適切でないものについては、Githubの `Setting → Secrets` に事前に登録しておくと、 `${{ secrets.HOGEHOGE }}` で取得することができます。
<img width="992" alt="secrets.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265206/858a1e41-35a1-aeb1-7504-19e72d599ae1.png">
アップロードは `aws s3 cp` コマンドを実行するだけですが、そのままWebで公開できるよう `--acl public-read` オプションを追加しています。

## 7. 完了をSlackに通知
```deploy.yaml
    - name: Notify to Slack
      run: curl -X POST -H 'Content-type:application/json' --data '{"text":"'"${GITHUB_REPOSITORY}"'\n【Deploy Success】"}' ${{ secrets.SLACK_WEBHOOK }}
```
curlで直接 `Incoming Webhooks` のURLにJSONペイロードを送信します。
通知先のチャンネルとURLはSlack側で事前に確認しておきます。
![slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265206/0fc2285b-cb30-910a-909f-aeec88296fe9.png)
↓通知結果↓
<img width="293" alt="webhock.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265206/d5b9256a-f22b-77d2-43e7-b3a2c5658301.png">

また、通知の内容や装飾は下記記事を参考に調整すると良いと思います。
参考：[SlackのIncoming Webhooksを使い倒す](https://qiita.com/ik-fib/items/b4a502d173a22b3947a0)

# まとめ
Github Actionsが正式リリースされたので使ってみたところ、非常に簡単に自動デプロイの環境を整えることができました。
本記事は私が実際に使用した内容の説明のみとなりますが、今後はテストなども追加したちゃんとしたCI/CD環境を整えたらまた記事にします。