1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

microCMSとNuxt3で作ったLPをさくらサーバーに自動デプロイする(GitHub Actions編)

Posted at

microCMSとNuxt3で作ったLPをさくらサーバーに自動デプロイする(GitHub Actions編)

はじめに

前回の記事では、シェルスクリプトを使って手動でデプロイする方法を紹介しました。

前回の記事: シェルスクリプト編

今回は、そのシェルスクリプトをベースに、GitHub Actionsで自動デプロイを実現しました!
mainブランチやstgブランチにpushするだけで、自動的にさくらサーバーにデプロイされるようになりました😸

手動デプロイから完全に解放されて、開発に集中できる環境が整いました!

背景

シェルスクリプト編では、Dockerコンテナから手動でdeploy.shを実行していました。
でも、本当は「コードをpushしたら自動でデプロイされる」のが理想ですよね。

特に、microCMSの記事更新をトリガーにして自動デプロイしたいという要望がありました。
microCMSからWebhookを受け取って、GitHubのrepository_dispatchイベントを発火させる仕組みを作ったので、CMSを更新するだけでLPも自動で更新されるようになりました!

シェルスクリプト編で作ったdeploy.shは、環境変数で設定を切り替えられるようになっていたので、GitHub Actionsでもそのまま流用できました。ありがたや🙏

使用技術・環境

  • フレームワーク: Nuxt.js 3
  • ビルド: SSG(静的サイト生成)
  • デプロイ先: さくらサーバー
  • CI/CD: GitHub Actions
  • 転送方法: rsync(SSH経由)
  • トリガー:
    • main/stgブランチへのpush
    • repository_dispatch(microCMSのWebhookから)

GitHub Actionsワークフローの全体像

まずは完成した.github/workflows/deploy.ymlの全体像です。

.github/workflows/deploy.yml
name: 'Nuxt3 LP Deploy'

on:
  push:
    branches:
      - main
      - stg
  repository_dispatch:
    types: 
      - update

jobs:
  'Deploy':
    runs-on: 'ubuntu-latest'
    steps:
      - name: 'Checkout repository'
        uses: 'actions/checkout@v4'
      
      - name: 'Copy package.json'
        run: |
          cp package.json /tmp/package.json
          cat /tmp/package.json
      
      - name: 'Setup Node.js'
        uses: 'actions/setup-node@v4'
        with:
          node-version: '20'
          cache: 'npm'
      
      - name: 'Set config'
        run: |
          echo "MICROCMS_SERVICE_DOMAIN=your_service_domain" >> $GITHUB_ENV
          echo "MICROCMS_API_KEY=${{ secrets.MICROCMS_API_KEY }}" >> $GITHUB_ENV
          mkdir -p ~/.ssh
          echo "${{ github.ref_name }}"
          case ${{ github.ref_name }} in
            'master'|'main')
              cat prod/.env.prod >> $GITHUB_ENV
              echo "${{ secrets.PROD_SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
              ssh-keyscan -H ${{ vars.PROD_REMOTE_HOST }} >> ~/.ssh/known_hosts
              ;;

            'stg')
              cat stg/.env.stg >> $GITHUB_ENV
              echo "${{ secrets.STG_SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
              ssh-keyscan -H ${{ vars.STG_REMOTE_HOST }} >> ~/.ssh/known_hosts
              ;;
             
          esac
          chmod 600 ~/.ssh/deploy_key

      - name: 'Install dependencies'
        run: |
          npm install
          npm list

      - name: 'Run Deploy.sh'
        env:
          SSH_KEY_PATH: ~/.ssh/deploy_key
        run: |
          case ${{ github.ref_name }} in
            'master'|'main')
              REMOTE_USER="${{ vars.PROD_REMOTE_USER }}"
              REMOTE_HOST="${{ vars.PROD_REMOTE_HOST }}"
              REMOTE_TARGET_DIR="${{ vars.PROD_REMOTE_TARGET_DIR }}"
              ;;
            'stg')
              REMOTE_USER="${{ vars.STG_REMOTE_USER }}"
              REMOTE_HOST="${{ vars.STG_REMOTE_HOST }}"
              REMOTE_TARGET_DIR="${{ vars.STG_REMOTE_TARGET_DIR }}"
              ;;
            *)
              echo "Skip deployment for branch: ${{ github.ref_name }}"
              exit 0
              ;;
          esac
          set -eu

          echo "Deploying..."
          echo "-----------------------------------"

          echo "Build process started"
          echo "Command: npm run generate"
          npm run generate

          echo "Build completed successfully!"
          echo "-----------------------------------"

          echo "Start transferring build metadata files..."

          echo "Creating necessary directories..."
          ssh -i ${SSH_KEY_PATH} ${REMOTE_USER}@${REMOTE_HOST} "mkdir -p ${REMOTE_TARGET_DIR}/_nuxt/builds/meta"

          echo "Transferring metadata files..."
          rsync -vz --ignore-existing \
            -e "ssh -i ${SSH_KEY_PATH} -p 22" \
            ".output/public/_nuxt/builds/meta/" \
            "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_TARGET_DIR}/_nuxt/builds/meta/"

          echo "Metadata files transferred successfully"
          echo "-----------------------------------"

          echo "Transferring generated files to the server..."
          echo "Transfer destination: ${REMOTE_HOST}"
          rsync -avz --delete \
            -e "ssh -i ${SSH_KEY_PATH} -p 22" \
            ".output/public/" \
            "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_TARGET_DIR}"

          echo "-----------------------------------"
          echo "Deployment completed successfully!"
          echo "Check the site update"

