目次
このブログは以前、JekyllでMarkdownからサイトを生成し、GitHub Pagesで公開していました。最初は main に変更を入れてビルドし、その結果を公開すれば十分でした。
記事やレイアウトを作業ブランチで直すようになると、別の課題が出てきます。プルリクエストを出す前にサイトが壊れていないか確かめたい。でも、レビュー中の変更まで本番へ公開したくはありません。
必要だったのは、作業ブランチとプルリクエストでは検証だけを行い、レビューを経て main に入った変更だけを公開することです。
ソースと公開ファイルは別のブランチ
main にはMarkdown記事、設定、ワークフローなどのソースがあります。GitHub Pagesが配信するのは、Jekyllが生成したHTMLやCSS、画像などを置く gh-pages ブランチです。gh-pages は生成物の置き場であり、手作業で編集する場所ではありません。
作業ブランチ/プルリクエスト
│ CIでビルド・言語ルートを検証
▼
main(記事・設定・ワークフローのソース)
│ 本番ビルドとルート検査
▼
gh-pages(生成HTML・CSS・アセット) ──► GitHub Pages
CIとCDを分ける理由
CIが答えるのは「この変更を正しくビルドできるか」です。作業ブランチやプルリクエストでも実行できます。CDが答えるのは「検証済みの成果物で本番サイトを置き換えるか」です。公開の条件を main へのマージに絞れば、確認中の変更がそのまま訪問者に届くことはありません。
2つのワークフローと起動条件
当時はこの2つの流れに Validate blog と Automatic build という名前を付けていました。
作業branch / pull request(検証のみ)
- branchへのpush / PRを開く・更新任意のbranchで検証
- Validate blogJekyll build + 言語別route検査
- 検証結果gh-pagesには公開しない
mainへのmerge(公開条件)
- 自動ビルド本番 Jekyll ビルド + ルート確認
- 生成ファイルgh-pagesに公開
- GitHub Pages生成サイトを配信
Validate blog(.github/workflows/main.yml) — 任意のブランチへのpush、プルリクエスト、手動のworkflow_dispatchで起動します。Jekyllをビルドして言語別ルートを検証し、デプロイはしません。Automatic build(.github/workflows/pages-deploy.yml) —mainへのpush(指定された変更だけのpushは除外)か、手動のworkflow_dispatchで起動します。ジョブ条件によりrefs/heads/main以外では公開しません。
Automatic build のpushトリガーでは、.gitignore、README.md、LICENSE、ARTICLE_PROGRESS.md の変更を無視します。そのため、これらだけを変更したpushでは検証は動いても本番デプロイは始まりません。手動実行を選んだ場合も、ブランチ条件は省略されず、main 以外ではジョブが動きません。
Validate blog:ブランチとPRを検証する
検証ワークフローはRuby 2.7をセットアップし、Bundlerのキャッシュを使って依存関係を用意します。その後、Jekyllでサイトをビルドし、生成された _site の言語別ルートを確認します。
bundle exec jekyll build
ruby tools/verify_language_routes.rb _site
このワークフローはpushの対象ブランチを限定しません。プルリクエストでも同じ検証を行い、GitHub Actionsから手動で起動することもできます。どの場合も目的は変更の確認であり、検証に成功しただけでは gh-pages も公開サイトも更新されません。
Automatic build:mainの変更を公開する
本番ワークフローもRuby 2.7とBundlerをセットアップし、bash tools/deploy.sh を実行します。このヘルパーは本番用のJekyllビルドと言語別ルート検査を行い、生成したサイトで gh-pages の内容を置き換えます。当時はその更新にforce pushを使っていました。gh-pages は毎回生成される出力なので、記事や設定の変更は main 側で行います。
つまり公開までの境界は明確です。作業ブランチやPRではビルド可否を確かめ、レビュー後に変更を main へ取り込むと、本番用の生成と公開が始まります。
韓国語記事の一文を直す例
韓国語の記事にある一文を修正する場合は、次の順に進めます。
mainから作業ブランチを作り、韓国語記事の該当箇所を編集してpushします。Validate blogの実行結果を確認します。Jekyllビルドと言語別ルート検査の両方が成功することを確かめます。main向けのプルリクエストを開き、PR上の検証を通してレビューを受けます。- PRを
mainにマージします。対象となる変更ならAutomatic buildが本番ビルドを行い、gh-pagesを更新します。 - デプロイの成功を確認し、公開サイトで韓国語記事の該当ページを開いて修正文を確かめます。
これが「検証はこまめに、デプロイは意図をもって」の実際の流れです。検証を手動でやり直すなら Validate blog、ソース変更なしで本番サイトを再生成するなら Automatic build を main から手動実行します。
当時のJekyllサイトをローカルで確認する
当時のJekyll構成をローカルで確かめるには、依存関係をインストールして開発サーバーを起動していました。
bundle install
bundle exec jekyll serve
本番環境だけで起きる問題は、当時このコマンドでproductionビルドを再現していました。
JEKYLL_ENV=production bundle exec jekyll build
現在の構成について
2026年10月6日現在、このサイトの本番環境はJekyll/ChirpyからAstroの静的サイトへ移行しています。この記事は以前のJekyll構成を記録したものです。現在は main の変更をNode/Astroでビルドし、site-v2/dist を自動で gh-pages に公開してGitHub Pagesが配信します。実装は変わりましたが、変更を検証してから本番に公開する原則は今も同じです。