【全自動】SphinxドキュメントをNetlifyでホスティングする


はーい！毎週金曜日は `Friday I/O` ですよー。
[株式会社ワムウ](http://wamw.jp)では、毎週金曜日は `興味がある事柄に取り組み、その成果を何らかの形でアウトプットする日` としております。


## はじめに

今回は `Sphinx` で生成したドキュメントを `Netlify` でビルド & ホスティングする方法をご紹介いたしますー。

### Sphinxとは

http://sphinx-users.jp

`reStructuredText` っていう `Markdown` みたいなもんで綺麗なドキュメントが作れますよってヤツです。
`PDF` とかも吐けるみたい。

### Netlifyとは

https://www.netlify.com

HTMLをむちゃくちゃ簡単にホスティングしてくれるお方です。
Githubと連携してプッシュ時に自動でデプロイ・ビルド・ホスティングまでしてくれます。


## ドキュメントを用意する

とか言われてもだるいと思うので、[サンプルプロジェクト](https://github.com/odoku/sphinx-on-netlify-sample)用意しときました！
ファイル構成は以下のとおり。

```
root
 |- docs
 |   |- requirements.txt
 |   |- source
 |       |- conf.py
 |       |- index.rst
 |- netlify.toml
```

よくプロジェクトのドキュメントって `docs` に入ってるよね。
そういうディレクトリ構成だと思って下さいませ。

`docsディレクトリ` 内で以下のコマンドを叩くとドキュメントのビルドが開始されると思います。

```console
pip install -r requirements.txt
sphinx-build source build
```


## netlify.tomlって何よ

https://www.netlify.com/docs/continuous-deployment/#deploy-contexts

Netlifyのビルドで利用する環境変数を設定したり、環境によって実行するコマンドを変えたり出来るみたい。
今回の内容はこんな感じ。

```toml
[build]
  base    = "docs"  # ビルドを実行するディレクトリ
  publish = "docs/build"  # ホスティングするディレクトリ
  command = "sphinx-build source build"  # ビルドコマンド
```


## Netlifyの設定

上記のプロジェクトをコピーして適当な名前のリポジトリを作ったら、いよいよNetlifyの設定ですよ。
ダッシュボードから `New site from Git` を押して登録していきましょう！

![step001.png](https://qiita-image-store.s3.amazonaws.com/0/12537/3e17e8fa-1c75-ef80-a849-91e2fa6acb4c.png "step001.png")

`GitHub` `GitLab` `BitBucket` に対応しているようですね。

![step002_a.png](https://qiita-image-store.s3.amazonaws.com/0/12537/4104b4cc-c85f-4300-f3bf-409d0e645306.png "step002_a.png")

さっき登録したリポジトリを選択してくださいまし。

![step002_b.png](https://qiita-image-store.s3.amazonaws.com/0/12537/9502099a-2dcd-8b4a-d5e8-bb0f5ac9f16d.png "step002_b.png")

設定画面に来ました！
`netlify.toml` に記述した内容が反映されていると思うので、そのまま何もせず登録をしてしまいましょう！

![step003.png](https://qiita-image-store.s3.amazonaws.com/0/12537/6096eea8-a83d-7838-9941-d12d2115a07d.png "step003.png")

モリモリとビルドが走ります！！！！

```console
7:40:10 PM: Build started
7:40:10 PM: Fetching cached dependencies
7:40:10 PM: Expected build cache - but failed to find it
7:40:10 PM: Failed to extract cache, continuing with build
7:40:11 PM: No cached dependencies found. Cloning fresh repo
7:40:11 PM: git lfs clone git@github.com:odoku/sphinx-on-netlify-sample
7:40:12 PM: git remote rm origin
7:40:12 PM: Preparing Git Reference refs/heads/master
7:40:13 PM: Found netlify.toml. Overriding site configuration
7:40:13 PM: Running build command: sphinx-build source build
7:40:14 PM: v6.11.2 is already installed.
7:40:15 PM: Now using node v6.11.2 (npm v3.10.10)
7:40:15 PM: Using version v6.11.2 of node
7:40:15 PM: Using /opt/buildhome/.rvm/gems/ruby-2.1.2
7:40:15 PM: Installing pip dependencies
7:40:16 PM: Collecting Sphinx==1.6.3 (from -r requirements.txt (line 1))
7:40:16 PM: /opt/buildhome/python2.7/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:318: SNIMissingWarning: An HTTPS request has been made, but the SNI (Subject Name Indication) extension to TLS is not available on this platform. This may cause the server to present an incorrect TLS certificate, which can cause validation failures. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#snimissingwarning.
SNIMissingWarning
/opt/buildhome/python2.7/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:122: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#insecureplatformwarning.
InsecurePlatformWarning
7:40:16 PM: Downloading Sphinx-1.6.3-py2.py3-none-any.whl (1.9MB)
7:40:17 PM: Collecting sphinx-rtd-theme==0.2.4 (from -r requirements.txt (line 2))
7:40:17 PM: Downloading sphinx_rtd_theme-0.2.4-py2.py3-none-any.whl (1.4MB)
7:40:17 PM: Collecting Pygments>=2.0 (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:17 PM: Downloading Pygments-2.2.0-py2.py3-none-any.whl (841kB)
7:40:17 PM: Requirement already satisfied: setuptools in /opt/buildhome/python2.7/lib/python2.7/site-packages (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:17 PM: Collecting imagesize (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:17 PM: Downloading imagesize-0.7.1-py2.py3-none-any.whl
7:40:17 PM: Collecting babel!=2.0,>=1.3 (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:17 PM: Downloading Babel-2.5.0-py2.py3-none-any.whl (6.8MB)
7:40:18 PM: Collecting snowballstemmer>=1.1 (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:18 PM: Downloading snowballstemmer-1.2.1-py2.py3-none-any.whl (64kB)
7:40:18 PM: Collecting Jinja2>=2.3 (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:18 PM: Downloading Jinja2-2.9.6-py2.py3-none-any.whl (340kB)
7:40:18 PM: Collecting alabaster<0.8,>=0.7 (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:18 PM: Downloading alabaster-0.7.10-py2.py3-none-any.whl
7:40:18 PM: Collecting sphinxcontrib-websupport (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:18 PM: Downloading sphinxcontrib_websupport-1.0.1-py2.py3-none-any.whl
7:40:18 PM: Collecting six>=1.5 (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:18 PM: Downloading six-1.10.0-py2.py3-none-any.whl
7:40:19 PM: Collecting requests>=2.0.0 (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:19 PM: Downloading requests-2.18.4-py2.py3-none-any.whl (88kB)
7:40:19 PM: Collecting docutils>=0.11 (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:19 PM: Downloading docutils-0.14-py2-none-any.whl (543kB)
7:40:19 PM: Collecting typing; python_version < "3.5" (from Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:19 PM: Downloading typing-3.6.2-py2-none-any.whl
7:40:19 PM: Collecting pytz>=0a (from babel!=2.0,>=1.3->Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:19 PM: Downloading pytz-2017.2-py2.py3-none-any.whl (484kB)
7:40:19 PM: Collecting MarkupSafe>=0.23 (from Jinja2>=2.3->Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:19 PM: Downloading MarkupSafe-1.0.tar.gz
7:40:19 PM: Collecting urllib3<1.23,>=1.21.1 (from requests>=2.0.0->Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:19 PM: Downloading urllib3-1.22-py2.py3-none-any.whl (132kB)
7:40:20 PM: Collecting idna<2.7,>=2.5 (from requests>=2.0.0->Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:20 PM: Downloading idna-2.6-py2.py3-none-any.whl (56kB)
7:40:20 PM: Collecting chardet<3.1.0,>=3.0.2 (from requests>=2.0.0->Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:20 PM: Downloading chardet-3.0.4-py2.py3-none-any.whl (133kB)
7:40:20 PM: Collecting certifi>=2017.4.17 (from requests>=2.0.0->Sphinx==1.6.3->-r requirements.txt (line 1))
7:40:20 PM: Downloading certifi-2017.7.27.1-py2.py3-none-any.whl (349kB)
7:40:20 PM: Building wheels for collected packages: MarkupSafe
7:40:20 PM: Running setup.py bdist_wheel for MarkupSafe: started
7:40:20 PM: Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'
7:40:20 PM: Stored in directory: /opt/buildhome/.cache/pip/wheels/88/a7/30/e39a54a87bcbe25308fa3ca64e8ddc75d9b3e5afa21ee32d57
7:40:20 PM: Successfully built MarkupSafe
7:40:20 PM: Installing collected packages: Pygments, imagesize, pytz, babel, snowballstemmer, MarkupSafe, Jinja2, alabaster, sphinxcontrib-websupport, six, urllib3, idna, chardet, certifi, requests, docutils, typing, Sphinx, sphinx-rtd-theme
7:40:22 PM: Successfully installed Jinja2-2.9.6 MarkupSafe-1.0 Pygments-2.2.0 Sphinx-1.6.3 alabaster-0.7.10 babel-2.5.0 certifi-2017.7.27.1 chardet-3.0.4 docutils-0.14 idna-2.6 imagesize-0.7.1 pytz-2017.2 requests-2.18.4 six-1.10.0 snowballstemmer-1.2.1 sphinx-rtd-theme-0.2.4 sphinxcontrib-websupport-1.0.1 typing-3.6.2 urllib3-1.22
7:40:23 PM: /opt/buildhome/python2.7/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:122: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#insecureplatformwarning.
InsecurePlatformWarning
7:40:23 PM: Pip dependencies installed
7:40:23 PM: Running Sphinx v1.6.3
making output directory...
7:40:23 PM: loading translations [ja]...
7:40:24 PM: done
7:40:24 PM: /opt/buildhome/python2.7/local/lib/python2.7/site-packages/sphinx/util/requests.py:64: UserWarning: Some links may return broken results due to being unable to check the Server Name Indication (SNI) in the returned SSL cert against the hostname in the url requested. Recommended to install "requests[security]" as a dependency or upgrade to a python version with SNI support (Python 3 and Python 2.7.9+).
'Some links may return broken results due to being unable to '
7:40:24 PM: loading pickled environment...
7:40:24 PM: not yet created
7:40:24 PM: building [mo]: targets for 0 po files that are out of date
7:40:24 PM: building [html]: targets for 1 source files that are out of date
7:40:24 PM: updating environment:
7:40:24 PM: 1 added, 0 changed, 0 removed
7:40:24 PM: reading sources... [100%] index
7:40:24 PM:
7:40:24 PM: looking for now-outdated files...
7:40:24 PM: none found
7:40:24 PM: pickling environment...
7:40:24 PM: done
7:40:25 PM: checking consistency...
7:40:25 PM: done
7:40:25 PM: preparing documents...
7:40:25 PM: done
7:40:25 PM: writing output... [100%] index
7:40:25 PM: 
generating indices...
7:40:25 PM: genindex
7:40:25 PM:
7:40:25 PM: writing additional pages...
7:40:25 PM: search
7:40:25 PM:
7:40:25 PM: copying static files...
7:40:25 PM: WARNING: html_static_path entry u'/opt/build/repo/docs/source/_static' does not exist
7:40:25 PM: done
7:40:25 PM: copying extra files...
7:40:26 PM: done
7:40:26 PM: dumping search index in Japanese (code: ja) ...
7:40:26 PM: Build complete: exit code: 0
7:40:26 PM: done
dumping object inventory...
7:40:26 PM: Cleaning up docker container
7:40:26 PM: done
7:40:26 PM: build succeeded, 1 warning.
7:40:26 PM: Starting to deploy site from 'docs/build'
7:40:26 PM: Deploying to CDN
7:40:26 PM: Uploading 6 files
7:40:27 PM: Uploading file search.html
7:40:27 PM: Uploading file index.html
7:40:27 PM: Uploading file _sources/index.rst.txt
7:40:27 PM: Uploading file searchindex.js
7:40:27 PM: Uploading file genindex.html
7:40:27 PM: Uploading file objects.inv
7:40:37 PM: Finished deploying 6 files in 11.099070847s
7:40:37 PM: Cleaning up the repository
7:40:37 PM: Starting post processing
7:40:37 PM: Bundling and saving cache
7:40:38 PM: Minifying bundle
7:40:42 PM: Finished uploading cache in 607.377138ms
7:40:43 PM: Finished processing build request in 33.249378107s
7:40:43 PM: Minifying bundle
7:40:44 PM: Post processing done
7:40:44 PM: Site is live
```

ページの上部に戻ってみると `URL` が生成されております。
これをクリックすると。。。

![step004.png](https://qiita-image-store.s3.amazonaws.com/0/12537/4905dd22-1dda-4f6b-eb8b-e564f218988c.png "step004.png")

うおおおおおおおーーー！！！！！1

![step005.png](https://qiita-image-store.s3.amazonaws.com/0/12537/e43c4dab-a103-16e6-b8e1-3387e33373ca.png "step005.png")

ほとんど設定してねーー！！！
なにこれ便利ーーー！！！！！
`Read The Docs` なんていらなかったんや！！！！


## ちょっと解説

[ドキュメント](https://www.netlify.com/docs/#python) に書いてありますが、NetlifyはPythonが動きます。
んで、ビルドディレクトリ直下に `requirements.txt` って名前でpipでインストールするヤツ書いておくと勝手にインストールしてくれます。
あとはビルドコマンドとして `sphinx-build` を呼んであげるだけ。
素晴らしく簡単。


## おわり

`pip` であれこれインストール出来るので結構やりたい放題出来ると思います。
あとは [Basic認証かけたり](https://www.netlify.com/docs/headers-and-basic-auth/) も出来る模様。
便利だわーまじで。。