チームブログをGitHubとHexoではじめよう!

Tokyo Otaku ModeでEngineerやってますpchwです。

通常、チームで技術ブログを書こうとすると、

  • 他の人からフィードバックをもらいにくい
  • フィードバックをもらっても、どの部分への指摘かわからない
  • 下書きをキャプチャした画像に赤入れされたのが送られてきた
  • そもそもリッチテキストで書くのがダルい

など不幸な出来事が起こりがちです。

僕らは日々の開発と同じようなフローに則ってチームでブログを執筆する環境を整えたので、その方法を共有します。

Tokyo Otaku Modeでは、主にNode.jsを使って開発を進めています。
そのため、プラグインを書くのにもふだんの環境がそのまま使えるHexoというBlogging Frameworkを使って、ブログを執筆する環境を整えました。

HexoはNode.js製でOctopressの影響を受けて開発されています。
HexoもOctopressも、GitHub Pagesで採用されているJekyllという静的サイトジェネレータから影響を受けたものです。
そのため、GitHub Pagesを使ってのブログのホスティングがしやすくなっています。

インストール

HexoはNode.js製なので、Node.jsのインストールが必要です。
Node.jsのインストール方法は何通りかあるのですが、ここではnvmを使うことにします。

1
2
3
4
$ curl https://raw.githubusercontent.com/creationix/nvm/v0.13.0/install.sh | bash
$ ~/.nvm/nvm.sh
$ nvm install 0.10
$ nvm use 0.10

これで、Node.jsがインストールできました。

次に、Hexoをインストールします。

1
$ npm install -g hexo

これで、hexoコマンドが使えるようになります。

セットアップ

使えるようになったhexoコマンドで、ブログのセットアップを行います。

1
2
3
$ hexo init <blog名>
[info] Copying data
[info] You are almost done! Don't forget to run `npm install` before start blogging with Hexo!

と初期化コマンドを実行すると

1
2
3
4
5
6
7
8
9
10
11
12
13
$ tree <blog名> -L 2
<blog名>/
├── _config.yml
├── package.json
├── scaffolds
│   ├── draft.md
│   ├── page.md
│   ├── photo.md
│   └── post.md
├── source
│   └── _posts
└── themes
└── landscape

このように各種ファイルが生成されます。
treeコマンドはディレクトリを階層構造をわかりやすく出力してくれるコマンドで、 brew install treeでインストールできます。)

その後、依存パッケージのインストールします。

1
2
$ cd <blog名>
$ npm install

この状態で、すでにBlogが動く状態になります。

1
2
$ hexo server
[info] Hexo is running at http://localhost:4000/. Press Ctrl+C to stop.

http://localhost:4000/ にアクセスすると、

image
このような形になります。

設定

_config.ymlファイルを編集することで、Blogの設定を変更できます。

詳細な設定値などはHexoのConfigurationページにまとまっています。

rootなどの設定は、正しく設定しないとcssやjsのpathが不正になって正しく動作しないので、設定し忘れないように。

Deployの設定

_config.ymlファイルの中にdeploy:というセクションがあります。
ここを適切に設定すれば、hexo deployとすることで簡単にGitHub PagesやHeroku等に記事を上げることができるようになります。

1
2
3
4
5
6
7
8
$ tail -n 8 _config.yml
# Deployment
## Docs: http://hexo.io/docs/deployment.html
deploy:
type: github
repo: git@github.com:<organization名>/<organization名>.github.io.git
branch: master

のように設定することで、GitHub PagesでOrganization Pagesを公開することできます。
(もちろん、先にGitHub上にRepositoryは用意しないといけません)

HerokuやRsyncなどを使ったDeployに関しては、公式のガイドに書かれています。

カスタムドメインの設定

ここはHexoの設定というよりは、GitHub PagesとDNSの設定とお考え下さい。
DNS側の設定で、カスタムドメインが<organization名>.github.ioを向くようにします。

そしてsource/CNAME

1
$ echo 'blog.otakumode.com' > source/CNAME

