GitHub Actions で Latexmk＆タグを使ってコンパイルする TeX ファイルを指定する話

# 概要
これまで筆者は

- [GitHub Actions で TeX のコンパイル（なお苦戦した模様）](https://qiita.com/denkiuo604/items/63b8c34a60a2340727b1)
- [GitHub Actions で TeX をコンパイル・PDF 化してタグ付きリリース](https://qiita.com/denkiuo604/items/137a1b3fc1955cfb9c58)

に挑戦してきた．

しかし，上に挙げた記事内の方法ではコンパイルが一度しか実行されない．従って，相互参照を含んでいたり BibTeX を利用していたりする場合，生成される PDF ファイルは (??) を含むなど不完全なものとなる．そこで，一度実行すれば自動的に必要なだけコンパイルをやってくれる Latexmk を利用して，この問題を解決する．

また，上に挙げた記事内の方法ではひとつの TeX ファイルのコンパイルにしか対応していなかった．これはコードの中でコンパイルする TeX ファイルを指定していたからである．そこで，コードでファイルを指定するのではなく，Git の機能の一つであるタグを用いてファイルを指定することで，この問題を解決する．

# 詳細
コンパイルさせたいファイルをタグ名で指定するため，タグ名は必ず `ファイル名-ver.x` にする．例えば `doc1.tex` というファイルをコンパイルさせたいなら，タグ名は `doc1-ver.1` などとする．

## 必要ファイルの準備
下記の通り，必要最低限のファイルを用意する．同じものが[このリポジトリ](https://github.com/denkiuo604/latexmk)にある．

```:ファイルツリー
.
│  .latexmkrc
│
└─.github
    ├─actions
    │  └─latex
    │          Dockerfile
    │          entrypoint.sh
    │
    └─workflows
            latexmk.yml
```

### .latexmkrc
`.latexmkrc` は Latexmk 実行時に何[^1]を使ってコンパイルするかを記述したファイルである．

```:.latexmkrc
$latex  = 'platex -synctex=1 %O %S';
$bibtex = 'pbibtex %O %B';
$dvipdf = 'dvipdfmx %O -o %D %S';
```
[^1]: platex か latex か，pbibtex か bibtex かなど．ここでは最低限の設定のみしている．

### Dockerfile
`Dockerfile` にはアクション実行時に行われる動作が一通り書かれている．

```dockerfile:Dockerfile
FROM ubuntu:latest

RUN apt-get update \
  && apt-get install -y --no-install-recommends \
    curl \
    python3 \
    latexmk \
    lmodern \
    texlive \
    texlive-latex-extra \
    texlive-lang-japanese \
  && rm -rf /var/lib/apt/lists/*

RUN mktexlsr && mkdir -p /app
WORKDIR /app

ADD entrypoint.sh /entrypoint.sh
RUN ["chmod", "+x", "/entrypoint.sh"]
ENTRYPOINT ["/entrypoint.sh"]
```

### entrypoint.sh
`entrypoint.sh` は `Dockerfile` の最後で実行されるシェルスクリプトである．Latexmk の実行と，生成された PDF ファイルのリリース実行が書かれている．
3行目の `GITHUB_REF` には `refs/tags/タグ名` という値が代入されているので，最初の10文字を排除して `TAG_NAME` としている．また，`TAG_NAME` は `ファイル名-ver.x` という形に決めていたので，4行目では後ろから見て最初のハイフン以降を排除して `FILE_NAME` としている．

```sh:entrypoint.sh
#!/bin/bash
set -eux
TAG_NAME=${GITHUB_REF:10}
FILE_NAME=${TAG_NAME%-*}

# build pdf (change if necessary)
latexmk -pdfdvi $FILE_NAME.tex

# create release
res=`curl -H "Authorization: token $GITHUB_TOKEN" -X POST https://api.github.com/repos/$GITHUB_REPOSITORY/releases \
-d "
{
  \"tag_name\": \"$TAG_NAME\",
  \"target_commitish\": \"$GITHUB_SHA\",
  \"name\": \"$TAG_NAME\",
  \"draft\": false,
  \"prerelease\": false
}"`

# extract release id
rel_id=`echo ${res} | python3 -c 'import json,sys;print(json.load(sys.stdin)["id"])'`

# upload built pdf
curl -H "Authorization: token $GITHUB_TOKEN" -X POST https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/${rel_id}/assets?name=$FILE_NAME.pdf\
  --header 'Content-Type: application/pdf'\
  --upload-file $FILE_NAME.pdf
```

### latexmk.yml
`latexmk.yml` にはアクションの場所や実行される条件が記述されている．実行条件は

- push された中身に TeX ファイルが含まれていること
- タグ名が `*-ver.*` の形になっていること

としている．

```yml:latexmk.yml
name: LaTeX to PDF (Latexmk)

on:
  push:
    paths: '*.tex'
    tags: '*-ver.*'

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: Set up Git repository
        uses: actions/checkout@v1
      - name: Build docker image
        uses: denkiuo604/latexmk/.github/actions/latex@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

これでアクション実行に必要なファイルは揃う．

## いざリリース
コンパイルしたい TeX ファイルを `.latexmkrc` と同じディレクトリに配置する．[このリポジトリ](https://github.com/denkiuo604/latexmk)では，例えば次のファイルを用いている．

```tex:doc2.tex
\documentclass{jsarticle}
\usepackage{amssymb}

\begin{document}

$(S,\Sigma,\mu)$を測度空間とする．
このとき，相異なる$i,j$に対して$A_i\cap A_j\neq\varnothing$を満たす
任意の$A_1,A_2,\cdots\in\Sigma$に対して
\begin{equation}\label{可算加法性}
    \mu\left(\bigcup_{k=1}^\infty A_k\right)=\sum_{k=1}^\infty\mu(A_k)
\end{equation}
が成り立つ．
また，(\ref{可算加法性})において$A_{n+1}=A_{n+2}=\cdots=\varnothing$とすることで
\begin{equation}\label{有限加法性}
    \mu\left(\bigcup_{k=1}^nA_k\right)=\sum_{k=1}^n\mu(A_k)
\end{equation}
も得られる．

\end{document}
```

上記 `doc2.tex` は相互参照を含むため，コンパイルを少なくとも2回実行しなければならない．しかし，Latexmk を使えば必要回数だけ自動でコンパイルしてくれる．

TeX ファイルを配置できたら，タグ名のルールに注意して push すればよい．今の場合，タグ名は `doc2-ver.1` などとする．実際の結果は [GitHub リポジトリ](https://github.com/denkiuo604/latexmk)を参照のこと．

# 参考
- [Latexmk - TeX Wiki](https://texwiki.texjp.org/?Latexmk)
- [シェルスクリプト（bash） 文字列処理（部分文字列・置換・長さ・連結・分割） – バイオインフォ 道場 [bioinfo-Dojo]](http://bioinfo-dojo.net/2017/09/15/bash_string/)