GitHub Actions でタグ付きリリースするのに使用するDockerfile を執筆時にも利用できるようにした

概要

GitHub Actions で、LaTeXコンパイル・PDF化しタグ付きリリースをするという記事は、ありましたが、手元でコンパイルをする場合にはローカルのコンピュータにインストールしたLaTeXを利用しているようでした。GitHub Actions でPDF生成を行うのであれば、ローカルでのコンパイルもDocker環境にしたいと考えたため、同じDockerfileから生成されたイメージとmakefileを利用するように変更しました。

手順

ここでは、下に示すディレクトリ構造となっているとします。

.
|-- .github
|     |-- actions
|     |    |-- latex
|     |        |-- Dockerfile
|     |        |-- texlive.profile
|     |-- workflows
|         |-- main.yml
|-- Makefile
|-- latexmkrc
|-- main.ltx
|-- ***.ltx
|-- ...

初めに、LaTeX のインストールプロファイルを用意します。 インストーラを実行すると、インストールのオプションを聞かれるので、そこでインストーラープロファイルの作成を選択肢、プロファイルを生成します。 デフォルトでは、texlive.profileとなっているはずです。 これをインストーラープロファイルを用いてTeX Liveをインストールしよう - Qiita を参考にしてカスタマイズします。 Docker イメージを早く構築するため、コンパイルに必要の無いドキュメントやソースファイル等を含まずサイズが小さくなるように以下の内容を追加しました。

# Exclude document and source files
option_doc 0
option_src 0

option_autobackup 0

よりインストールを早くしたい場合は、使用していないパッケージをインストール項目から外すようにするとよいと思います。 最終的に以下のインストーラープロファイルになりました。

# texlive.profile written on Sun Feb 16 17:23:18 2020 UTC
# It will NOT be updated and reflects only the
# installation profile at installation time.
selected_scheme scheme-full
TEXDIR /usr/local/texlive/latest
TEXMFCONFIG $TEXMFSYSCONFIG
TEXMFHOME $TEXMFLOCAL
TEXMFLOCAL /usr/local/texlive/texmf-local
TEXMFSYSCONFIG /usr/local/texlive/latest/texmf-config
TEXMFSYSVAR /usr/local/texlive/latest/texmf-var
TEXMFVAR $TEXMFSYSVAR
binary_x86_64-linux 1
instopt_adjustpath 1
instopt_adjustrepo 1
instopt_letter 0
instopt_portable 1
instopt_write18_restricted 1
tlpdbopt_autobackup 1
tlpdbopt_backupdir tlpkg/backups
tlpdbopt_create_formats 1
tlpdbopt_desktop_integration 1
tlpdbopt_file_assocs 1
tlpdbopt_generate_updmap 0
tlpdbopt_install_docfiles 1
tlpdbopt_install_srcfiles 1
tlpdbopt_post_code 1
tlpdbopt_sys_bin /usr/local/bin
tlpdbopt_sys_info /usr/local/share/info
tlpdbopt_sys_man /usr/local/share/man
tlpdbopt_w32_multi_user 1

# Exclude document and source files
option_doc 0
option_src 0

option_autobackup 0

なお、その都度最新のtexliveをインストールしてくることから、LaTeXのインストール先ディレクトリ名を年度からlatestに変更しています。

Dockerfileは、次のようにしました。

FROM ubuntu:latest

RUN apt-get update \
    && apt-get install -y \
    python3 \
    git \
    wget \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*
ADD texlive.profile /texlive.profile
# Install LaTeX
RUN wget http://mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz
RUN tar xvf install-tl-unx.tar.gz \
    && cd install-tl* \
    && ./install-tl -no-gui -repository http://mirror.ctan.org/systems/texlive/tlnet/ --profile=/texlive.profile
RUN /usr/local/texlive/latest/bin/x86_64-linux/tlmgr path add

RUN mkdir -p /workdir
WORKDIR /workdir

CMD ["/bin/bash"]

もし、標準で同梱されているパッケージ意外を使用したくなった場合は、RUN mkdir -p /workdirの前に追加用のコマンド実行文を書けば追加できます。

先に、手元でコンパイルするときのためにMakeFileとlatexmkrcを作ります。 ここで作成したMakeFileGitHub Actionsでも使用し、イメージのビルド・PDFの生成を行います。 イメージのビルドは、make buildで、生成したイメージを使用してコンパイルを行う際は、make startコンパイルができるようになりました。 pLaTex以外を使用している方は、適宜latexmkrcを変更してください。

# MakeFile
NAME=mylatexlive
VERSION=0.1

build:
    docker build -t $(NAME):$(VERSION) .github/actions/latex/

start:
    docker run --rm -i \
        -v $(PWD):/workdir $(NAME):$(VERSION) \
        latexmk *.ltx
# latexmkrc
#!/usr/bin/env perl
$latex = 'platex %O -synctex=1 -interaction=nonstopmode %S';
$xelatex = 'xelatex %O -synctex=1 -interaction=nonstopmode %S';
$biber = 'biber %O --bblencoding=utf8 -u -U --output_safechars %B';
$bibtex = 'upbibtex %O %B';
$makeindex = 'upmendex %O -o %D %S';
$dvipdf = 'dvipdfmx %O -o %D %S';
$dvips = 'dvips %O -z -f %S | convbkmk -u > %D';
$ps2pdf = 'ps2pdf %O %S %D';
$pdf_mode = 3;
$max_repeat=5;
$pvc_view_file_via_temporary=0;
$pdf_previewer='open -ga zathura -reuse-instance %O %S';

最後に、GitHub Actions の本体であるmain.ymlを作成していきます。 内容的には、ほぼGitHub Actions で TeX をコンパイル・PDF 化してタグ付きリリースする話 - Qiitaと同じですが、参考記事では Dockerfile から実行していた entrypoint.sh にある内容をmain.ymlから実行するように変更しています。 こうすることで、Dockerfileを GitHub Actions だけでなくローカルでの執筆でも使用できるようになります。

name: LaTeX to PDF

on:
  push:
    tags: v*.*.*

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      # - name: Set up Git repository
    - uses: actions/checkout@v2
    - name: Build docker image
      run: make build
    - name: Release PDF file
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        make start
        res=`curl -H "Authorization: token $GITHUB_TOKEN" -X POST https://api.github.com/repos/$GITHUB_REPOSITORY/releases \
        -d "
        {
          \"tag_name\": \"$(echo ${GITHUB_REF:10})\",
          \"target_commitish\": \"$GITHUB_SHA\",
          \"name\": \"main.pdf $(echo ${GITHUB_REF:10})\",
          \"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

これで、v..* 形式のタグをpushするとGitHub Actions が走り、main.pdfがリリースされるようになりました。

実際に実行したところ、pushからリリースにファイルが上がるまでの時間は、install-tlの実行に時間がかかってしまっているため、40分程度となっていました。 よりミニマムな構成でのLaTeXインストールにすれば、時間の短縮ができると思いますが、やりすぎると執筆時にパッケージを追加する都度にDockerイメージに手を加える必要がでてくるのが悩ましいところです。 3GByte超あるDockerイメージを許容するかはおいておくとして、...makefile内にパッケージ追加ジョブやイメージ削除ジョブも定義するとより使いやすくなると思います。

参考ページ