Circle CIで挟まざまなビルドが可能となるため、 HexoJekyll など静的なサイトジェネレータを使用してWebページを生成することが可能となります。 もちろん、サイトジェネレータを使用せずに静的ページがホスティング可能です。

さらに、そのビルド結果をGitHub PagesでWebページを公開するための自動デプロイを行うことが可能となります。

これらはすべて無料で行えるため、お財布にも優しいです。

GitHub Pages

GitHub PagesGitHub が提供している、GitHub上のリポジトリにアップされたコンテンツを利用してWebページとして公開できるホスティングサービスです。

また、カスタムドメインも使用でき、さらには 2018 年 5 月にカスタムドメインの HTTPS での配信がサポートされました。

privateリポジトリもGitHub Pagesが使用できますが、指定した配下以下はすべて公開されてしまうため、 くれぐれも公開の際にはご注意ください。

このブログもGitHub Pagesを使用しています。

ドメイン名

個人リポジトリは [user name].github.io、組織アカウントは [organization name].github.io/リポジトリ名 となります。

また、 CNAME ファイルを用意して中身に独自ドメインを記載すると独自ドメインの設定が可能となります。

Circle CI

Circle CI は、継続的インテグレーションサービスです。 継続的な統合や配信が可能となり、ソフトウェア開発プロセスを自動化できます。

1 Containerが無料で使用でき、1 Container増設毎に $50/月かかります。 また、GitHubやBitbuketと柔軟に連携が可能であり、 privateリポジトリの区別もありません。

GitHub Pagesをデプロイする際には1 Containerで十分なため、無料で始めることが可能です。

公開方法の選択

GitHub Pagesは

  • master ブランチ配下をすべて公開
  • master ブランチの docs ディレクトリ以下をすべて公開
  • gh-pages ブランチ配下をすべて公開

のどれかを1つ選択可能です。

つまり、公開する方法を選択したら、それに応じてブランチまたはディレクトリ配下にビルド成果物を入れて、 GitHubのリポジトリにpushすることでWebページを公開できます。

ご自身のユースケースにマッチする方法を選択しましょう。

リポジトリに mastergh-pages ブランチが存在しない場合は、該当する公開方法が選択できないようになっています。

公開タイミングの選択

公開タイミングも人それぞれですが、大きく分けて以下から選択することとなります。

  1. 選択した公開方法のブランチまたはディレクトリに、直接成果物をpushする方法
  2. GitHubのイベントを利用し、成果物をビルドして、選択した公開方法のブランチまたはディレクトリにpushする方法
  3. Circle CIのAPIを呼び出し、成果物をビルドして、選択した公開方法のブランチまたはディレクトリにpushする方法

パターン1: 選択した公開方法のブランチまたはディレクトリに、直接成果物をpushする方法

この方法はビルド環境がローカルにある必要がありますが、公開タイミングを自分で選択でき、かつCIを使用なくても実現できます。

しかし、複数人でメンテナンスを行う場合は、全員が同じ環境でビルドを行う保証がなく、下書きなど公開前の管理が難しくあまり向いていません。

パターン2: GitHubのイベントを利用し、成果物をビルドして、選択した公開方法のブランチまたはディレクトリにpushする方法

この方法はビルドをローカル環境で行わずよく、公開前にテストなどさまざまなビルドが可能となります。

この中でも一般的に多く取られる方法は、 「とあるブランチにmergeされたら、選択した公開方法のブランチまたはディレクトリにpushする」です。

パターン3: Circle CIのAPIを呼び出し、成果物をビルドして、選択した公開方法のブランチまたはディレクトリにpushする方法

この方法はGitHubのイベント以外を利用したい場合、たとえばチャットbotなどで取られることが多い方法です。

もちろんビルドをローカル環境で行わずよく、公開前にテストなどさまざまなビルドが可能となります。 また、任意のタイミングで公開ができるのも大きな強みです。

公開の準備

例として以下の方法とタイミングで VuePress で作成した静的ページを公開するようにしてみます。

今回使用しているサンプルはこちらです。

公開方法 公開タイミング
master ブランチの docs ディレクトリ以下をすべて公開 GitHubのイベントを利用し、成果物をビルドして、選択した公開方法のブランチまたはディレクトリにpushする方法

VuePressの成果物の生成先の変更

VuePressはデフォルトで .vuepress/dist にビルドされます。 しかし、 config.jsdest を設定することで、ビルド先を変更できます。

今回はこの destdocs/ を指定することにします。

// src/.vuepress/config.js

