LoginSignup
10
8

More than 3 years have passed since last update.

VSCodeでTeXファイルを編集してGitHub Actionsでコンパイル

Last updated at Posted at 2020-01-08

はじめに

去年の年末から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-langjapanesecollection-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内でコードを書くことができます。
Screenshot 2020-01-08 at 00.36.21.png

Step 2-2. コンテナの設定

Step 2-2-1. 利用するイメージを記述したDockerfileを準備

作業するディレクトリ直下に以下のような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 を配置することでコンテナ内でのみ適用される設定を記述できます。
くわしくはこちらにあるので参考にしてください。

編集する項目は以下の通りです。

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 1Step 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に記述します。

.github/workflows/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を生成するコマンドを上記で作成したファイルに記述します。

.github/workflows/main.yml
    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を作成しました。

.github/actions/release/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をアップロードするスクリプトです。

.github/actions/release/entrypoint.sh
#!/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が実行されます。

.github/workflows/main.yml
    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がプッシュされ、タグ付けされたものがプッシュされたら実行するように変更します。

.github/workflows/main.yml
...
on:
  push:
    paths:
    - texfiles/**.tex
    - texfiles/llmk.toml
    tags:
      - v*.*.*
...

これで、v*.*.*とタグ付けされたコミットをプッシュすることでGitHub Actionsが実行されるようになり、releaseページにアップロードされます。

おわりに

つたない文章、かつコードが多いため分かりづらい部分が多いとは思いますが、更新してきれいにし着たいと思います。
また、それぞれのトピックの情報量が少ないため、いつか記事を分割して詳しくしていきたいです。

参考情報

Dockerfile

llmk

Github Actions

その他

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8