Jenkins + GitBook で GitHub のドキュメント(PDF)のパブリッシュを自動化しよう

## はじめに
「AWS で CI 環境を構築」シリーズの第二弾です。

今回は Jenkins で GitHub のドキュメントを GitBook で PDF 化して、GitHub のリリースにアップロードすることで、ドキュメントのパブリッシュを自動化します。

## 準備
### GitHub - Jenkins 連携

以下で、GitHub のイベントをトリガーに、Jenkins サーバにソースが展開されるようにしておきます。

「Jenkins で GitHub のイベントを受けてゴニョゴニョする準備」
http://qiita.com/exabugs/items/cc2c6f59da98cd81a06f


### API トークン 作成

リリースの作成と成果物のアップロードで GitHub API を使用します。

そのため、Settings - Personal access tokens で API トークン を作成します。
![screencapture-github-settings-tokens-1483809559363.png](https://qiita-image-store.s3.amazonaws.com/0/69410/7a912a84-0c3e-fc40-46d9-011125ecab8a.png)

scopes (権限) は repo をチェック
![スクリーンショット_2017-01-08_2_24_46.png](https://qiita-image-store.s3.amazonaws.com/0/69410/1d3097d2-d94d-bd3a-ca0e-d69ddc4c439c.png)

作成したら、token をメモしておいて下さい
![スクリーンショット_2017-01-08_2_25_33.png](https://qiita-image-store.s3.amazonaws.com/0/69410/6cf6e9ec-ca40-a192-bd5b-9580ee1f34a4.png)


## インストール
### Node.js
yum では、まだ 0.10 です。古いです。
ここは LTS の 6系 が望ましいです。

Node.js は環境の管理をしたいので nvm を使います。
https://github.com/creationix/nvm

以下で nvm をインストール。
NVM_DIR でインストール ディレクトリを指定できます。(指定しない場合は ~/.nvm にインストールされる)
全ユーザで使えるように、/usr/local/nvm にインストールします。

```
# curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | NVM_DIR=/usr/local/nvm bash
```

インストール後、以下が ~/.bashrc に追記されます。しかし、このままではインストールしたユーザでしか使えない。
そのため、この部分を /etc/profile.d/nvm.sh (新規) に移動して、全ユーザで読み込まれるようにします。

```bash:/etc/profile.d/nvm.sh
export NVM_DIR="/usr/local/nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
```
再ログインで、上記 nvm が使用可能になります。

```
# nvm ls-remote

         v6.9.0   (LTS: Boron)
         v6.9.1   (LTS: Boron)
         v6.9.2   (LTS: Boron)
         v6.9.3   (LTS: Boron)
         v6.9.4   (Latest LTS: Boron)
```
最新の v6.9.4 をインストールしましょうか。

```
# nvm install v6.9.4
# nvm use v6.9.4
# nvm alias default v6.9.4
```
以下になれば Node.js はインストール完了です。

```
# node -v
v6.9.4
```



### GitBook
GitBook は以下でインストールできます

```
# sudo npm install gitbook-cli -g
# gitbook install
```

また、PDF出力のために、Calibre が必要です
https://calibre-ebook.com/download_linux

```
# sudo -v && wget -nv -O- https://download.calibre-ebook.com/linux-installer.py | sudo python -c "import sys; main=lambda:sys.stderr.write('Download failed\n'); exec(sys.stdin.read()); main()"
```
OS のライブラリも、不足があるようなのでインストールします

```
# yum install mesa-libGL
```

以下で、動作確認しておきましょうか。
(README.md と SUMMARY.md が必須)

```
# gitbook pdf
```

## 設定
### Jenkins

GitBook で PDF を生成し、リリースにアップロードします。
上記を実行するタイミングとしては、リポジトリに**SUMMARY.md が存在**し、かつ **tag が Push された時だけ**とします。


![スクリーンショット 2017-01-08 3.03.09.png](https://qiita-image-store.s3.amazonaws.com/0/69410/6e0c86a1-6668-fdc3-c27a-0f5624e08cc6.png)
![スクリーンショット 2017-01-08 3.03.56.png](https://qiita-image-store.s3.amazonaws.com/0/69410/6abf4fa1-7dc1-f3cc-ae21-1c7970782eba.png)

```bash
#!/bin/bash

export PATH=/usr/bin:/usr/local/bin:$PATH
. /etc/profile.d/nvm.sh

param() {
  echo $payload | jq -r $1
}

OWNER=`param '.repository.owner.name'`
BRANCH=`param '.ref' | sed "s:^refs/heads:remotes/origin:"`
NAME=`param '.repository.name'`
URL=`param '.repository.ssh_url'`
ID=`param '.after'`

echo $URL
echo $BRANCH

if [ ! -d $NAME ]; then
  git clone $URL
fi

cd $NAME

git fetch origin
git reset --hard ${BRANCH}


#GitBook
if [[  $BRANCH = refs/tags/*  ]]; then

  if [ -f SUMMARY.md ]; then
    gitbook pdf
    github_asset_upload.sh $OWNER $NAME ${BRANCH:10}
  fi

fi
```

Jenkins から呼び出しているスクリプト (github_asset_upload.sh) が以下になります。
gitbook コマンドで生成した book.pdf を、GitHub のリリースにアップロードする処理になります。
book.pdf が既に存在するなら、削除してアップロード (更新) になります。

```bash:github_asset_upload.sh
#!/bin/bash

TOKEN=<ここにトークンを記載>

OWNER=$1
REPO=$2
TAG=$3

FILE=book.pdf
TYPE=application/pdf

URL_API=https://api.github.com/repos/${OWNER}/${REPO}/releases
URL_UPLOAD=https://uploads.github.com/repos/${OWNER}/${REPO}/releases
CURL=(curl -s -H "Authorization: token ${TOKEN}")


# タグのリリースがあるか？
#  なければ、作成
#  あれば、何もしない
ID_RELEASE=`"${CURL[@]}" -X GET $URL_API | jq ".[] | select(.tag_name == \"$TAG\") | .id"`
if [ -z $ID_RELEASE ] ; then
  echo Release $TAG create.
  ID_RELEASE=`"${CURL[@]}" -X POST $URL_API -d "{\"tag_name\":\"$TAG\"}" | jq ".id"`
else
  echo Release $TAG exists.
fi
echo Release : $ID_RELEASE


# タグのリリースで、指定したファイル名のassetsがあるか？
#  なければ、何もしない
#  あれば、削除
ID_ASSET=`"${CURL[@]}" -X GET $URL_API/$ID_RELEASE/assets | jq ".[] | select(.name == \"$FILE\") | .id"`
if [ -z $ID_ASSET ] ; then
  echo Asset $FILE not exists.
else
  echo Asset $FILE exists : $ID_ASSET. so delete.
  "${CURL[@]}" -X DELETE $URL_API/assets/$ID_ASSET -d "{\"tag_name\":\"$TAG\"}"
fi


# ファイルのアップロード
echo Asset $FILE upload.
ID_ASSET=`"${CURL[@]}" -X POST -H "Content-type: $TYPE" -F file=@$FILE $URL_UPLOAD/$ID_RELEASE/assets?name=$FILE | jq ".id"`
echo Asset : $ID_ASSET
```

## 動作確認

タグを打ってPushしてみます。

```
$ git tag -a v1.9.0
$ get push origin v1.9.0
```

Release v1.9.0 が作成され、その中に book.pdf が追加されました。
![スクリーンショット_2017-01-08_2_33_03.png](https://qiita-image-store.s3.amazonaws.com/0/69410/c9e929a8-d0b8-c4d1-7f82-22496e2b2a3d.png)

## 日本語対応

日本語に対応するためには、フォントが必要です。

以下のサイトを参考に「Adobe／Google謹製の源ノ角ゴシック(Noto Sans CJK / Source Han Sans)」をインストールしました。(ありがとうございます)
http://backport.net/blog/2016/09/06/pdf_embedded_japanese_font/

フォントは、book.json で "GenShinGothic" を指定します。

```json:book.json
{
  "pdf": {
    "fontFamily": "GenShinGothic"
  }
}
```

さすが源ノ角！日本語がキレイにPDF化されました！
![スクリーンショット 2017-01-12 10.06.38.png](https://qiita-image-store.s3.amazonaws.com/0/69410/84f2a635-6728-1aa9-3100-d280947ab45e.png)


## カスタマイズ

PDF の見栄えをカスタマイズできるようです。
https://toolchain.gitbook.com/config.html

```json:book.json
{
    "pluginsConfig": {
        "fontSettings": {
            "size": 2
        }
    },
    "pdf": {
        "fontFamily": "GenShinGothic",
        "fontSize": 12,
    }
}
```

## リポジトリの小技

ドキュメント(マークダウン)は、ソースコードと同じツリーに入れる派と、いや、リポジトリも分けたいんだよ、という派があると思います。

ドキュメントの編集が頻繁にある場合、ソースと同じブランチだとコミットログが荒れてくるので、今回はドキュメント用のリポジトリを分離したいと思います。

その際、Git の オーファン(ルートなし） ブランチが便利です。
(コミット履歴やタグ等、master ブランチとは完全に切り離されたブランチになります。)

以下で、ルートなしの documents ブランチを作成し、そこに ドキュメント(マークダウン) をコミットしていきます。

```
$ git checkout --orphan documents
```


## おわりに
 - これで、「ドキュメントはマークダウンで」活動が、一歩進みました。
 - GitHub の操作は、Jenkins の Git プラグインを上手く使えば、もっと簡単にできるかもしれないです。
 - HTML 形式で出力して、GitHub-Pages でパブリッシュしようか、とも思いましたが、Private リポジトリでも GitHub-Pages は Public になるのですね。危ない、危ない。