GitHub ActionsでGitHub Pagesへポートフォリオサイトを自動デプロイ


はじめに

以前に自分のポートフォリオサイトをHugoでGitHub Pagesへサクッとデプロイという記事を書きました。

この記事の中ではGitHub PagesへのデプロイはローカルのMacからデプロイ用のスクリプトを走らせることでやっていましたがGitHub Actionsでできた方がイケてる!ということでやってみました。
やってみたところなかなかハマったので共有します。

GitHub Pagesにはこんなサイトがあがっています。

前提

  • 静的サイトジェネレータにHugoを使います。
  • Hugo公式にあるHost on GitHub | GitHub User or Organization PagesにてInstructionがある、HugoのレポジトリにGitHub Pages(github.io)のレポジトリをgit submoduleとして組み込んで使っていくやり方に則っています。

サイトジェネレータ(Hugo)用レポジトリ リンク https://github.com/momotaro98/hugo-bio
GitHub Pagesレポジトリ リンク https://github.com/momotaro98/momotaro98.github.io

Main Contents

Workflowファイルとデプロイ用スクリプト

.github/workflows.main.yml
on:
  push:
    branches:
      - master

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - name: Fix up git URLs # ポイント3 submoduleの扱い
        run: echo -e '[url "https://github.com/"]\n  insteadOf = "[email protected]:"' >> ~/.gitconfig

      - uses: actions/checkout@v1
        with:
          submodules: true # ポイント3 submoduleの扱い

      - name: Read environment variables # ポイント1 Hugoのビルドと環境変数の受け渡し
        id: env
        run: |
          . ./.env
          echo "::set-output name=HUGO_VERSION::${HUGO_VERSION}"
          echo "::set-output name=THEME_NAME::${THEME_NAME}"

      - name: Setup Hugo # ポイント1 Hugoのビルドと環境変数の受け渡し
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: '${{ steps.env.outputs.HUGO_VERSION }}'

      - name: Build
        run: hugo -t '${{ steps.env.outputs.THEME_NAME }}'

      - name: Deploy the artifact onto hosting service
        env: # ポイント2 Secretsの扱い
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
          EMAIL_ADDRESS: ${{ secrets.EMAIL_ADDRESS }}
        run: ./deploy.sh
deploy.sh
#!/bin/bash

set -eu

echo 'Deploying updates to GitHub...'

user_name="momotaro98"

echo 'Set Git configurations'
git config --global user.name $user_name
git config --global user.email ${EMAIL_ADDRESS}

echo 'Start deploying onto hosting service'

cd public # ポイント3 submoduleの扱い

# Check if there's change in the generated artifact
if [[ ! `git status --porcelain` ]]; then
  echo 'No change in artifact then finishing this deploying workflow'
  exit 0
fi

# ポイント2 Secretsの扱い
git remote set-url origin https://$user_name:${DEPLOY_TOKEN}@github.com/$user_name/$user_name.github.io.git
git checkout master
git add .

msg="rebuilding site `date`"
if [ $# -eq 1 ]
  then msg="$1"
fi
git commit -m "$msg"

git push origin HEAD

echo 'Deploy done'

echo 'Start doing git commit to master itself'

cd ..
# ポイント2 Secretsの扱い
git remote set-url origin https://$user_name:${GITHUB_TOKEN}@github.com/$user_name/hugo-bio.git
git checkout master
git add public
git commit -m "Deploy public `date`"
git push origin HEAD

echo 'Git commit done'

ポイント1 Hugoのビルドと環境変数の受け渡し

サイトをビルドするにはGitHub ActionsのランナーにHugoをインストールしてあげる必要があります。
今回 @peaceiris さんが作成したActionモジュールを利用しました。

また、レポジトリページのREADMEのTipsをそのまま拝借しました。

.env
HUGO_VERSION=0.59.1
THEME_NAME=resume
.github/workflows/main.ymlの一部
# 環境変数をファイルから読み込み設定
. ./.env
echo "::set-output name=HUGO_VERSION::${HUGO_VERSION}"
echo "::set-output name=THEME_NAME::${THEME_NAME}"
.
.
# 設定された環境変数を取得
hugo-version: '${{ steps.env.outputs.HUGO_VERSION }}'

このようにすることで環境変数をStep間で受け渡すことができます。

ポイント2 Secretsの扱い

.github/workflows/main.ymlの一部
- name: Deploy the artifact onto hosting service
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
    EMAIL_ADDRESS: ${{ secrets.EMAIL_ADDRESS }}

今回、3つのシークレットの値を使っています。

1つ目のsecrets.GITHUB_TOKENが特別です。

From 公式ドキュメント

GitHubは、ワークフローで利用するGITHUB_TOKENシークレットを自動的に生成します。 このGITHUB_TOKENは、ワークフローの実行内での認証に利用できます。
GitHub Actionsを有効化すると、GitHubはリポジトリにGitHub Appをインストールします。 GITHUB_TOKENシークレットは、GitHub Appインストールアクセストークンです。 このインストールアクセストークンは、リポジトリにインストールされたGitHub Appの代わりに認証を受けるために利用できます このトークンの権限は、ワークフローを含むリポジトリに限定されます。

GITHUB_TOKENはデフォルトで用意されておりworkflowが置かれるレポジトリスコープ内で有効です。
今回はデプロイスクリプトにて最後にsubmodule更新分をコミットしmasterにPushするために利用しています。

DEPLOY_TOKENEMAIL_ADDRESSは以下スクショのようにレポジトリのSettingから入力し設定します。

DEPLOY_TOKENはGitHub PagesのレポジトリにPushするために必要なトークンで個人のPersonal access tokensのページから生成したものです。

ポイント3 Git submoduleの扱い

ハマりました。

標準のactions/checkout@v1のアクションモジュールを利用していましたがこれは下記のようにsubmodules: trueを入れてあげないとsubmoduleの実体がディレクトリ下に現れません。

.github/workflows/main.ymlの一部
- uses: actions/checkout@v1
  with:
    submodules: true

このフラグを入れたあともこのissueと同じエラーが出てしまいました。

fatal: Could not read from remote repository.

どうやら現状ではsubmoduleをCloneするのにgitプロトコルではNGでhttpsを使うようにしないといけないようです。

こちらの解決方法を拝借しジョブの一番はじめに

- name: Fix up git URLs
  run: echo -e '[url "https://github.com/"]\n  insteadOf = "[email protected]:"' >> ~/.gitconfig

このステップを入れることで無事Submoduleが取得されました。

デプロイの様子

masterブランチに変更が入るごとにActionのページから確認できます。

補足 ローカルでのHugo起動はDockerで

GitHub ActionsとローカルでのHugoのバージョンが異なると困るので上述の.envファイルにあるバージョンをローカルでも利用するようにDockerを利用します。

こちらに関しても @peaceiris さんが作成したHugoのDockerのイメージを利用します。
Tipsにあるようにdocker-compose.ymlを設定すれば柔軟に環境変数でバージョンを指定できかつホットリロードで編集できるHugo環境ができます。

docker-compose.yml
version: '3'

services:
  hugo:
    container_name: hugo
    image: "peaceiris/hugo:v${HUGO_VERSION}"
    # image: peaceiris/hugo:v${HUGO_VERSION}-mod  # Hugo Modules
    ports:
      - 1313:1313
    volumes:
      - ${PWD}:/src
    command:
      - server
      - --bind=0.0.0.0
      - --buildDrafts

docker-compose upをするだけでHugoサーバがhttp://localhost:1313で立ち上がります。

参考