目次

1. 初めに

このブログはJekyllで静的ページを生成し、GitHubPagesで公開しています。 Jekyllのプラグインはサポートされているプラグインのみを使用しています。

サポートされているプラグインを使用する場合はJekyllはセーフモードONで十分で、 ビルド前の資産をプッシュするだけで勝手にビルドされてサイトが公開されます。

しかし、サポートされていないプラグインを使用する場合はJekyllをセーフモードOFFに設定する必要があります。 また、事前にビルドしてその生成物をプッシュする必要もあります。 懸念される課題はビルド前の資産と生成物の変更履歴が一緒になり汚くなること、 資産を編集する度に資産と生成物の両方をプッシュするのは手間になることです。

この課題を解決するため、CI/CDツールであるGitHubActionsを用いてビルドやプッシュを自動化する環境を構築しましたので、 今回はその構築手順と実行結果をまとめました。

2. ブログ公開までのワークフロー

まず、このブログが公開されるまでのワークフローを変更前と変更後でまとめました。 ★の記載された行が変更箇所です。

2.1. 変更前(セーフモードON:サポートされているプラグインのみ使用)

  1. ユーザがmasterブランチへ資産をプッシュする
  2. (★)GitHubActionsがmasterブランチへのプッシュを検知する
  3. (★)GitHubActionsが組み込まれたJekyll(セーフモードON)でビルドする
  4. GitHubActionsが生成物をデプロイする
  5. GitHubPagesがブログを公開する

2.2. 変更後(セーフモードOFF:サポートされていないプラグイン使用)

  1. ユーザがmasterブランチへ資産をプッシュする
  2. (★)GitHubActionsがmasterブランチへのプッシュを検知する
  3. (★)GitHubActionsがタイムゾーンを設定する
  4. (★)GitHubActionsがリポジトリをチェックアウトする
  5. (★)GitHubActionsがRubyをセットアップする
  6. (★)GitHubActionsがGemをインストールする
  7. (★)GitHubActionsがJekyll(セーフモードOFF)でビルドする
  8. (★)GitHubActionsがgh-pagesブランチへ生成物をプッシュする
  9. GitHubActionsが生成物をデプロイする
  10. GitHubPagesがブログを公開する

3. 自動化環境の構築手順

3.1. 公開用ブランチ(gh-pages)の作成

資産と生成物の変更履歴を分けるため、開発用ブランチ(master)と公開用ブランチ(gh-pages)で別々に管理します。

開発用ブランチは既にあるので、公開用ブランチを新たに作成します。

3.2. ワークフローの作成

資産を編集する度に資産と生成物の両方をプッシュするのは手間になるため、CI/CDツールであるGitHubActionsを用いて ブログ公開までのワークフロー の2.~8.を自動化します。

これにより開発用ブランチ(master)に資産をプッシュすると、 リポジトリのチェックアウト、ビルド環境の構築、セーフモードOFFのJekyllによるビルド、 公開用ブランチ(gh-pages)への生成物のプッシュなどが自動で実行されます。

また、公開用ブランチには親コミットを持たせたくないため、親のないブランチ(orphanブランチ)としてプッシュします。 因みにorphanとは孤児のことで、孤児は両親・親戚等の保護者のいない未成年者という意味で、 それが転じて親のないブランチでorphanブランチということらしいです。

以下のワークフローファイルを開発用ブランチ(master)に作成します。

.github/workflows/push-to-gh-pages-branch.yml

# ワークフロー名
name: Push To gh-pages Branch

# ジョブが実行されるトリガー
on:
  push:
    branches:
      - master # 2. GitHubActionsが`master`ブランチへのプッシュを検知する

# 実行されるジョブ一覧
jobs:
  deploy: # ジョブ名
    runs-on: ubuntu-20.04 # 実行環境

    concurrency: # 並行処理(同じグループのジョブは処理待ち)
      group: $ - $
      # [ワークフロー名]-[ワークフローの実行をトリガーしたブランチ名]
      # Deploy GitHub Pages - refs/heads/master

    steps: # ジョブで実行されるステップ一覧
      # 3. GitHubActionsがタイムゾーンを設定する
      - name: Set Timezone
        uses: szenius/set-timezone@v1.0
        with:
          timezoneLinux: "Asia/Tokyo"

      # 4. GitHubActionsがリポジトリをチェックアウトする
      - name: Checkout Repository
        uses: actions/checkout@v2

      # 5. GitHubActionsがRubyをセットアップする
      - name: Setup Ruby
        uses: actions/setup-ruby@v1
        with:
          ruby-version: 2.7

      # 6. GitHubActionsがGemをインストールする
      - name: Bundle Install According to Gemfile
        run: |
          bundle install

      # 7. GitHubActionsがJekyll(セーフモードOFF)でビルドする
      - name: Jekyll Build
        run: |
          bundle exec jekyll build

      # 8. GitHubActionsが`gh-pages`ブランチへ生成物をプッシュする
      - name: Push to gh-pages Branch
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: $
          publish_branch: gh-pages
          publish_dir: ./_site
          force_orphan: true # コミット件数は必ず1件(最新のコミットのみ)
          user_name: "github-actions[bot]"
          user_email: "github-actions[bot]@users.noreply.github.com"

