Texでの参照/引用エラーを起こさないために

## WHY
Texで論文を書くとあるあるなのが参照/引用エラーですよね？
![スクリーンショット 2020-01-12 17.45.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114953/dc31e5e7-bd7d-b82c-e83c-fcc2d3ee5ebd.png)

論文提出したあとにこれを見つけるととても恥ずかしいです///

そもそも参照/引用エラーって言ってますけど、これ警告レベルなので、ビルドの時に途中で止めてくれないんですよね。
僕はこれエラーレベルでいいと思うんですけど...

そこで、今回はCIで参照/引用エラーを検出してSlackで通知してくれるようにしましょう。

## WHAT
今回はCIにはGitHub Actionsを使って、エラーのチェックをしたいと思います。

### What is CI / Github Actions?
CI(Continuous Integration)は、細かい頻度でビルドとテストを繰り返し行うことで、コードの品質を保つために用いられます。
CIサービスはCircleCIやTravisなどが有名ですが、昨年GitHubが提供するGitHub Actionsが一般公開されたので今回はこちらを用います。

## HOW
### 前提条件
エンジニアたるもの論文のソースコードもバージョン管理していると思いますが、今回は、git/GitHubで管理されている前提であるとします。

そして、Texのコンパイルにはlatexmkを使いましょう。
```platex main && pbibtex main && platex main && dvipdfmx main```
とかやってもいいんですが、もっと簡単にlatexmkを使うと、コンパイルが楽になります。
それと、`build/`に中間/生成ファイルが配置されるのでプロジェクトをきれいに保てます。
一度設定すれば、 ```latexmk main```だけでコンパイルできますよ。

その設定は、以下のようなファイルをtexプロジェクトに追加するだけ。

```perl:.latexmkrc
#!/usr/bin/env perl
# file          .latexmkrc

## latex commands
$latex            = 'pdflatex -synctex=1 -halt-on-error';
$latex_silent     = 'pdflatex -synctex=1 -halt-on-error -interaction=batchmode';
$bibtex           = 'pbibtex';
$dvipdf           = 'dvipdfmx %O -o %D %S';
$makeindex        = 'mendex %O -o %D %S';
$max_repeat       = 5;

## pdf mode
$pdf_mode         = 3; # 0: none, 1: pdflatex, 2: ps2pdf, 3: dvipdfmx

## output directory
$aux_dir          = "build/";
$out_dir          = "build/";
```

### CIの設定
まず、https://slack.com/apps/A0F7XDUAZ-incoming-webhooks からSlackのIncomingWebHooksのURLを取得し、GitHubのリポジトリの設定からSecretsにそのURLを登録しましょう。
![スクリーンショット 2020-01-12 17.23.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114953/dc51362b-e3ea-c6ae-5854-a84a66895407.png)

そして、以下のファイルをコミットしてプッシュしましょう。

```.github/workflows/main.yml
name: compile tex

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    container:
      image: paperist/alpine-texlive-ja:latest
      volumes: 
        - .:/workdir
    steps:
      - uses: actions/checkout@v1
        with:
          fetch-depth: 1
      - name: compile 
        run: |
          latexmk main
      - name: check warning
        run: |
          ! grep -e "LaTeX Warning: Reference" -e "LaTeX Warning: Citation" build/main.log
          status=$?
          exit $status
      # ここのコメントアウトを外すと、生成したpdfをArtifactにアップロードしてくれる。(Artifactは上限があるのでおすすめしない。)
      # - uses: actions/upload-artifact@master
      #   with:
      #     name: main.pdf
      #     path: build/main.pdf

      - uses: 8398a7/action-slack@v2
        with:
          status: ${{ job.status }}
          author_name: Github Actions
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
        if: failure()
```

そうすると、こんなかんじでCIが走ります。
![スクリーンショット 2020-01-12 17.26.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114953/0bbadee0-b526-f2c3-1778-fbb7050b1132.png)

今回は、ビルドが失敗した時のみSlackに通知するようにしたので、失敗するとこんなかんじのメッセージが届きます。
![スクリーンショット_2020-01-12_17_27_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114953/9af1ae0a-833d-59e5-bf22-589fd12b061c.png)


## Conclusion
これでTexのビルドエラーや、参照/引用エラーを含めてエラー時にSlackに通知されるようにできました。
論文執筆はいっつもギリギリで作業してると思うので、エラーチェックの仕組みを作って細かい頻度で修正を加えられると精神的にも安心して執筆できると思います。

卒論や修論、学会論文などの執筆の手助けになれば幸いです。



## FYI しくみの説明
### コンパイル環境
GitHub Actions の実行環境にはDockerが選択できます。
日本語Texをコンパイルできる環境が https://hub.docker.com/r/paperist/alpine-texlive-ja で提供されているのでこちらを用います。

### 参照/引用エラーのチェック
参照/引用の警告は、以下の警告になります。
- `LaTeX Warning: Reference {label} on page {page} undefined on input line {line}.`
- `LaTeX Warning: Citation {label} on page {page} undefined on input line {line}.`

そして、コンパイル時のログが`build/main.log`に吐かれるので、このログファイルに上の警告が含まれるかをチェックすることで、参照/引用エラーを見つけることができます。

```
! grep -e "LaTeX Warning: Reference" -e "LaTeX Warning: Citation" build/main.log
status=$?
exit $status
```
grep は見つからなかった時にエラーコードで終了するので、それを反転し終了することで、参照/引用エラー時にCIが失敗するようにしています。