LaTeX 文書のコンパイルを GitHub Actions で自動化する

はじめに

latexmk で組版の繰り返しを自動化し、TeX Live 入りコンテナと Makefile で環境を固定して手元でコンパイルできるようにすると、あと一歩で「push したら勝手にビルドされ、PDF が落ちてくる」状態にできます。

この記事では、その組版を GitHub Actions に載せます。ローカルで使っているのと同じ TeX Live イメージを CI 上でも使うので、「手元で通れば CI でも通る」が保てます。

最小のワークフロー

.github/workflows/latex.yml を置きます。container: にローカルと同じイメージを指定すると、ジョブの各ステップがそのコンテナの中で実行されます。TeX Live と latexmk はイメージに入っているので、追加インストールは要りません。

name: build-pdf

on:
  push:
    paths: ['**.tex', '**.bib', '.latexmkrc', '.github/workflows/latex.yml']
  pull_request:
    paths: ['**.tex', '**.bib', '.latexmkrc']

# 同じ ref で新しい push があったら古い実行は打ち切る
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest
    container: texlive/texlive:TL2024      # ローカルと同じタグに揃える
    steps:
      - uses: actions/checkout@v4

      - name: Compile
        run: latexmk main.tex

      - name: Upload PDF
        uses: actions/upload-artifact@v4
        with:
          name: main-pdf
          path: main.pdf

      # 失敗時はログも持ち帰れるようにしておく
      - name: Upload log on failure
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: latex-log
          path: '*.log'

texlive/texlive イメージは git を含むため、actions/checkout はコンテナ内でもそのまま動きます。paths: フィルタで、原稿に関係ないコミットではワークフローを起こさないようにしています。

Makefile を再利用する

TeX Live 入りコンテナの Makefile は「docker run でコンテナを起動し、その中で latexmk を呼ぶ」構造でした。GitHub Actions ではジョブ自体がすでにコンテナ内なので、docker run の層は不要です。build ターゲットの中身が latexmk $(DOC).tex だけなら、CI からは次のように直接呼べます。

      - name: Compile
        run: make build            # 中身は latexmk main.tex

コンテナ起動の有無だけが違い、組版コマンドとその設定(.latexmkrc)はローカルと CI で完全に同一になります。「ローカルは make、CI はイメージ直実行、コマンドは共通」という形が、そのまま GitHub Actions にも当てはまります。

生成物の受け取り方

用途に応じて 3 通りあります。

1. Artifact として毎回受け取る

上の例のとおり actions/upload-artifact を使います。実行結果ページからダウンロードできます。保持期間は既定 90 日で、retention-days: で短くできます。レビュー用の一時的な PDF はこれで十分です。

2. Pull Request にコメントで知らせる

PR のたびにビルドが通ったこと(と Artifact へのリンク)をコメントしておくと、レビュアーが迷いません。

      - name: Comment on PR
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: `PDF をビルドしました → 実行ページの Artifacts からダウンロードできます。`
            })

3. タグを打ったら Release に添付する

版として確定した PDF を配布したいときは、タグ push をトリガーに Release へ添付します。

on:
  push:
    tags: ['v*']

jobs:
  release:
    runs-on: ubuntu-latest
    container: texlive/texlive:TL2024
    permissions:
      contents: write            # Release 作成に必要
    steps:
      - uses: actions/checkout@v4
      - run: latexmk main.tex
      - uses: softprops/action-gh-release@v2
        with:
          files: main.pdf

Pull Request で差分を見る

原稿レビューでは「どこが変わったか」が PDF 上で見えると効率的です。latexdiff で旧版との差分文書を作り、その PDF も一緒に上げておきます。

      - name: Build diff against base branch
        if: github.event_name == 'pull_request'
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"
          git fetch origin "${{ github.base_ref }}" --depth=1
          git show "origin/${{ github.base_ref }}:main.tex" > base.tex
          latexdiff base.tex main.tex > diff.tex
          latexmk diff.tex

      - name: Upload diff PDF
        if: github.event_name == 'pull_request'
        uses: actions/upload-artifact@v4
        with:
          name: diff-pdf
          path: diff.pdf

safe.directory の指定は、コンテナ内の利用者とチェックアウト先の所有者がずれて git がリポジトリを拒否するのを避けるためです。

ビルドを速く・安定させる

  • イメージのタグを固定する:latest ではなく TL2024 のように年号で固定すると、TeX Live の更新でビルドが急に変わることがなくなります。ローカルの Dockerfile と同じタグに揃えるのが要点です。
  • tlmgr install を CI でやらない:必要なパッケージは Dockerfile の段階でイメージ側に入れておき、CI では入れない。実行ごとのネットワーク待ちが消えます。
  • latexmk に任せる:組版回数の判断は latexmk がやるので、ワークフロー側で latex を複数回呼ぶような記述は不要です。
  • -interaction=nonstopmode を .latexmkrc に入れておく:エラーで対話待ちになり CI がハングするのを防ぎます(latexmk の記事の設定例に含めてあります)。

なお、イメージを用意せず手軽に済ませたい場合は xu-cheng/latex-action のような専用アクションもありますが、やっていることは「TeX Live 環境で latexmk を回す」で同じです。ローカルとイメージを共有したいなら container: 方式が素直です。

関連記事

まとめ

  • ローカルで使っている TeX Live イメージを container: に指定すれば、GitHub Actions でも同じ環境で組版できる。
  • CI ではコンテナ起動が不要なので、latexmk(または make build)を直接呼ぶだけ。設定は .latexmkrc に集約してローカルと共有する。
  • 成果物は Artifact/PR コメント/Release 添付から用途に合わせて選ぶ。latexdiff を挟めば PR で変更箇所を PDF で確認できる。

「latexmk で繰り返しを自動化 → コンテナで環境を固定 → GitHub Actions で契機を自動化」と重ねると、原稿を push するだけで最新の PDF が手に入る状態になります。

LaTeX組版・教材校正のご依頼・ご相談はコレクトコネクトへお問い合わせください。

← コラム一覧へ