3.2.1. 2021/09/03 追記

表示される記事の投稿日時は日本標準時(JST:UTC+0900)で期待した通りでしたが、 GitHubActionがJekyllでビルドする際に以下のメッセージが出力され、ビルドされない問題が発生しました。

  • Skipping: _posts/2021-09-02-00007.md has a future date
  • 記事の投稿日時が未来であるため、当該記事のビルドをスキップ

GitHubActionの実行環境のタイムゾーンが協定世界時(WET:UTC+0000)になっていたため、この問題が発生したと思われます。

以下の対応を行うことにより解決しました。

  • ワークフローのステップの最初にタイムゾーン設定処理(3.)を追加する

3.2.2. 2021/09/04 追記

GitHubActionがJekyllでビルドする際に以下のメッセージ(一部省略)が出力され、 ファイル名(日本語)の文字化けによりビルドが失敗する問題が発生しました。

  • utils.rb:141:in `initialize’: Invalid argument @ rb_sysopen - /contents/category/????.md (Errno::EINVAL)
  • エラーログはこちら

この問題はWindows用のRubyの課題として挙がっていました。 解決策はWindows以外を使用するか、ファイル名をASCII文字に変更するか、どちらかであるとのこと。

This is a known issue with Ruby on Windows. The solution would be to switch to a non-Windows system or rename files with ascii characters.

以下の対応を行うことにより解決しました。

  • ワークフローの実行環境をwindows-2019からubuntu-20.04に変更する
  • ワークフローのステップのタイムゾーン設定処理をLinux用に変更する
  • Linux環境のsasscはBundleInstallが非常に遅いため2.4.0から2.1.0に変更する

3.2.3. 参考サイト

  1. GitHub Actions による GitHub Pages への自動デプロイ - Qiita
  2. peaceiris/actions-gh-pages
  3. Rubyでのビルドとテスト - GitHub Docs
  4. Unicode character inside file name makes problems
  5. Ruby on Rails 6のbundle installが重すぎる

3.3. GitHubトークンの設定

GitHubトークンにリポジトリへの書き込み権限を設定するため、リポジトリで下記メニューに移動します。

  • Settings => Actions => General => Workflow permissions

デフォルトだとRead repository contents and packages permissionsがチェックされているため、 Read and write permissionsにチェックします。

3.3.1. 2024/05/28 追記

GitHubActionがプッシュする際に下記エラーが出力され、プッシュが失敗する事象が発生しました。

workflow: Push to gh-pages branch

Push the commit or tag
  /usr/bin/git push origin --force gh-pages
  remote: Permission to silverag-corgi/blog.git denied to github-actions[bot].
  fatal: unable to access 'https://github.com/silverag-corgi/blog.git/': The requested URL returned error: 403
  Error: Action failed with "The process '/usr/bin/git' failed with exit code 128"

GitHubトークンに書き込み権限が不足していたため、このエラーが発生しました。 本節を対応することにより、解決しました。

4. GitHubActionsによる自動化の実行結果

以下のコミットメッセージで開発用ブランチ(master)にプッシュした際の実行結果をワークフロー順に示します。

  • [d_upd] 記事更新

4.1. 開発用ブランチ(master)の資産状態

GitHubActions_gh-pages

4.2. 実行ログ

上記で作成した ワークフロー が実行され、31秒で完了しています。

GitHubActions_log

4.3. 公開用ブランチ(gh-pages)の資産状態

GitHubActions_gh-pages

5. 最後に

今回はセーフモードOFFのJekyllによるビルドを含めたワークフローの一部をGitHubActionsにより自動化しました。

これでサポートされていないプラグインだからと使用を見送っていたプラグインを使用できます。 しかし元々はサポートされているプラグインのみを使用する想定で実装していたため、移植する箇所が結構ありそうです。 大変そうではありますが、今から楽しみです。