のようにカスタムドメインの設定を書き、正しくリダイレクトされるようにします。

上記はサブドメインの設定で、トップレベルドメイン(Apex/Root/Naked/Bare)などの場合は手順が異なるので、GitHub Pagesのヘルプを確認してみてください。
(技術ブログなので、サブドメインで運用することが多いと思います。)

記事を書く環境をGit管理下に置く

チームで技術ブログを書く場合は、下記のようなフローを経るのが望ましいです。

  1. 開発と同じようにGitHub上で草稿を管理する。
  2. Pull Requestで相互にレビューを行う。
  3. Pull RequestがマージされたのをトリガーとしてCIを動かす。
    4.本番記事として公開する。

このフローができていないと、ブログを書くのがめんどくさくなったり、誰のチェックも通らない記事が世に出て行って、炎上を誘発したりしかねません。

1
2
3
4
5
6
$ git init
Initialized empty Git repository in ..../.git/
$ git checkout -b source
Switched to a new branch 'source'
$ git remote add origin git@github.com:<organization名>/<organization名>.github.io.git
$ git push origin source

Organization Pagesの場合は、masterブランチにある静的ファイルがブログの記事となって公開されていくため、記事を書く環境自体は別ブランチにしました。(上記手順ではsourceというブランチにしています)

公開される生成済み静的ファイルと記事を書く環境を同じmasterブランチに置いてもいいですが、個人的には分けた方が綺麗だと思うので分けました。

記事を書く

草稿

まず、ブランチを切ります。

1
2
$ git checkout -b "write-blog-with-hexo"
Switched to a new branch 'write-blog-with-hexo'

hexoコマンドを使うと

1
2
$ hexo new "<Article Title>"
[info] File created at /Users/.../<blog名>/source/_posts/<Article_Title>.md

以下のようにひな形が出力されるので、そこにMarkdown形式で書いていきます。

1
2
3
4
5
$ more source/_posts/<Article_Title>.md
title: Article Title
date: 2014-07-14 21:54:54
tags:
---

推敲

書き上がったら、仕上がりを確認します。

1
2
$ hexo server
[info] Hexo is running at http://localhost:4000/. Press Ctrl+C to stop.

http://localhost:4000/ にアクセスして記事を読み直し、問題があれば修正します。
Markdownファイルを編集すると自動的に変更を検知するので、リロードするだけで内容が最新にアップデートされます。

Pull Requestとレビュー

記事を書いたブランチをpushします。

1
2
3
$ git add source/_posts
$ git commit -m "Hexoを使って技術ブログ書く方法の記事"
$ git push origin write-blog-with-hexo

http://github.com/<organization名>/<organization名>.github.io を開き、sourceブランチへPull Requestを投げます。(hubコマンドでも構いません)

あとは、他の人にレビューをしてもらい、問題があればcommit/pushを繰り返し、記事を仕上げていきます。

review

問題が無くなった時点で、sourceブランチへマージします。

記事をデプロイする

マージ済みのsourceブランチの最新を取得してきて、
hexoコマンドでデプロイします。

1
2
3
$ git checkout source
$ git pull origin souce
$ hexo deploy

これで、無事に先ほど書いた記事が本番に反映されます。

デプロイの自動化

無事に記事が本番反映されたところで、面倒くさいデプロイの処理を自動化します。
sourceブランチへのマージまではGitHub上のマージボタンで完結できるので、
Travis CICircleCIなどのCIサービスを使ってsourceブランチへのpushをトリガーにしてsourceブランチの最新を取得し、hexo deployを行えばいいのです。

Tokyo Otaku ModeではCircleCIをCIサービスとして利用しているので、ブログのデプロイもCircleCIを使っています。

以下のようなcircle.ymlファイルを置いておけば、自動化が出来ます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ more circle.yml
machine:
timezone:
UTC
node:
version: 0.10.26
deployment:
production:
branch: source
commands:
- git config --global user.name "Circle CI"
- git config --global user.email "<your mailaddress>"
- git submodule init
- git submodule update
- ./node_modules/.bin/hexo clean
- ./node_modules/.bin/hexo generate
- ./node_modules/.bin/hexo deploy
general:
branches:
only:
- source

