esaで書いた記事をGitHub Pagesでブログとして公開する

# はじめに
[esa](https://esa.io)には、書いた記事をGitHubにPushする[webhook](https://docs.esa.io/posts/176)があります(今はまだβ)。

その機能を使い、

* esaで記事を書いて
* Middlemanでビルドして
* Werckerで自動デプロイして
* GitHub Pagesでブログとして公開する

までの手順を紹介します。

全体像を雑に図にするとこんな感じです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/43208/20631b34-9a79-b3d3-1a3b-a8dda8942f48.png" width="400">

esaやMiddlemanやGithub Pages、CIについてはいくらか知識がある人を対象とします。

# esaのGitHub webhook
esaのGitHub webhookは、esaの特定ディレクトリ以下に記事を書いたらGitHubの特定のリポジトリにpushしてくれる機能です。

次のような特徴があります。

1. esaの特定のディレクトリだけを対象とできる
1. 任意のブランチをpush先に指定できる
1. 保存先ディレクトリを指定できる
1. 保存するファイルのパスは`${保存先ディレクトリ}/${esaの記事ID}.html.md`となる
1. タイトルやカテゴリなどのメタ情報はfrontmatterとして出力される (後述)

webhookについての[リリースノート](https://docs.esa.io/posts/176)を見ていただければイメージしやすいかと思います。

## frontmatter
frontmatterとは、MiddlemanやJekyllで使われているファイルのメタ情報を記述するためのものです。

ファイルの先頭にYAMLとして書かれます。esaのwebhookによって作成されるファイルのfrontmatterは次のようになります。

```yaml
---
title: "たいとる"
category: かてごり
tags: 
created_at: 2016-07-28 00:56:48 +0900
updated_at: 2016-07-28 00:58:15 +0900
published: true
number: 123
---
```


`title`, `category`, `tags`は、例えばesa内での記事のパスが `webhook_root_path/foo/bar/たいとーる #tag1 #tag2` であれば次のようになります。

```yaml
title: "たいとーる"
category: foo/bar
tags: tag1, tag2
```

# Middleman
では早速ブログを作っていきましょう！

## 初期化
まずはMiddlemanを初期化します。

```bash
gem install middleman
middleman init myblog --template=blog
```

これで`myblog/`ディレクトリ以下に必要なファイルが作成されました。

## Gemfile
`Gemfile`に次の1行を追加してください。

```rb:Gemfile
gem "middleman-deploy", github: "middleman-contrib/middleman-deploy", ref: "243ab38b08896cd5a37d6845a01a5761b934a898"
```

GitHubへのデプロイに[middleman-deploy](https://github.com/middleman-contrib/middleman-deploy)というGemを使いますが、リリースされているバージョンはバグがあって使えません。
GitHubにある最新のソースは修正されているのでそれを使います。

追加したら`bundle install`しておきましょう。

## frontmatter対応
Middlemanではfrontmatterの`date`という属性を日付として使用しています。しかし、esaでは`created_at`になっているのでMiddlemanでも日付を認識できるようする必要があります。

`config.rb`でパッチをあてます。`config.rb`の先頭に次のコードを追加してください。

```rb:config.rb
module EsaFrontmatter
  def data
    return @page_data if @page_data
    super
    @page_data[:date] ||= @page_data[:created_at]
    @page_data
  end
end

Middleman::Sitemap::Resource.prepend(EsaFrontmatter)
```

## middleman-blogの設定
`config.rb`でblogについての設定をしていきます。次の設定を追加してください。他はデフォルトで大丈夫です。

```rb:config.rb
activate :blog do |blog|
  blog.permalink = ":year/:month/:day/:title.html"
  blog.sources = "articles/:title.html"
  blog.default_extension = ".md"
end

set :relative_links, true
```

esaのwebhookでは記事をgitに保存するときに階層化できないので、すべての記事が`source/articles/`ディレクトリに入るようにします。

`relative_links`は、GitHub Pagesをサブディレクトリとして公開するとき必要になります。
(http://nownabe.github.io/subdir/ みたいな)

## middleman-deployの設定
デプロイの設定をします。今回はGitHubにデプロイするので次のようになります。

```rb:config.rb
activate :deploy do |deploy|
  deploy.build_before = true
  deploy.deploy_method = :git
  # deploy.branch = "master"
end
```

`gh-pages`ブランチではなく`master`ブランチにデプロイする場合は`deploy.branch = "master"`としてください。

# リポジトリ作成
GitHub上にリポジトリを作成して、ここまでで作ったコードをpushしておきましょう。

# Wercker
[Wercker](http://wercker.com/)はTravis CIとかCircle CIとかと同じ、いわゆるCIサービスです。
GitHubアカウントでログインしてみてください。

ここでは4つのことをします。

* 作成したリポジトリをWerckerのCI対象として登録する
* デプロイ用のSSH鍵を作成する
* gh-pagesへの変更は対象外とする
* wercker.ymlを作成する

## Application作成
まずは、作成したリポジトリをWerckerのCI対象として登録します。
ログインできたら「Create」というボタンがあるので、そこをクリックしてApplicationを作成してください。

![スクリーンショット 2016-07-28 2.16.34.png](https://qiita-image-store.s3.amazonaws.com/0/43208/0e2185cb-2fe4-c4e8-7e33-b65fa30596ff.png)

先ほど作成したGitHubのリポジトリを選んで、進めていってください。
「Configure access」はrecommendedのでOKです。

![スクリーンショット 2016-07-28 2.18.28.png](https://qiita-image-store.s3.amazonaws.com/0/43208/0900d008-ef2f-c435-c621-50558ce20d62.png)

## デプロイ用SSH鍵作成
作成したApplicationの設定画面に移動してください。「Settings」というボタンです。

左のメニューの「Environment variables」をクリックして、SSH鍵を作成してください。

「SSH Key variable name」には`DEPLOY_SSH_KEY`を入力し、「SSH Key pair」は「Generate new SSH key-pair」を選択してください。

![スクリーンショット 2016-07-28 2.22.56.png](https://qiita-image-store.s3.amazonaws.com/0/43208/59ec6956-93c1-2f56-551b-8d27e3cc1a55.png)

「Add」をクリックすると公開鍵と秘密鍵が生成されるので、公開鍵はコピーしてGitHubのリポジトリにDeploy keyとして登録しておいてください。

## gh-pagesを対象外にする
次はgh-pagesをCIの対象外とします。
設定画面の「Workflows」をクリックしてください。
下の「Pipelines」の「build」というリンクをクリックしてください。

![スクリーンショット 2016-07-28 2.25.33.png](https://qiita-image-store.s3.amazonaws.com/0/43208/f476a102-8e76-b44a-09b2-b0ff627a888b.png)

「Webhooks」の「Ignore branch(es)」に`gh-pages`と入力して「Update」をクリックしてください。

![スクリーンショット 2016-07-28 2.28.22.png](https://qiita-image-store.s3.amazonaws.com/0/43208/6dbb8a7a-3394-3036-0a19-cc187d30e253.png)

## wercker.yml
最後に、`wercker.yml`を作成します。`.travis.yml`みたいなものです。

`config.rb`と同じ階層に作成してください。

```yaml:wercker.yml
box: ruby:2.3.1

build:
  steps:
    - script:
        name: Install Node.js
        code: |
          sudo apt-get update -y
          sudo apt-get install -y nodejs
    - bundle-install
    - script:
        name: configure git user
        code: |
          git config user.name $WERCKER_STARTED_BY
          git config user.email `git log -1 --format="%ce"`
    - add-ssh-key:
        keyname: DEPLOY_SSH_KEY
        host: github.com
    - add-to-known_hosts:
        hostname: github.com
        fingerprint: 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
    - script:
        name: deploy
        code: bundle exec middleman deploy
```

意味はなんとなくわかると思うので細かくは説明しません。
いろいろと準備して、最後の`bundle exec middleman deploy`で`gh-pages`ブランチにpushしています。

これができたら、commitしてpushしておいてください。
このpushでWerckerのビルドが走ってGitHub Pagesでブログが公開されるはずです。

# esaのwebhookを設定する
最後に、esaでGitHub webhookを設定します。

左の「TEAM」メニューで「Webhooks」タブを選択します。そこで「Add webhooks」をクリックしてください。

<img width="922" alt="スクリーンショット 2016-07-28 2.34.25.png (183.0 kB)" src="https://img.esa.io/uploads/production/attachments/1679/2016/07/28/4429/5df50fce-8b97-4335-a9e1-07d31e4557f3.png">

いろいろ選択肢がでるので「GitHub(β)」を選択して、入力していきます。
「output directory」は必ず`source/articles/`ですが、ほかは適当に設定してください。

<img width="850" alt="スクリーンショット 2016-07-28 2.35.57.png (123.6 kB)" src="https://img.esa.io/uploads/production/attachments/1679/2016/07/28/4429/77979e1e-f2bd-42f8-b946-b0cd4f2849f2.png">

API Access Tokenは[こちら](https://github.com/settings/tokens)から取得してください。

設定ができたら、「esa root category」で指定したディレクトリ(カテゴリ)の中で記事を書いてみてください。
Ship It!したらWerckerでビルドが走り、GitHub Pagesで公開しているブログが更新されるかと思います。

# おわりに
サンプルのソースコードを用意しました。参考にしてください。
https://github.com/nownabe/middleman-no-esa

GitHub webhook便利すぎてますますesaが気に入りました :heart_eyes: 
:thought_balloon: (Ikachanってなんだろう)