バレンタインなのでLatex卒論ビルドサーバーを作った

2/14、バレンタインなのに卒論執筆に追われている現状に嫌気が刺したので卒論執筆を効率化するためにLatex卒論ビルドサーバーを建てました。

現状の卒論執筆環境における問題点

現在Linux上でLatexを用いてgit管理下の卒論を作ってるわけですが以下のような問題点がありました。

  • Latexをビルドするのがめんどくさい
  • ビルドするのとgit pushするのが別コマンドなのがめんどくさい
  • Latexの環境構築がめんどくさくて別マシンで卒論が書けない
  • 生成したPDFを教授、准教、共同研究先にそれぞれ添付してメールを送るのがめんどくさい
  • どこを編集したのかメールに書くのがめんどい

提案手法

先に述べた現状の卒論執筆環境の問題点は、卒論をpushするだけで自動ビルドしてメールを送ってくれるようなサーバーがあれば解決します。

そこでbitbucketのwebhookを用いて、リモートリポジトリへのpushを検知したらビルドサーバーへgetリクエスト->ビルドサーバーで変更をpull->Latexビルド->メール送信

を行うサーバーを作りたいと思います。

Webhook

webhookとはgithubやbitbucketにある、git pushされたときに特定のサーバーへhttp getリクエストを送ることができる仕組みです。

bitbucketの場合、リポジトリのSettingsからWebhookの設定ができます。

今回は卒論リポジトリにpushされたら、ビルドサーバー上のphpファイルにgetリクエストを行うことにしました。

ビルドサーバーの構築

ビルドサーバーはUbuntu 15.10をMicrosoft Azure上に構築しました。

こちらの記事を参考に、tex-liveをインストールし、platexコマンドの打てる状態にします。

Latexはplatex -> divpdfmxという流れでコマンドをうつことで.tex -> dvi -> pdfにできるのでそのようなシェルスクリプトを書きます。(ローカルでも使えるようにpオプションでpdfプレビュー)

これで./latexcompile.shで.texファイルをpdfにすることができるようになりました。

git pullできるようにする

webhookでビルドサーバー上のphpをキックするわけですが、php上でexecでgit pullするとき、gitのsshパーミッションやファイル書き込みパーミッションでかなり苦労しました。

phpからのexecで実行されたコマンドは、apacheユーザー(ubuntuではwww-data)の権限で実行されます。

そのため、正しくファイルパーミッションなどを設定していないとすぐにこけてしまいます。

リモートリポジトリへのアクセスはsshで行うのですが、www-dataユーザーは/var/www/.ssh/id_rsaの秘密鍵を使うことになります。

なのでまずはssh-keygenで/var/www/.ssh/にssh鍵を作成

この時パスフレーズの設定は何も入力せずにEnterを押します。

パスフレーズなしの秘密鍵はなかなか危険な感じがしますがパスフレーズを入力するプロンプトをwebhookから突破できないので仕方なく。ssh-agentとか使うといけるらしいけどめんどくさ(ry

作成できたら、/etc/ssh/ssh_configにホストがbitbucket.orgのときは/var/www/.ssh/id_rsaを使うように設定を書き込みます。

あとは/var/www/.ssh/id_rsa.pubをbitbucketのssh keyに登録すればgit cloneができるはずです。

git cloneしたら、www-dataと自身のユーザーが所属するwebhookグループを作ります。

 

そして、cloneしたリポジトリ全体に対して所有権をwebhookグループにし、グループに対し書き込み権限を与えます。

これでgit pullができるようになるはずです。

キックするphpファイルを作る

apacheで公開したディレクトリ(ブラウザーからアクセスできるディレクトリ)にキック用のphpファイルを作ります。

phpファイル内ではまず、execを使ってgit fetchを行ってリモートリポジトリの変更情報を取得します。

次にexecでgit logを行い、追加されたコミットを取得します。

このようなコマンドを実行することでローカルのmasterブランチとリモートのmasterブランチ間のlogを指定のフォーマットで出力できます。

logを取得したらgit pullします。

pullしたらリポジトリに移動し、先ほど作ったビルド用スクリプト(latexcompile.sh)を走らせて.texからpdfを生成します。

Slackに通知する

ビルドが失敗した場合はビルドエラーを、ビルドが成功した場合はpdfとdiffを、slackで通知します。

slackで通知を行うには、IncomingWebhookというものを使うと特定のURLにpostを行うだけでslackに通知できるのでphpからでも通知をおくれます。

こちらのサイトを参考に、phpからexecでcurlを実行し、slackに通知させました。

ビルドに失敗したとき

エラーログをテキストとして出してくれます。

ビルドに成功したとき

PDFと差分diffを出力したURLを送ってくれます。

メールを送信する

メールはmailutilsをインストールし、phpのexecでmailコマンドを叩きます。

こんな感じでメールを送れます。

変更差分もgit diffの出力をそのまま送るため、教授も思わずニッコリです。

今後の課題

  • PDFをAzure Storageへアップロード
  • diffが衝撃的なぐらい見づらい
  • slackに通知がくるまでにタイムラグがある
  • releaseブランチにpushしたときのみ教授にメール
  • メールの文章を(バレないように)それっぽく自動生成

ユーザー評価

今回の卒論ビルドサーバーを教授に説明したところ

「早く卒論を書いてください」

とのことでした。