Gatsby.js製ブログをセルフホストしているサーバーにデプロイする

Yucchiy's Noteは2019/02/13時点で、Gatsby.jsで作成していて、sakura VPSに立ち上げたサーバー上でホストしています。

このブログをGithub Actionsを用いてサーバーにデプロイしてみます。

ただし下記を前提とします。

  • サーバーに対して公開鍵認証でSSHができる
  • サーバー上ではnginxが構築されている(nginxである必要はないが)
  • レポジトリ直下にGatsby.jsコンテンツが配置されている(package.jsonなどが直下に配置されている)

workflow fileの作成

Github Actionsを設定するためには、まずworkflow fileと呼ばれるファイルを.github/workflowsディレクトリ以下に作成する必要があります。このディレクトリ下に.ymlまたは.yaml拡張子でファイルを配置したものをworkflow fileとして認識します。

今回、デプロイ設定を記述するworkflow fileは.github/workflow/deployment.ymlで作成します。このファイルは下記の処理を行います。

  1. Gatsby.jsを動作させるためにNode.jsを利用できるようにする
  2. Gatsby.jsを動かしてブログをビルドする
  3. 2.で作成した成果物をサーバーにrsyncで配信する
  4. Slackにデプロイ通知をする

早速ですが、上記の処理を行う.github/workflow/deployment.ymlは以下となります。

name: Deployment for blog

on:
  push:
    branches:
      - master

jobs:
  build-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: 10.x
    - name: Cache dependencies
      uses: actions/cache@v1
      with:
        path: ~/.npm
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.os }}-node-
    - run: npm install
    - run: npm run build --if-present
    - name: deploy to server
      uses: AEnterprise/rsync-[email protected]
      env:
        DEPLOY_KEY: ${{ secrets.SERVER_SSH_KEY }}
        ARGS: "-avzr --delete"
        SERVER_PORT: ${{ secrets.SERVER_PORT }}
        FOLDER: "./public/"
        SERVER_IP: ${{ secrets.SERVER_IP }}
        USERNAME: ${{ secrets.USERNAME }}
        SERVER_DESTINATION: ${{ secrets.SERVER_DESTINATION }}
    - uses: actions/checkout@v2
    - name: Slack Notification
      uses: rtCamp/action-slack-[email protected]
      env:
        SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

ワークフローのトリガーイベントの設定

まず、このワークフローの名前とワークフローの呼び出しトリガーとなるイベントを設定します。該当箇所を抜粋すると以下のとおりです。

# このワークフローの名前
name: Deployment for blog

# トリガーは、`on:`で記述
on:
  push:
    branches:
      - master

ワークフロー名はDeployment for blogとし、masterにプッシュされたタイミングでこのワークフローを実行しています。 ちなみにイベントは複数指定できますし、branchsを省く事もできます。その時は全てのプッシュイベントに対してワークフローが呼び出されます。

詳細はEvents that trigger workflows - GitHub Actions / Referenceに記載されています。 スケジュールジョブを実行することもできますし外部からWebHook経由でイベントを実行することもできそうです。また、レポジトリに対しての各種イベントのハンドリングも簡単そうです。

ジョブを記述する

このワークフローでやることを書きます。jobstepsに順繰り処理の内容を書いていきます。まずはそのジョブの環境を下記のように記載します。

jobs:
  # build-deployというジョブを記述する。複数定義すると並列に動く?
  build-deploy:
    # ジョブはubuntu-latest上で実行される
    runs-on: ubuntu-latest
    # ここからジョブの内容を記載していきます。書いてあることが上から順次実行されます。
    steps:

ここからsteps項目以下に処理について説明していきます。

Node.jsのセットアップ

Gatsby.jsの動作にはNode.jsが必要です。下記のように記述します。

    - uses: actions/checkout@v2
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: 10.x
    - name: Cache dependencies
      uses: actions/cache@v1
      with:
        path: ~/.npm
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.os }}-node-

やっていることとしては、10.xのNode.jsを利用できるようにしています。 また、package-lock.jsonファイルが同じ内容なら~/.npmディレクトリをキャッシュすることで、パッケージのインストールを高速化しようとしています。

Gatsby.jsでブログをビルドする

配信するためのhtmlやcss、jsなどの成果物をGatsby.jsでビルドします。手順は下記のとおりです。

    - run: npm install
    - run: npm run build --if-present

特に難しいことはしてないのですがnpm installしてパッケージをインストール後、npm run buildでGatsby.jsによるビルドを実施しています。ここまで成功すると./publicに成果物が生成されます。 ここをカスタマイズするとjs製の静的サイトジェネレーターでも応用が効くかもしれません。

rsyncでサーバーに成果物をデプロイする

デプロイって言ってもrsyncコマンドでコピーしているだけなんですが。 Marketplaceから探してきたDeploy with rsync経由でrsyncを叩いています。

    - name: deploy to server
      uses: AEnterprise/rsync-[email protected]
      env:
        DEPLOY_KEY: ${{ secrets.SERVER_SSH_KEY }}
        ARGS: "-avzr --delete"
        SERVER_PORT: ${{ secrets.SERVER_PORT }}
        FOLDER: "./public/"
        SERVER_IP: ${{ secrets.SERVER_IP }}
        USERNAME: ${{ secrets.USERNAME }}
        SERVER_DESTINATION: ${{ secrets.SERVER_DESTINATION }}

注意点として(ってほどでもなく当然やるべきなんですが)、秘密鍵情報などセキュリティの観点から秘密にするべき情報はSecretsを用いてを隠しています。

Secrets

Secrets

設定はレポジトリ単位で行え、「Settings > Secrets」でアクセスするか https://github.com/{username}/{repository}/settings/secretsでアクセスできます。設定したSecretは、${{ secrets.設定した名前 }}でアクセスできます。

あと、rsyncの引数はちょっと自信がないです...

Slack通知を送る

最後に成功したら今どきっぽく(?)Slackで通知します。MarketplaceのSlack Notifyを利用しています。

    - uses: actions/checkout@v2
    - name: Slack Notification
      uses: rtCamp/action-slack-[email protected]
      env:
        SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

動作確認

メニューの「Actions」にアクセスすることで下記のようにGitHub Actionsの動作状況を確認できます。

check github actions

check github actions

まとめ

Gatsby.jsで構築したブログの自動デプロイをGitHub Actionsで構築しました。

軽い気持ちでGitHub Actionsを触ってみましたが、(当然ですが)GitHub単体で(CircleCIとか連携せずに)CI回せるのはとても楽だなっていうのと、GitHubのイベントのハンドリングがとても簡単なため、今まで外部のサーバーにWebHook飛ばしたりして処理してたものをGitHub上で完結できそうでとても楽そうです。

あとSelf-hosted runnersに少し心が惹かれています。

Reference