ワークフローの処理フロー

このワークフローは大きく分けて次のステップで構成されています:

  1. リポジトリのチェックアウト
  2. Node.js環境のセットアップ
  3. 環境変数とSSH鍵の設定(本番/ステージングの分岐)
  4. 依存関係のインストール
  5. デプロイの実行(シェルスクリプトと同じ処理)

それぞれ詳しく見ていきます。

1. トリガーの設定

on:
  push:
    branches:
      - main
      - stg
  repository_dispatch:
    types: 
      - update

ワークフローは次の2つのタイミングで実行されます:

  • ブランチへのpush: mainまたはstgブランチにpushしたとき
  • repository_dispatch: microCMSのWebhookなどから、GitHub API経由でrepository_dispatchイベントを発火させたとき

repository_dispatchを使うことで、GitHub以外の外部サービス(この場合はmicroCMS)からも自動デプロイをトリガーできます。

2. リポジトリのチェックアウト

- name: 'Checkout repository'
  uses: 'actions/checkout@v4'

GitHub Actionsでワークフローを実行するために、リポジトリのコードをチェックアウト(取得)します。

actions/checkout@v4は、GitHub公式のアクションで、リポジトリのコードを取得するためのものです。

3. Node.js環境のセットアップ

- name: 'Setup Node.js'
  uses: 'actions/setup-node@v4'
  with:
    node-version: '20'
    cache: 'npm'

Node.js 20をセットアップし、npmのキャッシュも有効化します。
cache: 'npm'により、依存関係のインストールが高速化されます(package-lock.jsonを元にキャッシュを使い回します)。

3. 環境変数とSSH鍵の設定(本番/ステージングの分岐)

- name: 'Set config'
  run: |
    echo "MICROCMS_SERVICE_DOMAIN=your_service_domain" >> $GITHUB_ENV
    echo "MICROCMS_API_KEY=${{ secrets.MICROCMS_API_KEY }}" >> $GITHUB_ENV
    mkdir -p ~/.ssh
    case ${{ github.ref_name }} in
      'master'|'main')
        cat prod/.env.prod >> $GITHUB_ENV
        echo "${{ secrets.PROD_SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
        ssh-keyscan -H ${{ vars.PROD_REMOTE_HOST }} >> ~/.ssh/known_hosts
        ;;
      'stg')
        cat stg/.env.stg >> $GITHUB_ENV
        echo "${{ secrets.STG_SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
        ssh-keyscan -H ${{ vars.STG_REMOTE_HOST }} >> ~/.ssh/known_hosts
        ;;
    esac
    chmod 600 ~/.ssh/deploy_key

