GitHub Actions で TeX のコンパイルと PDF 化をさせようとしたら意外に苦戦した話

# 概要
GitHub Actions を使って「push したら TeX のコンパイルと PDF 化を実行する」を実現しようとしたら，本質とはあまり関係のない部分で結構苦戦したので，その内容をまとめる．

# 詳細
- [GitHubだけでLatexをコンパイルしてPDFをリリースにアップロードする - Qiita](https://qiita.com/takuseno/items/2b4c4a129205d03526ad)
- [GitHub Actionsを使って，TeXをビルドする仕組み作ってみた - 夜は短し歩けよ未来大生](http://tkr1205.hatenablog.com/entry/2019/10/17/172611)

を参考にリポジトリを準備する．どこで苦戦したかを明らかにするために，最初に **修正前** のソースコードを提示する．すなわち，これから示すソースコードたちをコピペして使ってもエラーを吐くので注意．修正したものは本記事の最後に示す．

## リポジトリの準備: 修正前
GitHub のリポジトリに以下の通りファイルを用意．

```
.
│  main.tex
│
└─.github
    │
    ├─actions
    │  └─latex
    │          Dockerfile
    │          entrypoint.sh
    │
    └─workflows
            main.yml
```
`.github` 内のそれぞれのファイルの中身は次の通り．

```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
ENTRYPOINT ["/entrypoint.sh"]
```

```shell:entrypoint.sh
#!/bin/bash
set -eux

# build pdf (change if necessary)
ptex2pdf main.tex

# create release
res=`curl -H "Authorization: token $GITHUB_TOKEN" -X POST https://api.github.com/repos/$GITHUB_REPOSITORY/releases \
-d "
{
  \"tag_name\": \"v$GITHUB_SHA\",
  \"target_commitish\": \"$GITHUB_SHA\",
  \"name\": \"v$GITHUB_SHA\",
  \"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=main.pdf\
  --header 'Content-Type: application/pdf'\
  --upload-file main.pdf
```

```yml:main.yml
name: LaTeX to PDF

on:
  push:
    paths: main.tex

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: Set up Git repository
        uses: actions/checkout@v1
      - name: Build docker image
        uses: ユーザー名/リポジトリ名/.github/actions/latex@master
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
```

## 困った点その1: permission denied
`entrypoint.sh` の実行段階で

```
/usr/bin/docker: Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"/entrypoint.sh\": permission denied": unknown.
```
というエラーが出た．軽く調べたのち

- [Docker Run - Error Permission Denied on CMD ["/node/execure.sh"] - Docker Hub - Docker Forums](https://forums.docker.com/t/docker-run-error-permission-denied-on-cmd-node-execure-sh/17129)

を参考に，`Dockerfile` で `entrypoint.sh` に実行権限を与えるように直した．

```dockerfile:Dockerfileの最終行付近
ADD entrypoint.sh /entrypoint.sh
RUN ["chmod", "+x", "/entrypoint.sh"]    # この行が追加部分
ENTRYPOINT ["/entrypoint.sh"]
```

## 困った点その2: exec user process caused "no such file or directory"
同じく `entrypoint.sh` の実行段階で

```
standard_init_linux.go:211: exec user process caused "no such file or directory"
```
というエラー文が出た．調べたところ

- [dockerfile - standard_init_linux.go:190: exec user process caused "no such file or directory" - Docker - Stack Overflow](https://stackoverflow.com/questions/51508150/standard-init-linux-go190-exec-user-process-caused-no-such-file-or-directory)

と同一の症状だったため，`entrypoint.sh` の改行コードが CRLF なのを LF に直したところ，エラーは解消された．

## 困った点その3: ptex2pdf の実行オプション
jsarticle を使いたかったのだが，`entrypoint.sh` 内で [ptex2pdf](https://texwiki.texjp.org/?ptex2pdf) をそのまま実行していたため

```
! Undefined control sequence.
l.1 \documentstyle
                  {jsarticle}
? 
! Emergency stop.
l.1 \documentstyle
                  {jsarticle}
```
というエラー文が出た．これは適当なオプションを付けることで解消．

```shell:entrypoint.shの5行目
#!/bin/bash
set -eux

# build pdf (change if necessary)
ptex2pdf -l -ot -kanji=utf8 main.tex    # この行が変更点
```

## 困った点その4: GITHUB_TOKEN
ここまでで，GitHub 上での TeX のコンパイルと PDF 化は実現される．その次には「生成された PDF をリリースする」という動作が発生するのだが，そこで発生したエラーが下記である．

```
/entrypoint.sh: line 16: GITHUB_TOKEN: unbound variable
+ res=
```
結論のみ述べると，`entrypoint.sh` に [GITHUB_TOKEN](https://help.github.com/ja/github/automating-your-workflow-with-github-actions/virtual-environments-for-github-actions#environment-variables) がきちんと受け渡されていないことが原因であった．そこで，`main.yml` を次のように修正した．

```yml:main.ymlの最終行付近
      - name: Build docker image
        uses: ユーザー名/リポジトリ名/.github/actions/latex@master    # この行以下が修正箇所
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
これでめでたく PDF ファイルのリリースまでが実現される．

## リポジトリの準備: 修正後
修正後のソースコードは以下の通りである．

```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"]
```

```shell:entrypoint.sh
#!/bin/bash
set -eux

# build pdf (change if necessary)
ptex2pdf -l -ot -kanji=utf8 main.tex

# create release
res=`curl -H "Authorization: token $GITHUB_TOKEN" -X POST https://api.github.com/repos/$GITHUB_REPOSITORY/releases \
-d "
{
  \"tag_name\": \"v$GITHUB_SHA\",
  \"target_commitish\": \"$GITHUB_SHA\",
  \"name\": \"v$GITHUB_SHA\",
  \"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=main.pdf\
  --header 'Content-Type: application/pdf'\
  --upload-file main.pdf
```

```yml:main.yml
name: LaTeX to PDF

on:
  push:
    paths: main.tex

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: Set up Git repository
        uses: actions/checkout@v1
      - name: Build docker image
        uses: ユーザー名/リポジトリ名/.github/actions/latex@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
これらのファイルを配置し，実際に PDF がリリースされているリポジトリは[こちら](https://github.com/denkiuo604/tex-to-pdf)．

# 参考
- [GitHubだけでLatexをコンパイルしてPDFをリリースにアップロードする - Qiita](https://qiita.com/takuseno/items/2b4c4a129205d03526ad)
- [GitHub Actionsを使って，TeXをビルドする仕組み作ってみた - 夜は短し歩けよ未来大生](http://tkr1205.hatenablog.com/entry/2019/10/17/172611)
- [Docker Run - Error Permission Denied on CMD ["/node/execure.sh"] - Docker Hub - Docker Forums](https://forums.docker.com/t/docker-run-error-permission-denied-on-cmd-node-execure-sh/17129)
- [dockerfile - standard_init_linux.go:190: exec user process caused "no such file or directory" - Docker - Stack Overflow](https://stackoverflow.com/questions/51508150/standard-init-linux-go190-exec-user-process-caused-no-such-file-or-directory)
- [ptex2pdf - TeX Wiki](https://texwiki.texjp.org/?ptex2pdf)
- [GitHub Actionsの仮想環境 - GitHub ヘルプ](https://help.github.com/ja/github/automating-your-workflow-with-github-actions/virtual-environments-for-github-actions)