Staging環境の用意

デプロイの自動化が済んだら、次はStaging環境の用意に移ります。
これまでは、ローカルでhexo serverを実行し、localhost:4000にアクセスすることで見た目の確認を行っていました。
しかし、この方法だとちょっと確認をしてもらうのにも環境整備が必要だったりするなど、面倒なケースが発生し得ます。
そこで、Hexoに付いているHerokuにデプロイする機能を利用し、Staging用にHerokuにデプロイするようにします。

単純に設定しようとすると、本番環境・Staging環境両方にも同時にデプロイするようにしか書けないのですが、Circle CIを噛ませることにより、別々にデプロイさせることが出来ます。

circle.ymlの設定

circle.ymldeploymentセクションにproductionの項目を設定しましたが、ここにはstagingという項目も設定できます。
また、hexo deployコマンドは、_config.ymlのパスを指定するオプションがあります。
この2つを組み合わせると、特定ブランチへの更新は本番環境へ、それ以外はStaging環境へといった動作が可能になります。

以下がstaging環境へのデプロイも設定したcircle.ymlです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
machine:
timezone:
UTC
node:
version: 0.10.26
deployment:
production:
branch: source
commands:
- git config --global user.name "Circle CI"
- git config --global user.email "<your mailaddress>"
- git submodule init
- git submodule update
- ./node_modules/.bin/hexo clean
- ./node_modules/.bin/hexo generate
- ./node_modules/.bin/hexo deploy
staging:
branch: /.*/
commands:
- git config --global user.name "Circle CI"
- git config --global user.email "<your mailaddress>"
- ./node_modules/.bin/hexo clean
- ./node_modules/.bin/hexo generate
- ./node_modules/.bin/hexo deploy --branch $CIRCLE_BRANCH --config _staging_config.yml
general:
branches:
ignore:
- master

sourceへのpushは本番環境へのデプロイが走り、それ以外はStaging環境へのデプロイが走ります。
CircleCI自身が本番環境へのデプロイ時にmasterを書き換えるため、masterは除外設定をしています。

Staging用の_config.ymlを設定

本番環境は_config.ymlを見て、Staging環境は_staging_config.ymlを見るようになっています。
_staging_config.ymlのdeployセクションは

1
2
3
4
$ tail -n 3 _staging_config.yml
deploy:
type: heroku
repo: git@heroku.com:<用意したherokuのアプリ名を入れる>.git

というふうに設定します。

Herokuの準備

実際にHerokuに上げるためには、Herokuのアプリケーションが必要です。

Heroku Toolbeltをインストールして、

1
2
$ heroku login
$ heroku create

とすれば、Herokuアプリケーションが生成されるので_staging_config.ymlrepo: git@heroku.com:<用意したherokuのアプリ名を入れる>.gitの部分を埋めます。

Circle CIがHerokuへアクセスできるようにする

このままだと、Circle CIからHerokuへのpushがアクセス拒否されてしまうので、
適切にPermissionを設定してあげる必要があります。
Circle CIの設定画面に、HerokuのAPIキーを入れます。
HerokuのAPIキーはここのAPI Keyの項目から取得できます。

ブランチをpushしてみる

ここまで終われば、適当なブランチをsourceから切ってpushすることにより、自動的にCircleCIが動き、Staging環境が更新されるはずです。

あとは、Staging環境のHerokuのURLを校正してもらいたい人に共有するなどすれば、
Hexoが入っていない環境の人も、実際の見た目に近い環境で確認することができます。

まとめ

このようにして、Tokyo Otaku Modeでは、チームで技術ブログを書くうえで面倒くさい障害を取り除き、開発と同じようなフローで書けるように自動化を進めました。

Tokyo Otaku Modeでは、面倒くさいことは自動化してやるぜ!という気概あふれるエンジニアを募集しています!
こちらからご応募ください!
(「ブログを見た」とひと言いただければ、僕らエンジニアが喜びます)