ここが重要なポイントです!

  • ブランチに応じた環境分岐: github.ref_name(現在のブランチ名)で、本番環境(main)とステージング環境(stg)を自動的に切り替えます
  • 環境変数ファイルの読み込み:
    • cat prod/.env.prod(またはcat stg/.env.stg)で、プロジェクトルートのprod/.env.prod(またはstg/.env.stg)ファイルから環境変数を読み込んで$GITHUB_ENVに追加
    • このファイルはオプションです。存在しない場合はエラーになるため、必要に応じて空ファイルを作成するか、この行を削除してください
  • SSH鍵の設定:
    • GitHub Secretsに保存したSSH秘密鍵を~/.ssh/deploy_keyに書き出し
    • ssh-keyscanでサーバーのホスト鍵をknown_hostsに登録(初回接続時の確認をスキップ)
    • chmod 600で鍵のパーミッションを設定(SSH接続には必須)

4. 依存関係のインストール

- name: 'Install dependencies'
  run: |
    npm install
    npm list

package.jsonに基づいて依存関係をインストールします。
npm listでインストールされたパッケージを確認(デバッグ用)。

5. デプロイの実行

- name: 'Run Deploy.sh'
  env:
    SSH_KEY_PATH: ~/.ssh/deploy_key
  run: |
    case ${{ github.ref_name }} in
      'master'|'main')
        REMOTE_USER="${{ vars.PROD_REMOTE_USER }}"
        REMOTE_HOST="${{ vars.PROD_REMOTE_HOST }}"
        REMOTE_TARGET_DIR="${{ vars.PROD_REMOTE_TARGET_DIR }}"
        ;;
      'stg')
        REMOTE_USER="${{ vars.STG_REMOTE_USER }}"
        REMOTE_HOST="${{ vars.STG_REMOTE_HOST }}"
        REMOTE_TARGET_DIR="${{ vars.STG_REMOTE_TARGET_DIR }}"
        ;;
    esac
    set -eu
    npm run generate
    # ... rsyncでデプロイ ...

シェルスクリプト編で作ったデプロイ処理を、そのままGitHub Actions上で実行しています。
ブランチごとに適切なサーバー情報(ユーザー名、ホスト名、デプロイ先ディレクトリ)を設定してから、ビルドとデプロイを実行します。

重要なポイント

GitHub Secrets と Variables の使い分け

GitHub Actionsでは、SecretsVariablesという2つの方法で値を設定できます。

  • Secrets: 機密情報(SSH秘密鍵、APIキーなど)を保存
    • 例: PROD_SSH_PRIVATE_KEY, MICROCMS_API_KEY
    • ワークフロー内では${{ secrets.SECRET_NAME }}で参照
    • 値は非表示で、ログにも出力されません
  • Variables: 公開しても問題ない設定値(ホスト名、ユーザー名など)を保存
    • 例: PROD_REMOTE_HOST, PROD_REMOTE_USER
    • ワークフロー内では${{ vars.VARIABLE_NAME }}で参照
    • ログにも表示されますが、機密性は低い情報です

varsとは?
varsはGitHub Variablesを参照するためのコンテキストです。${{ vars.PROD_REMOTE_USER }}のように書くことで、リポジトリのSettingsで設定したVariablesの値を取得できます。

使い分けることで、セキュリティを保ちながら柔軟に設定を管理できます。

ブランチによる環境の自動切り替え

case ${{ github.ref_name }} in
  'master'|'main')
    # 本番環境の設定
    ;;
  'stg')
    # ステージング環境の設定
    ;;
esac

github.ref_nameを使って、ブランチ名に応じて自動的に環境を切り替えます。

  • mainブランチ → 本番環境にデプロイ
  • stgブランチ → ステージング環境にデプロイ

