MkDocs を多言語サイトに対応しつつ GitHub Pages に自動デプロイする

MkDocs との出会い

以前の記事 で紹介した Portal ですが、そのサイトは Hugo という静的サイトジェネレータを使用して作成していました。

Hugo 側の機能で多言語サイトへの対応ができるなど、非常に高性能でよかったのですが、watchモードで動かしている時によくバグってしまい、イライラが溜まってしまったので別のジェネレータを探しました。

そこで見つけたのが MkDocs というジェネレータです。この MkDocs ように用意されている Material Design のテーマが非常にいい感じだったので、エイヤッという感じで乗り換えてみました。

しかし、MkDocs 自体には Hugo のような複数言語サイトへの対応の機能はないので、そこをいい感じにしつつ、ついでで Push すると GitHub Pages (gh-pagesブランチ)にも自動で Push してくれるようにするまで行いました。

https://github.com/PortalMC/www.portalmc.org

このプロジェクトで使用したので、必要があればここを見てください

1. 多言語サイトを無理やり作る

多言語サイトの表現方法は思いつく感じ以下のようなものがあります。

  • サブドメインに ja とかがつく
  • URLのパスの一部に ja とかがつく
  • クエリストリングに lang=ja  みたい感じでつく

よくあるのは1つ目と2つ目だと思います。

今回は、サブドメインだとCDN周りの設定が面倒になってくるので、2番目の方法を採用しました。(Hugoもこの方法だったというのもあります。)

デフォルトのフォルダ構成

こんな感じに、ページとして表示可能なパスの場合は、 index.html が置かれています。

今回、URLのパスのプレフィックスとして  ja がうまく付くようにフォルダ構成をいじります。

ちょうどこんな感じのURLの対応になります。

このアクセスを可能にするためのフォルダの構成はこうなります。

ja  フォルダ以下に、 assets  と sitemap.xml 以外のファイルが同じように配置されている状況になれば良さそうです。(  assets も配置してもいいですが、中身が同じで無駄なので省きます。)

今回の肝

Hugo のように1つの構成でやるのは無理なので、2つ以上の構成を用意して、外部コマンドで合体させる必要があります。

ただし、ここに sitemap.xml が関わってくるので、いい感じにこれもマージしないといけません。

サイトマップさえなければシェルスクリプトでも良かったのですが、XMLを行数だけであつかうのは怖いので、今回は Gradle を使用していい感じにマージさせるようにします。

build.gradle

フォルダ構成

主にこんな感じです。

default で指定されたものをビルドして public フォルダに移動、後はサブの構成をどんどんビルドして public フォルダに追加していくだけです。

追加するときには前述の余分なものが入らないように削除を行っています。

これで、 ./gradlew build と叩けば公開用のフォルダが出来上がります。

2. GitHub Pages に自動デプロイする

GitHub Pages のホスティング方法は何種類かありますが、今回は gh-pages ブランチに自動でコミット・プッシュが行なわれるようにしたいとおもいます。

CI周りには安定の CircleCI を使います。

Docker

CircleCI2 で、Docker周りが充実しましたが、公式で提供されているのはたいてい1言語だけをサポートしたものだけしか用意されていません。

今回のプロジェクトでは、Python(MkDocs)とJava(Gradle)が必要になるので、カスタムのDockerイメージを作成してやっちゃいたいと思います。

とはいっても、Hub に公開されているPythonとJavaのDockerfileをガッチャンコして、足りないものを追加でインストールするようにしただけです。

実際のDockerfileは以下で公開しています。

https://github.com/PortalMC/www.portalmc.org/blob/master/deploy/docker/Dockerfile

config.yml

リポジトリにプッシュする関係上、リポジトリへの書き込み権限を持った Deploy Key の追加と、ステップ中で add_ssh_keys  を呼ぶ必要があります。

特に  add_ssh_keys  を追加するのが公式のドキュメントのわかりやすい部分に書いていないので結構な時間を取られました。。。

run で実行しているシェルスクリプトがビルドやgitの操作を行う本体になります。

スクリプトはこちらで紹介されているものをほぼそのまま使用しています。

https://blog.yuyat.jp/post/auto-deploy-hugo-to-github-pages-with-circleci/

gh-pages 用のリポジトリのinit時に CNAME ファイルを追加する部分と、ビルドコマンドが変わっています。

https://github.com/PortalMC/www.portalmc.org/blob/46994ce3096700d63e752f461befc94c01067fb8/deploy/scripts/deploy_production.sh

あとは CircleCI側でプロジェクトを有効にすれば、Pushと同時にサイトの更新も自動で行われるようになります。

おわりに

本来の使い方から外れるととたんにめんどくなるのがつらい。世知辛い。