はじめに
去年の年末からTeXを書きはじめ、色々調べて環境を構築したので記事にしたいと思います。
LuaLaTeX + llmkが実行できる環境をDockerfileで作成して、VSCodeで執筆、GitHubにファイルをプッシュすることで、GitHub ActionsでCI/CDを実行して、releaseにPDFファイルをアップロードするような仕組みを作りました。
リポジトリ:pyama2000/tex2pdf: Tex files
Step 1. (La)TeX環境をDockerで構築
なぜDockerで環境を構築したかというと、以前macOSにTeX Liveをインストールした際に作業が複雑でゴミファイルも多数残ってしまい、それがトラウマとなっているからです。そこで、インストール等に失敗してもホスト側に影響がない、また端末・OSなどの環境に左右されずにどこでも執筆できるようにDockerを用いました。
はじめの頃はPaperist/docker-alpine-texlive-ja: Minimal TeX Live image for Japanese based on alpineこちらのイメージを使ってPDFファイルを生成していましたが、調べていくうちにLuaLaTeXが比較的新しいLaTeXエンジンであることがわかったので、LuaLaTeXが使える環境を作成していきたいと思います。
※ これから説明する手順で作成するDockerfileをビルドしたものはDocker Hubに上がっているので、特に必要がない方は以下のコマンドを実行していただいて、この章をとばすこともできます。
$ docker pull pyama0327/lualatex-haranoaji-llmk:latest
Dockerイメージ概要
Dockerfileを作成するにあたって、TeX Live 2019 + 原ノ味フォント + llmk の Docker コンテナを作る - Qiitaを参考にして作成しています。こちらの記事ではTeX Live 2019をフルでインストールしているのですが、できるだけイメージのサイズを減らしたかったのとLuaLaTeXのみを使用するため、ベースイメージをalpine、TeXの環境をschema basic + collection-langjapaneseとしました。
LaTeXのコンパイルにlatexmkを利用することが主流らしいですが、今回は参考にした記事と同様にllmk
という比較的新しいツールを使ってコンパイルしたいと思います。また、フォントも原ノ味フォントを使用しています。
Dockerfile
この記事では一部分しか解説しないので、完全版が見たい場合はこちらを確認してください。
Step 1-1. (Lua)LaTeXをインストール
今回はTeX Liveに含まれるすべてのパッケージをインストールするscheme-fullではなく、なるべくイメージサイズを小さくするためにscheme-basicを利用します。このスキームはLaTeXを使うために必要な最小限のパッケージをインストールします。
さらに日本語に対応するためにcollection-langjapaneseやcollection-latexextraなどをtlmgr
でインストールします。
Step 1-2. llmk
をインストール
llmk
は以下のコマンドを実行するだけでシンプルにインストールすることができます。
$ wget -qO /usr/local/bin/llmk https://raw.githubusercontent.com/wtsnjp/llmk/master/llmk.lua
$ chmod +x /usr/local/bin/llmk
Step 1-3. 原ノ味フォントをインストール、TeXに適用
LuaLatexはすでに原ノ味フォントを利用できるプリセットに対応しているため、複雑な作業は必要ありません。
# 原ノ味フォントをダウンロード
$ git clone https://github.com/trueroad/HaranoAjiFonts.git
# TeXのフォントディレクトリーにコピー
$ mkdir -p "${FONT_PATH}/opentype/haranoaji"
$ cp -p ./HaranoAjiFonts/*.otf "${FONT_PATH}/opentype/haranoaji/"
$ rm -rf ./HaranoAjiFonts
# TeXで利用できるようにする
$ mktexlsr
Step 1-4. イメージを作成、DockerHubに公開
完成したDockerfileをビルドしてイメージを作成してDockerHubに公開しましょう。
この作業は必須ではありませんが、この環境を構築するのに5分以上かかるのでビルドして公開したほうがVSCodeやGitHub Actionsで利用する際に時間短縮になります。
※ Docker Hubにログインしている前提です。
$ docker build -t [イメージ名(:タグ名)] [Dockerfileのあるディレクトリ]
$ docker push [イメージ名(:タグ名)]
Step 2. VSCodeで執筆
Step 2-1. 拡張機能をインストール
VSCodeの拡張機能であるRemote Development Extension Pack
をインストールすると、VSCodeの機能をそのままにDocker内でコードを書くことができます。
Step 2-2. コンテナの設定
Step 2-2-1. 利用するイメージを記述したDockerfileを準備
作業するディレクトリ直下に以下のようなDockerfileを用意してください。
# Step 1-4で作成したイメージの名前とタグ名
FROM イメージ名:タグ名
ビルドしていない場合は、上記のDockerfileの代わりにStep 1で作成したDockerfileをコピーしてください。
ただし、コンテナに入るたびにビルドが走るため時間がかかります。
Step 2-2-2. コンテナに入る
VSCodeで Ctrl + Shift + p なりでコマンドパレットを起動して、Remote-Conteiners: Open Folder in Container...
を実行すると、ディレクトリ直下のDockerfileを自動でビルドしてコンテナに入ることができます。
Step 2-2-3. コンテナ内で適用する設定
.devcontainer
ディレクトリ直下にdevcontainer.json
を配置することでコンテナ内でのみ適用される設定を記述できます。
くわしくはこちらにあるので参考にしてください。
編集する項目は以下の通りです。
{
...
"dockerFile": "./DockerFile",
...
"setting": {
...
"latex-workshop.latex.recipes": [
{
"name": "llmk",
"command": "llmk"
},
{
"name": "clean",
"command": "llmk",
"args": [ "--clean" ]
},
{
"name": "clobber",
"command": "llmk",
"args": [ "--clobber" ]
}
],
"latex-workshop.latex.recipes": [
{
"name": "llmk",
"tools": [ "llmk", "claen" ]
},
{
"name": "clean",
"tools": [ "llmk", "clobber" ]
}
],
"latex-workshop.view.pds.viewer": "tab",
"editor.renderControlCharacters": true,
"window.zoomLevel": 0,
"latex-workshop.message.update.show": false
},
...
"extensions": ["james-yu.latex-workshop"]
Step 2-2-1で作成したDockerfileを.devcontainer
直下に移動させて、もう一度ビルドし直すと執筆環境が出来上がります。
Step 3. GitHub Actionsを設定
Step 1、Step 2だけでTeXの執筆環境・PDF生成の手順は揃いましたが、個人的にGitHub Actionsを使ってみたかったので、TeXファイルをGitHubにタグ付きでプッシュするとGitHubのreleaseページにアップする仕組みを作りました。
ワークフローを作成
.github/workflows
直下にmain.yml
を作成します。このYAMLファイルがワークフローを定義する設定ファイルです。
詳しい書き方は公式サイトや他の記事を参考にしてカスタマイズしてください。
完成したファイルはこちらにあります。
ファイル構成
.github
├── actions
│ └── release
│ ├── Dockerfile # 独自定義したアクションで使用するコンテナ
│ └── entrypoint.sh # コンテナ内で実行するスクリプト
└── workflows
└── main.yml # ワークフローを定義
Step 3-1. 公開イメージを利用する
Step 1-4で公開したDockerイメージを利用してPDFを生成するので、それをmain.yml
に記述します。
name: TeX2PDF
on: push
jobs:
create:
runs-on: ubuntu-latest
# ↓で利用するイメージを指定します
container: pyama0327/lualatex-haranoaji-llmk
steps:
# ↓を実行しないとファイルが取得できません
- uses: actions/checkout@v1
- name: Print hello
run: echo "Hello, world!"
上記ファイルをプッシュするとActionsが走って、Hello, world!
と出力されます。
Step 3-2. PDFファイルを生成
すでにTeXファイルからPDFファイルを生成する方法はイメージ内にあるので、TeXファイルとllmk.toml
をプッシュしてPDFを生成するコマンドを上記で作成したファイルに記述します。
steps:
- uses: actions/checkout@v1
# - name: Print hello
# run: echo "Hello, world!"
working-directory: ./texfiles
- name: Create PDF from TeX
run: llmk
- name: Set filename to $FILE_NAME
run: echo "::set-env name=FILE_NAME::`basename *.pdf .pdf`"
working-directory: ./texfiles
Create PDF from TeX
ステップではllmk.tomlファイルを読み込んでllmk
を実行しています。今回は、texfiles
ディレクトリ以下にllmk.tomlやTeXファイルがあるので、working-directoryで指定しています。
Set filename to $FILE_NAME
ステップは後ほど使うのですが、前のステップで作成したPDFファイルの拡張子を抜いたファイル名を環境変数にセットしています。
Step 3-3. PDFファイルをreleaseページにアップロード
main.yml
で実行するアクションを独自に定義できるので、この機能を利用してアップロードします。
jsonをjq
で処理したかったので、alpineにjq
をいれるDockerfileを作成しました。
FROM alpine:latest
RUN apk upgrade --update && \
apk add --no-cache jq curl
ADD entrypoint.sh /entrypoint.sh
RUN ["chmod", "+x", "/entrypoint.sh"]
ENTRYPOINT ["/entrypoint.sh"]
entrypoint.sh
はreleaseを作成し、PDFをアップロードするスクリプトです。
#!/bin/ash
set -eux
TAG_NAME=`echo ${GITHUB_REF:10}`
REQUEST=`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\": \"$FILE_NAME.pdf\",
\"draft\": false,
\"prerelease\": false
}"`
RELEASE_ID=`echo ${REQUEST} | jq ".id"`
curl -H "Authorization: token ${GITHUB_TOKEN}" \
-X POST https://uploads.github.com/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=${TAG_NAME}.pdf \
--header 'Content-Type: application/pdf' \
--upload-file texfiles/${FILE_NAME}.pdf
Upload the PDF to GitHub release
ステップを以下のように定義することで、上記のDockerfileをビルドし、entrypoint.shが実行されます。
steps:
...
- name: Upload the PDF to GitHub release
uses: ./.github/actions/release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Step 3-4. 実行される条件を変更する
ただしこのままでは、プッシュされたファイル全てに対してActionsが実行されるので、TeXファイルとllmk.tomlがプッシュされ、タグ付けされたものがプッシュされたら実行するように変更します。
...
on:
push:
paths:
- texfiles/**.tex
- texfiles/llmk.toml
tags:
- v*.*.*
...
これで、v*.*.*
とタグ付けされたコミットをプッシュすることでGitHub Actionsが実行されるようになり、releaseページにアップロードされます。
おわりに
つたない文章、かつコードが多いため分かりづらい部分が多いとは思いますが、更新してきれいにし着たいと思います。
また、それぞれのトピックの情報量が少ないため、いつか記事を分割して詳しくしていきたいです。
参考情報
Dockerfile
- TeX Live 2019 + 原ノ味フォント + llmk の Docker コンテナを作る - Qiita
- Paperist/docker-alpine-texlive-ja: Minimal TeX Live image for Japanese based on alpine
- y-yu/new-year-letter: 年賀状
llmk
Github Actions
- GitHub Actions で TeX のコンパイルと PDF 化をさせようとしたら意外に苦戦した話 - Qiita
- GitHub Actions で TeX をコンパイル・PDF 化してタグ付きリリースする話 - Qiita
- GitHub Actions で Latexmk&タグを使ってコンパイルする TeX ファイルを指定する話 - Qiita
- 新 GitHub Actions 入門 - 生産性向上ブログ
- GitHub Actionsの使い方 | 純規の暇人趣味ブログ