Posted at

GitHubだけでLatexをコンパイルしてPDFをリリースにアップロードする


モチベーション

GitHubへのpushをトリガーとしてコンパイルやlintを行なって継続的にコードをデリバリーするCIが開発プロセスの重要な要素となってきました.普段からCircle CIやTravis CIをいじっている人が論文を書こうと思った時,新しいコミットに対して最新のPDFを自動で作ってくれたら嬉しいなと思うのは自然なことです.

本記事ではCircle CIなどの外部CI環境を使わずに,先日リリースされたGitHub Actionsを用いて,PDFのビルドからGitHub Releasesへのアップロードまでを全てGitHub上で行う方法について述べます.


前準備

本記事ではGitHub Actionsを用いてPDFのコンパイルを行います.

まだアクセスできない方は,こちらからサインアップしてアクセスできるようになるまで待ちましょう.


本題

GitHub Actionsではコマンドを全てDockerコンテナ上で実行します.

コマンドはDockerfileを用意することで任意のコマンドを自作することができます.

ここでは以下のディレクトリにファイルが配置されていると仮定します.

.

|-- .github
|-- actions
|-- latex
|-- Dockerfile
|-- entrypoint.sh
|-- main.workflow
|- main.tex

最初にLatexをコンパイルするためのDockerfileを書きます.

FROM ubuntu:16.04

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl \
python3 \
latexmk \
lmodern \
texlive \
texlive-latex-extra \
texlive-lang-japanese \
&& rm -rf /var/lib/apt/lists/*

RUN mktexlsr && mkdir -p /app
WORKDIR /app

ADD entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

GitHub Actions上で上のDockerfileをビルドしてもらうことでLatexのコンパイルとGitHub Releasesへのアップロードに必要なコマンドをインストールしたコンテナができます.

次にentrypointは以下のように実装しました.


entrypoint.sh

#!/bin/bash

set -eux

# build pdf (change if necessary)
pdflatex main.tex

# create release
res=`curl -H "Authorization: token $GITHUB_TOKEN" -X POST https://api.github.com/repos/[user]/[repo]/releases \
-d "
{
\"tag_name\": \"v$GITHUB_SHA\",
\"target_commitish\": \"$GITHUB_SHA\",
\"name\": \"v$GITHUB_SHA\",
\"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/[user]/[repo]/releases/${rel_id}/assets?name=main.pdf\
--header 'Content-Type: application/pdf'\
--upload-file main.pdf


[user][repo]の部分は自分のもので置き換えてください.GitHub Actions実行中ではいくつかの環境変数が自動で設定されます.GITHUB_TOKENはその1つで,GitHub Actionsが実行するたびに,その実行回のみ使用できるOAuthトークンが設定されます.

GitHub ReleasesのAPIについてはこちらをご覧ください.

最後にworkflowを定義します.


main.workflow

workflow "Build PDF" {

on = "push"
resolves = ["Build"]
}

action "Build" {
uses = "./.github/actions/latex"
secrets = ["GITHUB_TOKEN"]
}


下の方にあるsecrets = ["GITHUB_TOKEN"]がないと環境変数にトークンが設定されないので必須です.

完成したmain.workflowはGitHubのビューアーから見ると以下のような感じになります.


実行結果

以上のGitHub Actionsがセットされた状態でコミットがpushされると以下のようにGithub Releasesが作成され,PDFが添付されます.

リリースの作成者がgithub-actionsなのが面白いですね.


参考文献