【GitHub Actions】Next.jsプロジェクトを自動でビルド→EC2にデプロイする仕組み作ってみた

## はじめに
こんにちは、皆さんは普段どうやってデプロイをしていますか？
オンプレ、AWS、GCP…デプロイ先の環境は様々だと思いますが、デプロイが自動化されているプロジェクトの方が多いのではないでしょうか。
自分も仕事の環境ではAWSに自動でデプロイされる仕組みになっています。
今日はそんな仕組みを個人開発環境にも導入してみようかと思います。

## 設計

▼デプロイするもの
[この記事](https://qiita.com/Ryukuu0919/items/574b989c2ca3dea31693)で作成したTodoアプリ（Next.jsで静的なwebアプリ）

▼デプロイ先
AWSのEC2

▼CI/CDツール
GitHub Actions

▼デプロイの流れ
対象リポジトリのmainブランチにpushされたら、ビルドが実行され静的ファイルをEC2にデプロイする

## Github Actionsとは
github上の様々なアクションをきっかけに、あらかじめ設定しておいた動作を行ってくれる機能です。（雑まとめ）
なのでmainブランチに何かしらpushされることをトリガーに、next.jsのビルドをしてEC2にデプロイするよ～と設定してあげることによって今回の目的を達成しようと思います。


## 実装

### ■Githubの対象リポジトリにEC2に接続するための情報を登録する

▼手順
・対象リポジトリ>「setting」>「Sercrets and variables」>「Actions」>「Secretsタブ」>「New repository secret」で以下を追加
| NAME | VALUE |
|:-|:-|
| EC2_USER  | EC2に接続する際のユーザ名（多分ec2-userになってるはず）  |
| EC2_HOST | EC2に接続する際のパブリック IPv4 DNS |
| SSH_PRIVATE_KEY |  EC2に接続する際のキーペア |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3577451/e52f890c-9046-808b-37a9-61b16f5d3441.png)

### ■GitHub Actionsのワークフロー設定
GitHub Actionsはどうやら対象リポジトリ直下に/.github/workflows/をいうディレクトリを作り、その中にいろいろと設定を書いたテンプレートファイルを置けば設定できるらしい。
ということで書いてみました。


```deploy.yml
name: Build and Deploy
on:
  push:
    branches:
      - main    // ここでmainブランチにpushされた時にgithubActionsがトリガーされるよと定義している

jobs:
  build_and_deploy:
    runs-on: ubuntu-latest    // githubActionsがどんな環境で動くか指定。今回はビルドしてEC2へのデプロイができればいいのでubuntuにしておきます。

    steps:
      - name: Checkout code
        uses: actions/checkout@v2    // おまじない。githubActions上でこのリポジトリのコード使うよ～とチェックアウトする…みたいな意味らしい。

      - name: Setup Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '20'   // Next.jsをビルドするのでNext.jsのセットアップをする（App Routerを使用するならnodeが古いバージョンだとエラーになるので注意）

      - name: Install Dependencies
        run: |
          cd 【package.jsonまでのパス】   // package.jsonがある場所まで移動する。（他の人もそうなのかわからないが自分の場合「/home/runner/work/自分で作ったルートディレクトリ」となっていた）
          npm install

      - name: Build
        run: |
          cd 【package.jsonまでのパス】
          npm run build   // ビルドします。SSGの場合静的ファイルはoutってフォルダに出力される
          
      - name: Deploy to EC2
        env:
          PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}   // 上で設定したシークレットの情報
          HOST: ${{ secrets.EC2_HOST }}
          USER: ${{ secrets.EC2_USER }}
        run: |
          cd 【package.jsonまでのパス】
          echo "$PRIVATE_KEY" > private_key
          chmod 600 private_key
          scp -o StrictHostKeyChecking=no -i private_key -r ./out $USER@$HOST:/var/www/html/   // scpコマンドでEC2にoutディレクトリの中身をコピーしてる
          rm -f private_key

```


### ※注意
Next.js14でSSGとしてビルドするためには、 `next.config.js` に `output: 'export'` を追加してSSG を有効化しなければいけないみたいです。※僕はここでめっちゃくちゃ詰まりました。
こうすれば静的ファイルがoutディレクトリに出力されます。
（Next.js 13.2以前では`next export`というコマンドで静的ファイルを出力していた）

```next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export'
}

module.exports = nextConfig
```


### EC2のドキュメントルートを変更する
上記だとEC2の`/var/www/html/`に`out`ディレクトリが出力され、その中に静的ファイルが入っています。このままだと`http://【ドメイン】/out/`でindex.htmlは確認できますが、パスが合ってないためcssやjsが読み込まれていません。
そのためEC2に入ってドキュメントルートを`/var/www/html/out/`に変えてください。


## 実行してみる
ここまで実装出来たらmainブランチに何か適当な変更をpushしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3577451/c10b45db-be12-1fa9-55bb-5e83ecca9658.png)

Github>Actoinsから実行結果が確認できます。

失敗していた場合は各ステップのどこで失敗したかわかるようになっているので、成功するまでトライ＆エラーを繰り返しましょう、、、！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3577451/5e4a54a0-0b72-4437-e3f0-22cef0bb3be5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3577451/96a38389-17a4-dff1-1e13-372610a6377c.png)


成功していたらEC2のドメイン（またはIpアドレス）をたたいてみます。

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3577451/9b889f5d-418c-f4d1-b1f1-71bbb811f0ce.gif)

デプロイできてるぞおおおおおお、、、、！！


## まとめ
実際に触ってみた感想としては、エラーの表記もわかりやすいし意外と取っ付きやすい機能だなと感じました。
今後はテストやフォーマットチェックなどもCI/CDの中に含めていきたいなあと思いました。
自動化を極めて怠惰（誉め言葉）なエンジニアを目指しましょう、、！


## 参考文献
https://developers.play.jp/entry/2023/11/06/085943?utm_source=feed
https://qiita.com/kubota_ndatacom/items/1055df9b1568b86ddb41