同じワークフローファイルで、複数の環境に対応できるのが便利です!

repository_dispatch で外部サービスから自動デプロイ

microCMSのWebhookからrepository_dispatchイベントを発火させることで、CMSの更新をトリガーに自動デプロイできます。

microCMS側の設定例:

  1. microCMSのWebhook機能で、GitHub APIを呼び出す
  2. 以下のようなリクエストを送信:
curl -X POST \
  -H "Authorization: token YOUR_GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  https://api.github.com/repos/YOUR_USERNAME/YOUR_REPO/dispatches \
  -d '{"event_type":"update"}'

これで、microCMSの記事を更新すると自動的にLPも更新されます!

メタデータファイルの先行転送(シェルスクリプト編と同じ)

シェルスクリプト編でも紹介した通り、メタデータファイルを先に転送してから全ファイルを転送することで、デプロイ中のエラーを防いでいます。

# 1. メタデータを先に転送(上書きしない)
rsync -vz --ignore-existing ... "_nuxt/builds/meta/"

# 2. 全ファイルを転送(古いファイルは削除)
rsync -avz --delete ... ".output/public/"

詳しい理由は、シェルスクリプト編の記事を参照してください!

設定方法

1. GitHub Secrets の設定

リポジトリの Settings → Secrets and variables → Actions から、以下のSecretsを追加します:

Secret名 説明
MICROCMS_API_KEY microCMSのAPIキー xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
MICROCMS_SERVICE_DOMAIN microCMSのサービスドメイン(オプション) your_service_domain
PROD_SSH_PRIVATE_KEY 本番環境用のSSH秘密鍵 -----BEGIN OPENSSH PRIVATE KEY-----...
STG_SSH_PRIVATE_KEY ステージング環境用のSSH秘密鍵 -----BEGIN OPENSSH PRIVATE KEY-----...

SSH秘密鍵は、さくらサーバーにSSH接続できる鍵をそのままコピー&ペーストしてください。

2. GitHub Variables の設定

同じく Settings → Secrets and variables → Actions の Variables タブで、以下を設定:

Variable名 説明
PROD_REMOTE_USER 本番環境のSSHユーザー名 your_username
PROD_REMOTE_HOST 本番環境のホスト名 xxx.sakura.ne.jp
PROD_REMOTE_TARGET_DIR 本番環境のデプロイ先ディレクトリ /home/your_username/www
STG_REMOTE_USER ステージング環境のSSHユーザー名 your_username
STG_REMOTE_HOST ステージング環境のホスト名 xxx.sakura.ne.jp
STG_REMOTE_TARGET_DIR ステージング環境のデプロイ先ディレクトリ /home/your_username/www

3. ワークフローファイルの配置

.github/workflows/deploy.ymlに上記のワークフローファイルを配置します。

ディレクトリ構造:

.github/
  workflows/
    deploy.yml

実行方法

通常のデプロイ(ブランチへのpush)

git push origin main   # 本番環境にデプロイ
git push origin stg    # ステージング環境にデプロイ

ブランチにpushするだけで、自動的にデプロイが開始されます!
もちろんpushでなくて、PRを作成してからのマージでもOKです。

microCMSからの自動デプロイ(repository_dispatch)

microCMSのWebhookを設定して、記事更新時にGitHub APIを呼び出すようにします。
これで、CMSを更新するだけで自動でデプロイされます。

まとめ

GitHub Actionsで自動デプロイを組むことで、以下のことが実現できました:

pushするだけで自動デプロイ(手動実行不要)
ブランチごとに環境を自動切り替え(本番/ステージング)
microCMSからも自動デプロイ可能(repository_dispatch)
シェルスクリプトをそのまま流用(環境変数設計の賜物)
高速なデプロイ(rsyncの差分転送)

シェルスクリプト編から、完全自動デプロイ編への進化ができました!

これで、開発に集中できる環境が整いました😸

自動デプロイ組んでる時、なんかめっちゃエンジニアやってる感じでおもしろかったです!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?