Gitlab CIでLaTeXを全自動コンパイル

# はじめに
卒論・修論や最終レポートの季節ですが、学生の皆さんいかがお過ごしでしょうか。こういった文章をLaTeXで書いてGitで管理している学生さん、たくさんいらっしゃると思います。

今日はそんな皆さんの手間を減らすために、GitLabにpushするだけでLaTeXが全自動でコンパイルされるシステムをDockerを使って組み上げていく方法を紹介します。

# 全体の構成
Docker上にGitLabとGitLab Runnerを用意して、GitLab Runner上でTeX Liveコンテナを動かしてコンパイルする仕組みです。

# 事前準備
とりあえずDockerとDocker-composeを用意しておきましょう。インストール方法はここでは特に紹介しません。作業ユーザーをdockerグループに所属させておくと、sudoが不要になって便利といえば便利です。それなりにリスクは負うことになりますが。

# Docker-composeの準備
## docker-compose.yml
とりあえず`docker-compose.yml`を書いていきましょう。GitLab本体と、GitLab Runnerを用意します。バックアップが容易なように、Volumeを作ってマウントしてあげるとよいでしょう。また、GitLab Runner上でTeX Liveコンテナを動かす都合上、Docker in Docker状態になるため、`docker.sock`を忘れずにマウントしておきます。

```yaml
version: '2'
services:
  gitlab:
    restart: always
    image: gitlab/gitlab-ce
    hostname: localhost
    ports:
      - "10080:80"
      - "10022:22"
    volumes:
      - conf:/etc/gitlab
      - logs:/var/log/gitlab
      - data:/var/opt/gitlab
    environment:
      VIRTUAL_HOST: gitlab.example.com
  gitlab-runner:
    restart: always
    image: gitlab/gitlab-runner:alpine
    volumes:
      - ci_data:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock

volumes:
  conf:
  logs:
  data:
  ci_data:
```

## コンテナの起動
Docker-Composeを使っているので、`docker-compose.yml`が存在するディレクトリに移動して、以下のコマンド一発で起動できます。

```bash
$ docker-compose up -d
```

# GitLab側の準備
まずは管理者ユーザーを作成しましょう。作成できたら管理者ユーザーでログインして、Runner用のトークンを取得します。

`Admin Area`に入り`Runners`ページを見ると、`Registration token is xxxxxxx`という記述があるので、このトークンを控えておきます。

# GitLab Runnerの準備
GitLab Runnerに、Runnerを登録することでCIを走らせることができます。Runner側のコンテナに情報を入力して、登録作業を済ませましょう。

まずはGitLab Runnerのコンテナ名を調べます。

```bash
$ docker ps
CONTAINER ID        IMAGE                         COMMAND                  CREATED             STATUS                        PORTS                                                   NAMES
cea8d4827c73        gitlab/gitlab-runner:alpine   "/usr/bin/dumb-init /"   38 hours ago        Up 38 hours                                                                           gitlab_gitlab-runner_1
```

今回は`gitlab_gitlab-runner_1`であるとわかりました。では実際にRunnerを登録します。`url`欄と`registration-token`欄は、実際の環境に合わせて変更してください。コマンドを実行すると対話環境が始まりますが、必要な情報はほとんど引数として与えてしまっているため、終わるまでEnterを連打していれば大丈夫です。Tagに関しては、後で編集できるのでやはり気にしなくてOKです。

```bash
$ docker exec -it gitlab_gitlab-runner_1 gitlab-ci-multi-runner register -n \
  --url https://gitlab.example.com/ \
  --registration-token REGISTRATION_TOKEN \
  --executor docker \
  --description "LaTeX Runner" \
  --docker-image "aruneko/texlive"
```

# リポジトリの準備
## latexmkの準備
LaTeXのコンパイルには、おなじみ`latexmk`を用います。いろいろな状況を勝手に判断して、全自動でTeXファイルからPDFファイルを生成してくれるすごいやつです。texファイルがあるディレクトリと同一の階層に、`.latexmkrc`を用意しましょう。今回は、uplatex環境を前提としたサンプルをご紹介します。

```perl
#!/usr/bin/env perl
$latex            = 'uplatex -shell-escape -synctex=1 -halt-on-error';
$latex_silent     = 'uplatex -shell-escape -synctex=1 -halt-on-error -interaction=batchmode';
$bibtex           = 'upbibtex %O %B';
$biber            = 'biber %O --bblencoding=utf8 -u -U --output_safechars %B';
$dvipdf           = 'dvipdfmx %O -o %D %S';
$makeindex        = 'mendex %O -o %D %S';
$max_repeat       = 5;
$pdf_mode         = 3;
```

## .gitlab-ci.ymlの準備
latexmkの設定が済んだら、CIの手順書である`.gitlab-ci.yml`を準備しましょう。といっても、ビルドはすべてlatexmkが肩代わりしてくれるので、とてもシンプルに記述できます。

今回、TeX Live環境には[hionoさんが作成したDocker Image](https://hub.docker.com/r/hiono/texlive/)を[私がフォークしたもの](https://hub.docker.com/r/aruneko/texlive/)を利用します。フォークした理由は単純で、ソースコードを掲載するためのmintedを使う都合でPygmentsをインストールしておきたかったのと、いつも使っているbxjsclsのバージョンを上げておきたかったからです。

今回texファイル名が`thesis`である前提で書いてありますが、そこは適宜変更してください。

```yaml
image: aruneko/texlive:latest

compile_uplatex:
  script:
    - latexmk thesis.tex
  artifacts:
    paths:
      - thesis.pdf
```

# CIの実行
2つの隠しファイルができあがったら、addしてcommitしてpushしましょう。

```bash
$ git add .latexmkrc .gitlab-ci.yml
$ git commit -m "CIに対応"
$ git push -u origin master
```

あとはCIが走るのを眺めるだけです。`Pipelines`ページで閲覧できます。完成品もここからダウンロードできるようになっています。

# おわりに
既存のものをうまく組み合わせて、LaTeXコンパイルを自動化することができました。忙しい季節、少しでも手間を減らして__本質__に集中しましょう！