const title = 'GitHub Pages VuePress Sample!';
const description = 'Just play VuePress for kenchan0130 blog.';

module.exports = {
  title: title,
  description: description,
  dest: 'docs/'
};

これで vuepress build のビルド先が docs/ になりました。

Circle CIの設定

Circle CIでbuildを行うので、.circleci/config.yml にビルドの設定を記述していきます。

version: 2

jobs:
  build:
    working_directory: ~/github-pages-vuepress-example
    docker:
      - image: node:9.11
        environment:
          TZ: "/usr/share/zoneinfo/Asia/Tokyo"
          LANG: ja_JP.UTF-8
          LC_ALL: C.UTF-8
          LANGUAGE: ja_JP.UTF-8
          DEPLOY_BRANCH: master

    steps:
      - checkout

      #### Node dependencies ####
      - restore_cache:
          keys:
            - yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }}
            - yarn-packages-{{ .Branch }}
            - yarn-packages-master
            - yarn-packages-

      - run:
          name: Install Node dependencies
          command: yarn install

      - save_cache:
          paths:
            - node_moduels
          key: yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }}
      #### Node dependencies end ####

      - run:
          name: Deploy development branch to master
          command: |
            if [ "${CIRCLE_BRANCH}" = "${DEPLOY_BRANCH}" ]; then
              chmod +x deploy.sh
              ./deploy.sh
            fi

steps が実際に行っている処理です。具体的には、

  1. working_directory に設定したディレクトリに対象のコミットをチェックアウト
  2. キャッシュの呼び出し
  3. node の依存をインストール
  4. node_moduels をキャッシュ
  5. 今ビルドしているブランチが master だったらデプロイスクリプト(deploy.sh)を走らせる

を行っています。

今回のポイントは「今ビルドしているブランチが master だったらデプロイスクリプト(deploy.sh)を走らせる」です。 これにより、 master に変更があった時のみデプロイが行われます。

デプロイスクリプトの用意

Circle CIのビルド設定で deploy.sh を走らせるようにしましたが、ここでは実際にその中身を用意します。

#!/bin/bash -e

# build
yarn run --silent build

if [ "$(git status --porcelain | wc -l | xargs)" -eq 0 ]; then
  echo "Not exist deploying contents."
  exit 0
fi

git config --global user.name "Circle CI"
git config --global user.email "<>"
git add -A
git commit -m "[ci skip] Deploy by CI"

git push -f $(git config --get remote.origin.url) master:master > /dev/null/ 2>&1

echo "Deploy a site!"

cd -

やっていることは単純で、

  1. VuePressのビルド
  2. デプロイ内容物かあるかの確認
  3. ビルド結果をコミット
  4. GitHubのリモート master ブランチにコミットをpush

を順に行っています。

重要なのはコミットメッセージに [ci skip] を含めていることです。

このコミットがマージされた際のビルドではCIが走りません。 もしCIを走らせてしまうと、無限にデプロイ処理が行われてしまいます。

ほかにもSlack通知など行うなど、ご自身で自在にカスタマイズが可能です。

Circle CIの連携

Circle CIと連携されていないとGitHubのリポジトリにコミットをプッシュしてもビルドは走りません。 まずはCircle CIにログインをします。

プロジェクトの追加を選択して、今回連携したいリポジトリを選択して Set Up Project をクリックします。

Circle CI のプロジェクトの追加

ビルドの設定方法などが記載されていますが、もうすでに設定済みなので Start building をクリックするだけです。

Circle CI のプロジェクトの設定

これで、リポジトリに変更があるたびにCircle CIのビルドが走ます。

GitHub Pagesの公開

master ブランチの docs/ ディレクトリに成果物がプッシュされるようになったので、 Gitリポジトリの Settings より、 GitHub Pagesの公開方法を指定します。

GitHub Pages 公開方法選択

今回は関係しませんが、カスタムドメインを設定する場合、 「master ブランチの docs ディレクトリ以下を全て公開」を選択していると、 CNAME ファイルは docs/CNAME に設置する必要があります。

ディレクトリルート直下に CNAME ファイルを設定しても反映されません。 意外とハマりどころなのでご注意ください。

まとめ

GitHub PagesをCircle CIを使用してデプロイする方法を紹介しました。

公開方法と公開タイミングをどう選択するかで、 若干Circle CIの設定やデプロイスクリプトの内容が変わりますが、 基本的にやることは変わりません。

GitHub PagesとCircle CIでお手軽にかつ、お金をかけずに静的サイトホスティングしていきましょう!