静的ブログをCircleCIでビルドして、GitHubでホスティングしてみた

僕がやってるブログ(静的サイトジェネレータ製)のビルドからホスティングまでの話を書きます。CircleCIを使ってビルドとデプロイを自動化しているので、その辺りの作業を自分でやってて疲弊している方はぜひ参考にしてみてください。
※ CircleCIの基礎はざっくり省きます。

↓ホスティングしているブログ
https://unearned-in.com/
↓ソースコード管理用リポジトリ
https://github.com/Y0KUDA/unearned-in.com
↓ホスティング用リポジトリ
https://github.com/Y0KUDA/Y0KUDA.github.io


処理はこんな感じで流れます。
1. ブログを更新してリポジトリにPushします
2. CircleCIがリポジトリのWebhookを受けてビルドを開始します
3. CircleCIがビルドしてできたファイルをGitHubリポジトリにアップロードします
![Untitled Diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275289/55b275aa-eeaa-6eac-6b3c-53cb5d98aa89.png)

2,3のCircleCIによるビルド、アップロードについて実際に使っているconfig.ymlでポイントを解説していきます。

↓使ってるconfig.ymlはこんな感じです。

```yml
version: 2.1

executors:
  default:
    docker:
      - image: circleci/node:jessie

jobs:
  init:
    executor: default
    steps:
      - checkout
      - persist_to_workspace:
          root: .
          paths:
            - .

  build:
    executor: default
    steps:
      - attach_workspace:
          at: .
      - restore_cache:
          key: dependency-cache-{{ checksum "package.json" }}
      - run:
          name: build
          command: |
            curl -o- -L https://yarnpkg.com/install.sh | bash  
            yarn --ignore-engines
            sudo npm install -g gatsby
            gatsby clean
            yarn build
      - save_cache:
          key: dependency-cache-{{ checksum "package.json" }}
          paths:
            - ./node_modules
      - persist_to_workspace:
          root: .
          paths:
            - .
  
  upload:
    docker:
      - image: buildpack-deps:scm
    steps:
      - attach_workspace:
          at: .
      - run:
          name: upload to server
          command: |
            cd ..
            git clone https://github.com/Y0KUDA/Y0KUDA.github.io.git
            cd Y0KUDA.github.io 
            echo * |xargs rm -rf 
            cd ..
            cp -rf project/public/* Y0KUDA.github.io/ 
            echo unearned-in.com > Y0KUDA.github.io/CNAME
            cd Y0KUDA.github.io 
            git config --global user.email "dummy@dummy.com"
            git config --global user.name "dummy"            
            git add --all 
            git commit -m "update"
            git push https://${GHUSR}:${GHPWD}@github.com/Y0KUDA/Y0KUDA.github.io.git master:master
workflows:
  all:
    jobs:
      - init:
          filters:
            branches:
              only: blog  
      - upload:
          requires:
            - build
      - build:
          requires:
            - init
```

# 解説
## ビルド
ブログのコードをビルドします。

```yml
  build:
    executor: default
    steps:
      - attach_workspace:
          at: .
      - restore_cache:
          key: dependency-cache-{{ checksum "package.json" }}
      - run:
          name: build
          command: |
            curl -o- -L https://yarnpkg.com/install.sh | bash  
            yarn --ignore-engines
            sudo npm install -g gatsby
            gatsby clean
            yarn build
      - save_cache:
          key: dependency-cache-{{ checksum "package.json" }}
          paths:
            - ./node_modules
      - persist_to_workspace:
          root: .
          paths:
            - .
```

ビルドコマンドは各自によって変わるので特に解説することはないです。  
ポイントは`restore_cache`、`save_cache`でキャッシュ機能を使っている点です。
Node.jsパッケージはダウンロードにめちゃくちゃ時間がかかるのでビルドの度にダウンロードしていたら非効率です。CircleCIではキャッシュを効かせることで、以前ダウンロードしたものを再利用することができます。ここでは、`package.json`のハッシュ値をキーとして利用しています。つまり、`package.json`が更新されればキャッシュはロードされず、Node.jsパッケージが新たにダウンロードされ、新しいキャッシュが作成されます。



# アップロード
ビルドして出来たファイルをホスティング用リポジトリにアップロードします。
コードに解説コメントを入れました。

```yml
  upload:
    docker:
      - image: buildpack-deps:scm
    steps:
      - attach_workspace:
          at: .
      - run:
          name: upload to server
          command: |
            # ホスティング用リポジトリをcloneする
            cd ..
            git clone https://github.com/Y0KUDA/Y0KUDA.github.io.git
            cd Y0KUDA.github.io 
            # cloneしたホスティング用リポジトリの中身を削除する
            echo * |xargs rm -rf 
            # 先程ビルドしたファイルをホスティング用リポジトリにコピーする
            cd ..
            cp -rf project/public/* Y0KUDA.github.io/ 
            # カスタムドメインを利用する場合はルートにドメイン名が書かれたCNAMEファイルを配置する必要があるっぽい。
            echo unearned-in.com > Y0KUDA.github.io/CNAME
            # コピーしたファイルを全部commitしてpushする
            cd Y0KUDA.github.io 
            git config --global user.email "dummy@dummy.com"
            git config --global user.name "dummy"            
            git add --all 
            git commit -m "update"
            git push 
            ## パスワードなどのベタ書きはやめよう。CircleCIではSecret Variableが利用可能！
            https://${GHUSR}:${GHPWD}@github.com/Y0KUDA/Y0KUDA.github.io.git master:master
```

# さいごに
雑にまとめましたが、参考になれば幸いです。
ご質問・ご意見等あればお気軽にどうぞ。
「自分はこうしている」「こうした方がいい」等のご意見もいただけると幸いです。