ぽよメモ

レガシーシステム考古学専攻

MAASでストレージレイアウトのカスタマイズを探求したがよくわからなかった話

MAASとは

maas.io

Metal as a Service の略で、Ubuntuの開発元であるCanonicalが開発している、オープンソースのベアメタルサーバ管理ソリューションです。
以下の様な機能を提供しています。

  • OSのインストール自動化
    • PXEブートして curtin + cloud-init でプロビジョニング
  • VLAN管理
  • DNSおよびDHCPの提供
  • 各種Bare Metal Controller(IPMI、HP iLOIntel AMTなど)との連携による電源管理*1
  • 物理マシンのインベントリ
  • KVM・LXDホストおよび仮想マシン管理

Web UIからこれらの一連の操作を行うことが出来ます。例えばAWSのWebコンソールのように、ボタンをぽちぽちしたりAPI経由で仮想マシンおよび物理マシンの構築がオンプレミスでもできるようになります。

環境

pudding@maas-master:~$ snap list | grep maas
maas      2.9.2-9165-g.c3e7848d1  12555  2.9/stable     canonical*  -
maas-cli  0.6.5                   13     latest/stable  canonical*  -

MAASのストレージレイアウトつらい問題

2021年6月現在の最新安定版である v2.9 では、デフォルトで以下のレイアウトがサポートされています*2

  • Flat layout
  • LVM layout
    • パーティションレイアウトはFlat layoutと同じ。ただし、LVMによる論理ボリューム(LV)管理ができるようになっている。
    • ボリュームグループの空き容量全てが単一のLVによって占有されており、レイアウトを変えるためにはunmountしてresize2fsしてlvresizeする必要があるが、ルートにマウントされているのでいじるのが大変。
  • bcache layout
    • HDDのような遅いデバイスSSDなどをキャッシュとして噛ませるモード。
    • SSDが搭載されていない場合は自動でFlat layoutにフォールバックされる。
  • VMFS6 layout
    • VMWare ESXiをデプロイする際に自動で選択されるモード。よく知らない。
  • Blank layout
    • 手動でのパーティションレイアウト作成が必要なモード。そのままではOSのインストールができない。

これ以外のレイアウトをUIから指定したい場合、MAASでCommissionしてそのマシンの構成情報を取得・UI上からデバイスパーティションレイアウト・ファイルシステム手動で編集するしかありません。

f:id:pudding_info:20210619153034p:plain
CommissionしてReadyになったらこのUIでストレージレイアウトを編集出来る

数台程度しかマシンがない一般的なご家庭ならまだしも、逸般的な誤家庭とか、企業のプロダクション環境のサーバは単一のディスクしかないシンプルな環境とはほど遠いはずです。デフォルトで用意されているストレージレイアウトはどう見ても機能不足で、一台ずつ手動設定というのはさすがに目も当てられません。

curtin

Ubuntuの有名さに対して、curtinは驚くほど知られていません。例えばQiitaで curtin を検索してみても、軽く読んだ限り明示的に利用しているのは以下の記事だけのようでした。

qiita.com

公式ドキュメントを見ても何ができて何を目指しているのか全然分からないというのが正直な感想でした。

curtin.readthedocs.io

curtinのconfigを抽出する

とにかく、MAASは内部的にはこのcurtinを利用してマシンのセットアップを行っています。以下のドキュメントで説明されています。

maas.io

MAASは選択したストレージレイアウトに従って動的にcurtinの設定を生成し、デプロイしているようです。一度手動でストレージのレイアウトを編集してデプロイし、MAAS CLIからその設定を抜き出すことで、独自のレイアウトを再利用することができます。

$ MAAS_USER=MAASのログインユーザ名
$ MAAS_URL=MAASのURL(例:http://localhost:5240/MAAS/)
# API KeyはWeb UIから入手可能
$ maas login ${MAAS_USER} ${MAAS_URL}
API key (leave empty for anonymous access):
# ホスト名と紐付けて目的のノードのsystem idを探す
$ maas ${MAAS_USER} machines read | jq -r '.[] | .hostname + ": " + .system_id'
maas-node1: xh4xrn
maas-node3: qbyswd
maas-node2: t3f4ba
# 今回はmaas-node1のcurtin configを適当なファイルに吐く
$ maas ${MAAS_USER} machine get-curtin-config xh4xrn > /tmp/curtin-config-lvm

重要なのは storage: から始まるセクションだけなので他は消してしまって良いです。以下の様なマシンでLVM layoutを選択した場合のストレージレイアウトです。

storage:
  config:
  - grub_device: true
    id: sda
    model: Virtual Disk
    name: sda
    ptable: gpt
    serial: 6002248094595034c40f053014e7387d
    type: disk
    wipe: superblock
  - device: sda
    flag: boot
    id: sda-part1
    name: sda-part1
    number: 1
    offset: 4194304B
    size: 536870912B
    type: partition
    uuid: 33524d54-d698-43e5-985e-cc68b470f720
    wipe: superblock
  - device: sda
    id: sda-part2
    name: sda-part2
    number: 2
    size: 68174217216B
    type: partition
    uuid: 9d681714-39ad-42e2-a555-84f52b9cb216
    wipe: superblock
  - devices:
    - sda-part2
    id: vgroot
    name: vgroot
    type: lvm_volgroup
    uuid: 280744d7-d041-40e2-98c8-4d4810d780f2
  - id: vgroot-lvroot
    name: lvroot
    size: 68170022912B
    type: lvm_partition
    volgroup: vgroot
  - fstype: fat32
    id: sda-part1_format
    label: efi
    type: format
    uuid: 4314dc3b-b93a-4d9f-a0f2-68c167f6bb03
    volume: sda-part1
  - fstype: ext4
    id: vgroot-lvroot_format
    label: root
    type: format
    uuid: d422bd61-cd28-473e-ad17-7e80fc51a241
    volume: vgroot-lvroot
  - device: vgroot-lvroot_format
    id: vgroot-lvroot_mount
    path: /
    type: mount
  - device: sda-part1_format
    id: sda-part1_mount
    path: /boot/efi
    type: mount
  version: 1

公式ドキュメントを読むとおおよその意味は分かります。

curtin.readthedocs.io

この設定でmaas-node1を固定するには以下の様にします(storageセクション以外は消しておくこと)*3

$ sudo cp /var/snap/maas/current/preseeds/curtin_userdata.sample /var/snap/maas/current/preseeds/curtin_userdata_ubuntu_amd64_generic_focal_maas-node1
$ cat /tmp/curtin-config-lvm | sudo tee -a /var/snap/maas/current/preseeds/curtin_userdata_ubuntu_amd64_generic_focal_maas-node1

抽出したconfigを流用する

現在の設定には2つつらみがあります。

  • uuidやserialが指定されている
  • ボリュームのサイズが指定されている

前者を解決するために、とりあえずそれらの値を全部削除します。type: partition および type: format についてはuuidが無くても動く*4ようですが、 type: disk では serial もしくは path の指定が必要なようです*5。よって以下の様にpathを指定します。

  storage:
    config:
    - grub_device: true
      id: sda
      model: Virtual Disk
      name: sda
      ptable: gpt
-     serial: 6002248094595034c40f053014e7387d
+     path: /dev/sda
      type: disk
      wipe: superblock

この設定はかなりハードウェアの変更に弱いです。全然良い方法とは思えませんが共通化するためにはこれくらいしか方法が無いように思われました。

後者は解決できませんでした。

https://curtin.readthedocs.io/en/latest/topics/storage.html#partition-command

Note Curtin does not adjust size values. If you specific a size that exceeds the capacity of a device then installation will fail.

このように書いてあり「残り全部」みたいな指定ができません。管理するマシンのストレージ容量の最低値を基準にすれば一応動くはず……*6

この設定を Ubuntu 20.04 かつ amd64 なマシンのセットアップに利用するためには、ノードごとの設定と同じようにファイルを配置します。

$ sudo cp /var/snap/maas/current/preseeds/curtin_userdata.sample /var/snap/maas/current/preseeds/curtin_userdata_ubuntu_amd64_generic_focal
$ cat /tmp/curtin-config-lvm | sudo tee -a /var/snap/maas/current/preseeds/curtin_userdata_ubuntu_amd64_generic_focal

ノードごとの設定が無い場合、デフォルトの設定を無視してこのストレージレイアウトが読まれます。

疑問点

さて、全ノードが全て同容量の単一ディスクしか持っていない場合はこれでもうまくいきそうです。しかし現実には、

  • 導入した世代によって容量が違う
  • 導入した世代によってはSATAではなくNVMe SSDを搭載している
  • ディスクが2本以上搭載されている

など様々なケースが考えられそうです。果たしてこれをプロダクション環境で利用している人たちはどうやっているんでしょうか……

ホストごとに設定を作ることは出来ますが、ホスト名のプレフィクスなどで読み込むconfigを変えるようなロジックは無さそう*7であり、

  • インストールするOSのバージョン・マシンのアーキテクチャの組ごとにマシンの構成の方を固定化してしまう
  • 全ホストで独自の設定ファイルを生成するようにする

のいずれかの対策をとらなければいけないように思われます。

まとめ

おうちでベアメタルクラウドをやる第一歩としてMAASでPoCしていたところ、ストレージ周りの工夫が必要なことが判明したため少し調べました。

現状では一度手動で設定し、その設定を流用することで以降独自のストレージレイアウトでプロビジョニングできそうです。ただしノードごとに構成が揃っていることが必要そうです。

これをプロダクション環境で使っている人たち、どうしているんですかおしえてください 🙏

参考


*1:いずれもそのマシンがサポートしていない場合、手動で電源をオンにしたりする必要があります

*2:maas.io

*3:https://maas.io/docs/snap/2.9/ui/custom-machine-setup#heading--template-naming

*4:そもそもpartitionのドキュメントには uuid の項目がありません。このパラメータがどう使われているのかは不明です。 https://curtin.readthedocs.io/en/latest/topics/storage.html#partition-command

*5:https://curtin.readthedocs.io/en/latest/topics/storage.html#disk-command

*6:使えない領域が出来ます

*7:https://github.com/maas/maas/blob/1aa6276c0b6d7d702f1ed3036fd11d30e879c285/src/maasserver/preseed.py#L614

これからコーヒー趣味を始める人に伝えたいこと3選

tl; dr

  • コーヒー器具の○杯用は小さいコーヒーカップ換算なのでマグカップで飲むなら信用するな
    • 余談:コーヒーサーバはオールガラスが洗いやすくておすすめ
  • 沸きたての熱湯でドリップするな、少し冷ませ
  • サーカスコーヒーはいいぞ

はじめに

この記事はコーヒーが趣味な筆者が偏見と経験だけを元に言いたいことを書いた物です。決して空いていたあくあたん工房アドベントカレンダー10日目の枠を埋めるためではありません*1

最近身の周りに家でコーヒーを家でドリップして飲む人が増えてきたような気がします。とても嬉しいので皆さんどんどん開拓して僕に色々教えて下さい。

この記事では始めたばかりの頃に引っかかりがち・やりがちのことについて軽く触れます。もちろん好みの部分もあるので、自分の手と舌と鼻を一番信用して下さい。なお、本記事で色んなものを紹介していますが、筆者にアフィリエイト収入等一切入りませんので安心して(?)ご覧下さい。

コーヒー器具の「○杯用」という表記

 僕は昔からこの表記が好きではないのですが、コーヒーをドリップするための器具にはどの程度の量をいれるのに良いか、という指標として「○杯用」などの表記が採用されています。大抵は1〜2杯用、もしくは3〜4杯用が一般的です。ところで、この「1杯」とは具体的に何mlに相当するんでしょうか?

www.ucc.co.jp

カップ一杯分(約140cc)

www.keycoffee.co.jp

1杯 120 ml

HARIOのドリッパーV60の説明書き https://www.hario.com/manual_pdf/VD.pdf

一杯分(120ml)

どうも120〜140mlくらいのようです。ここで我が家にあるコーヒーカップとマグカップを見てみましょう。

f:id:pudding_info:20201209162310j:plain
普通のコーヒーカップとこのすばマグカップ

高さは約半分というところです。口の広さは同じくらいですね。

f:id:pudding_info:20201209162530j:plain
コーヒーカップボーンチャイナで6年使っても綺麗

f:id:pudding_info:20201209174205j:plain
ソーサーもちゃんとついてるよ

小さく見えるコーヒーカップですが、僕は普段これに160~170ml入れて飲んでいます*2。既に120mlを大きく超えていますね……マグカップのときは230〜250mlくらい入れているため、だいたいマグカップ一杯が世に言う「2杯分」くらいに相当します。つまり、1~2杯分の器具だと実はマグカップ1杯分にしかならない可能性があり、来客対応などが難しくなる可能性があります。大は小を兼ねるということで、とりあえず3~4杯用のものを買っておくのが丸いと思います。

ところで1杯120mlという根拠はなんなんでしょうね……エスプレッソなどを飲むデミタスカップとしては120mlは多すぎますし、レギュラーコーヒーを飲む用としてはいささか量が少ない気がします。軽く調べてみてもコーヒーカップは満水時200mlくらい入るのが主流なように感じます。120mlだとかなり寂しい量になりそうですね。

余談:コーヒーサーバはオールガラス製が洗いやすい

コーヒーサーバとは、ドリッパーを使って抽出したコーヒーを一時的に入れておくポットです。Amazonなどで安いコーヒーサーバを探しているとだいたい以下の様な物がヒットすると思います。

www.amazon.co.jp

f:id:pudding_info:20201209171442p:plain
HARIO(ハリオ) V60レンジサーバー (上記サイトより引用)

とても安くて入手性も良く、持ち手が熱くならないなど良いこともあるんですが、とにかく洗いづらいし乾かしづらい
このプラスチックの部品とガラスの隙間に汚れや洗剤が溜まったり、そこだけ乾かなくてドリップしたときに温められた空気に押し出されて出てきたりします。

長年これが個人的に悩みで、しかしなかなか頑丈で壊れないので買い換えられずにいました。去年あるときついに割ってしまい、どうにかこのプラスチックの持ち手を避けようと色々探していたら各社それなりにオールガラス製のコーヒーサーバを出していることが分かりました。

僕が持っているのは以下のコーヒーサーバです*3 www.amazon.co.jp

f:id:pudding_info:20201209172638j:plain
撮影のためだけに引っ張り出してきた器具たち

オールガラス製で心配していたのは持ち手が折れてしまうとか熱くなってしまうとかですが、今のところ特にそういう問題は出ていません。たぶんこの持ち手が折れるようなときにはコーヒーサーバごと割れるので、持ち手がプラ製でも変わらんなというのが僕の感想です。とにかく洗いやすくなったし見た目もなんかオシャレなのでオススメです。

ドリップするときの温度

コーヒーの抽出というのは非常に難しく、かつ繊細な工程です。そしてドリップにおいて重要な要素の一つが湯温です。コーヒーのドリップ方法について調べると分かりますが、だいたい90℃!とか85℃!とかみんな言うことがバラバラで統一的な見解がありません。それは当たり前で、個人の好みや抽出器具、豆、煎り具合など多数の要素があるうちの一つの要素に過ぎないため、他の要素との兼ね合いで変わるためです。

一般に湯温が高ければ苦みが強い味になります。それに加えてえぐみや渋みの様な味も強くなります*4。多少まともな豆を買ってコーヒーを抽出する際にあまりに高い湯温にしてしまうと強い苦みや渋みが出てしまい、あれ?なんか安豆と変わらないのでは……?となりがちです。

T-falなどに代表される湯沸かし器を使ってお湯を沸かし、それを使ってドリップしている人が多いのではないでしょうか。最近は温度調節機能がついたものもありますが、多くの場合は沸騰させる機能しか無いはずです。この場合、完全に沸いたお湯をすぐ使うと100℃近いため、前述したように余計な成分を抽出してしまい本来ある豊かな香りやコクを損ないやすいです。

ドリップポットで少し冷ます

ドリップポットとかドリップケトルとかそういう呼び方をする道具があります。

f:id:pudding_info:20201209185052j:plain
以前バイト先で使っていた小さいドリップポット

これにはドリップ時にお湯を注ぎやすくするだけで無く、湯温を適度に下げるという役割もあります。あと見た目がオシャレになってなんかカッコイイ。

キッチン用の温度計が1000円台で買えるので、

  1. 電気ケトルからドリップポットに注ぐ
  2. 適当に85℃くらいに調整してドリップ
  3. 苦みが濃い→次回から温度を少し下げる
    苦みが薄い→次回から温度を少し上げる

こんな感じで良い具合の所を探ってみて下さい。

どこで豆を買うか

f:id:pudding_info:20201210204733j:plain
自分でドリップしながら撮影するのが難しすぎて諦めた写真

コーヒー豆はいろんなところで売っています。スーパーなどで売られるとてもリーズナブルな豆から、スターバックスやカルディなどのようなちょっとお洒落な雰囲気を漂わせた豆、専門店のお高い豆まで幅が広いです。

個人的にはやはり専門店に行って、その香りに触れて選んで欲しいなと思いますが、そうは言っても世間は大コロナ時代。やはり家から頼めるオンラインショップで済ませたいところ……。

というわけで筆者のおすすめコーヒー豆ショップを紹介します。

circuscoffee.shop-pro.jp

銀行振り込みしかありませんし、送料もかかりますが、一度は試して欲しいと思っています。初めて注文する方は以下の送料お得セットで少量試してみるのはいかがでしょうか。

circuscoffee.shop-pro.jp

挽いてもらわず豆のままであれば、ジップロックなどで密閉して冷凍庫で3週間〜4週間くらいもちます。ミルで挽くときに解凍なども不要です。是非お試しあれ。

まとめ

アドベントカレンダーの穴埋め筆者の丁寧なくらしの紹介いかがでしたでしょうか。 コロナで心がすさみがちな日々、コーヒーでほっと一息つくのは良い物ですよ。

明日のあくあたん工房アドベントカレンダーもご期待ください。


*1:執筆時点でまだ18日目が空いており、このままではまたよく分からない記事を捻出することになるので誰か書いて下さい

*2:おそらく満水時に200ml入る設計になっています。

*3:3〜4杯用を買えと言っておきながらこれは300mlしか入らないんですが、これは僕が普段はネルドリップ用のポットを使っていて、こっちは一人用をエアロプレスでいれるためにしか使っていないためです。

*4:この辺りは豆にもよるので一般論として受け取って下さい

日本語論文をLaTeXで書いてtextlintで校正するテンプレートを作った

はじめに

 この記事の対象者は主に修論・卒論を書く人です。英語論文についてはとくに言及しません。

 初めて論文を書くことはとても大変です。しかし、そのひどい初々しい論文を校正する人はもっと大変です。しかも大抵の学生はいっぱい書いてから見て下さい!とお願いしてきます。もはや何から手を付けて良いかすらわからない……。こんなひどい状況を打破するべく、体裁の指摘を自動でやってくれて、内容の指摘に集中できるようになるテンプレートを用意しました!
 これは実は原型のほとんどが実際にM2の時に研究室内で使っていた物なのですが、

  • 去年は忙しくて公開できるような形に持っていく余裕が無かった
  • でもこのまま忘れてしまうには惜しい
  • ↑を作る上で利用させていただいたOSSのメンテナになったので宣伝したくなった

という事情で今年公開することにしました。Pull Requestお待ちしています。

github.com

テンプレートの使い方

リポジトリをフォークする、又は以下の画像にあるUse this templateというボタンをクリックしてください。

f:id:pudding_info:20201205021153p:plain
Use this templateボタン

Creative Commons Zero(CC0)*1で公開していますので、著作者表記などに配慮することなく自由にご利用頂けます。

テンプレートの特徴

LaTeX on Docker

 Word論文はリジェクト!とまでは言いませんが、こうした自動化の恩恵を受けやすいのは単純なテキストで書けるLaTeXです。分からない人は覚えて下さい。
 昔はLaTeXの環境構築は大変だと言われていました(要出典)。今もこだわると大変ですが、どうしてもヒラギノを使わないと死んでしまう人以外はDockerで構築するのが良いでしょう。WindowsでもMacでもLinuxでも安定した結果を得られます。

 僕は以下のリポジトリで管理し、tagを付ける度にDockerhubでビルドするようにしています。このテンプレートではこのイメージを利用していますが、任意のイメージに差し替えることも出来ます。

github.com

https://hub.docker.com/r/pddg/latex

Makefile

 どんなコマンドを打つか思い出すのが面倒なので、このテンプレートではmakeを使います。Windowsではscoopを使ってmakeをインストールする他、開発環境をWSLに持ってしまうなどがおすすめです。

 make すればpdfができて、 make clean すれば中間ファイル含めて全て削除される、そういうシンプルな世界がオススメです。ちなみにGNU Makeの使い方を解説した僕の資料もあるので、是非使ってみてください。

Git管理

 今は2019年なのでGitで管理してGitHubにpushするのは、もはや特殊でも何でもありません。
 現在はGitHub Actionsという超便利なものがあります。これを使って、このテンプレートでは以下の様なワークフローを組みます。textlintやreviewdogについては後述します。

f:id:pudding_info:20201122223159p:plain
論文執筆のワークフロー

VSCode対応

 Visual Studio CodeMacWindowsLinuxのいずれでもよく使われており、非常に便利なエディタです。加えて、最近はDockerやWSLなどとの連携も強化されており、ポータブルな開発環境の構築が簡単になってきました。VSCodeLaTeX用拡張であるLaTeX WorkshopはビルドをDockerコンテナ内で実行することに対応しており、以下の様な環境をすぐに構築出来ます。

f:id:pudding_info:20201204235728g:plain
VSCodeで編集するときの様子

 PDFからソースへ、逆にソースからPDFの該当箇所へジャンプできます。また、保存時に自動ビルドが走ります。

 Dockerがインストール済みのホストにVSCodeをインストールして、必要なエクステンションを入れれば上の画像のような環境が完成するようになっています。

まとめ

 まずこのテンプレートによって2つの問題が解決します。

  • 環境構築が難しい
    • DockerとVSCodeが使用可能であればすぐにPDFを生成できる
  • 使い方が難しい
    • 最低限 make を覚えていればPDFが生成できる

書き始めるまでに脱落する人をできるだけ救えることができれば幸いです。

 実はもう一つ、タイトルにもある重要な特徴があるので次で紹介します。

textlintで校正する

 論文では全体の体裁を意識して記述する必要があります。基本的に表記揺れや「ですます調」「である調」の混じった文などは許されません。しかし、これらを人間が意識して校正するのは多大な労力を必要とします。そこでこれらについてある程度ツールで指摘出来るようにします。これを実現するのがtextlintです。

github.com

環境構築

 このような校正自体をローカルで実行する必要はないかなと思っています。PushしたときにCIでちゃんと警告されればそれでいいかなと。

 一応Node製のツールなので、LaTeXより楽に環境を整えることができます。単にNode JSをインストールしてnpm installすれば環境構築は完了です。

textlint-plugin-latex2e

 textlintは内部的に文章をASTへ変換して使用します。デフォルトではLaTeXファイルを読み込めないため、このプラグインを利用します。

github.com

昨年メンテナとして加えて頂き、サードパーティー製のLaTeXパーサへの移行のお手伝いをしました。
 textlintのASTとLaTeXパーサが解析したASTをすり合わせる、というような細かい作業をしており、おそらく潜在的なバグがあります。もしうまく動かないときは積極的にissueを上げて頂ければと思います*2

Rule

 textlintで警告を出すために様々なルールを追加していきます。
とは言ってもtextlint-rule-preset-japaneseまたはtextlint-rule-preset-ja-technical-writingをインストールすれば終了です。これはいくつかのルールをまとめたもので、個別のルールに対して設定を書くことも出来ます。全部書くと多すぎるので、言及の必要があるものだけ書きます。

github.com

github.com

これらは様々なルールを一括で導入できて便利な反面、この部分ではこのルールを無視したいと思ったとき、(後述するtextlint-filter-rule-commentsを利用すると)毎回% textlint-disable ja-technical-writing/ルール名として記述する必要があり、ちょっと面倒です。不要なルールがあったり、各ルールの最新版が常に反映されているわけではないなど、自分でルールを管理した方が全体を把握でき便利な場合もあります。とりあえず上記プリセットを突っ込んで使ってみて、不満があるなら自分で再構築するのが良いかと思います。

 各ルールの設定は、上記プリセットを導入している場合と、そこに含まれるルールを個別に導入した場合で書き方が異なります。

導入しているとき

{
    "rules": {
        "preset-ja-technical-writing": {
            "ルール名": {
                "設定名": ""
            }
        }
    }
}

導入していないとき

{
    "rules": {
        "ルール名": {
            "設定名": ""
        }
    }
}

textlint-rule-sentence-length

https://github.com/textlint-rule/textlint-rule-sentence-length

一文当たりの単語数ではなく文字数に制限をかけます。英語の文章を含む場合、ignoreする必要があるかもしれません。

textlint-rule-no-mix-dearu-desumasu

https://github.com/textlint-ja/textlint-rule-no-mix-dearu-desumasu

 である、ですます調を統一します。指定しない場合、全体から見て多い方が優先されるので、論文ではである調に統一します。

{
    "rules": {
        "no-mix-dearu-desumasu": {
             "preferInHeader": "である",
             "preferInBody": "である",
             "preferInList": "である",
             // 文末以外でも、敬体(ですます調)と常体(である調)を厳しくチェックするかどうか
             "strict": true
         }
    }
}

textlint-rule-ja-no-mixed-period

https://github.com/textlint-ja/textlint-rule-ja-no-mixed-period

 「。」と「。」のミスはprh(後述)で修正するため、こちらはどちらかというとそもそも文末のピリオド抜けを検知するために使います。

{
    "rules": {
        "ja-no-mixed-period": {
             "periodMark": "",
             "allowPeriodMarks": [],
             "allowEmojiAtEnd": false,
             // --fix時に直すかどうか
             "forceAppendPeriod": true
        }
    }
}

textlint-rule-no-doubled-joshi

https://github.com/textlint-ja/textlint-rule-no-doubled-joshi

 連続して同じ助詞を使用しないようにします。「AにBにします」みたいな文章に対してエラーを出します。当初全角カンマをうまく取り扱えず誤検知が起きていたため、要望を出して改善して頂きました*3。バージョン3.7.0以降を推奨します。

{
    "rules": {
        "no-doubled-joshi": {
            "min_interval" : 1,
            "strict": false,
            "allow": ["",""],
            "separatorCharacters": [
                ".", "", "", ""
            ],
            "commaCharacters": [
                "", ""
            ]
        }
    }
}

textlint-rule-prh

https://github.com/textlint-rule/textlint-rule-prh

 表記揺れを修正するためのルールです。「.」と「。」、「サーバ」と「サーバー」など、間違えやすい語句を検知して修正します。

{
    "rules": {
        "prh": {
            "rulePaths" :["prh.yml"]
        }
    }
}

表記揺れの一覧とその修正はprh.ymlとして別ファイルに書き込みます。

version: 1
rules:
  # Githubやgithubを修正する
  - expected: GitHub
  # ピリオドとカンマを修正
  - expected:pattern: /[。。]/g
  - expected:pattern: /[、、]/g

LaTeXではリンクがリンクとしてパースされない(単なる文字列として処理される)ため、リンクを含む場所ではignoreする必要があるかもしれません。必要な表現をどんどん足していくことで、表記揺れを自動で検知できるようになります。

Filter

 設定したルールに対して例外を設けることが出来ます。

textlint-filter-rule-whitelist

https://github.com/textlint/textlint-filter-rule-whitelist

 例えばprhでGitHubの誤字を修正したい場合、リンクまで検知してしまうという問題がありましたが、ここでホワイトリスト製で例外を管理できます。他のルールで引っかかった語もこれで排除することが出来ます。

{
    "filters": {
        "whitelist": {
            "allow": [
                "github.com"
            ]
        }
    }
}

textlint-filter-rule-comments

https://github.com/textlint/textlint-filter-rule-comments

 一部だけlintをオフにしたい場合に使えます。

{
    "filters": {
        "comments": {
            "enablingComment": "textlint-enable",
            "disablingComment": "textlint-disable"
        }
    }
}

例えば英文では文字数制限を解除したい場合、以下の様に書きます。

% textlint-disable sentence-length

\section{英語}
    hoge hoge fuga fuga

% textlint-enable sentence-length

\section {日本語}
    ほげほげふがふが

ルール名を指定しない場合、全てのルールを無視します。ルールはカンマ区切りで複数指定することが出来ます。

GitHub ActionsでCI/CD

 textlintしてreviewdogを走らせ、masterにマージしたら自動でPDFをビルド、タグを打つとそれをリリースします。プライベートリポジトリでは

  • Freeアカウント:2000分/月
  • Proアカウント:3000分/月

のビルド時間が無料枠になります*4GitHub Student Developer Packに登録することでPro相当の恩恵を得られるので、大学のメールアドレスを持っている人は登録しましょう*5。また、大学や研究室単位でTeamやOrganizationを使用している場合、上記に当てはまらない可能性があるため、そのOwnerに確認しましょう。

 Travis CIやCircle CIを使う場合と比べて、トークン等を自分で取得・指定する必要がなく楽です。テンプレートにはすでにGitHub Actionsのworkflowが組み込まれており、特に設定することなく自動で実行されます。

Lint

 LaTeXのコードを静的解析し、ルールに違反する文章を検出します。このテンプレートではPull Requestを発行/更新するとこのワークフローがトリガーされるようになっています。このワークフローの実行にはおよそ30~40秒かかります。詳細は .github/workflows/lint.yaml を見てみて下さい。
 違反した文章を修正しやすくするよう、reviewdogからコメントをもらえるようにしています。更新は全てPull Requestを経由することで、masterブランチは常にビルド可能かつルールに違反していない文章のみが存在するようになります。

↓修正箇所をこんな感じで指摘してくれます。

f:id:pudding_info:20191208002634p:plain
reviewdogによるレビュー

Build

 masterブランチへのpushでビルドを実行し、その成果物をアップロードしてダウンロード出来るようにします。1分~1分半程度かかります。

f:id:pudding_info:20191208003135p:plain
ビルドしたPDFのダウンロード

 この成果物はデフォルトでは90日間有効なようです*6。それ以上の期間更新したい場合、次章のようにタグを付けて自動リリースしましょう。

Release

 タグを付けたらGitHub Releasesに新しいリリースを作ってPDFをアップロードします。1分~1分半程度かかります。

f:id:pudding_info:20191208003250p:plain
GitHub ReleasesからPDFをダウンロード

 こちらはファイルの保持期限が特にないため、第一稿、第二稿、完成などのような段階ごとにタグを打っておくと分かりやすくて良いでしょう。

注意点

 インライン数式に$を使用すると大幅なパフォーマンス劣化を生じます。インライン数式は \( x^2 \) のように記述することでパフォーマンス劣化を避け高速にlintを実行できます*7
 $ によるインライン数式が多数利用されたTeXソースに対するlintは全く終わらなくなってしまいます。そのため、同梱しているGitHub Actionsのワークフローではタイムアウトを10分に設定しており、これを超えると強制的にワークフローが終了します。これによりGitHub Actionsの無料ビルド時間を食い潰さないようになっていますので、もしタイムアウトしたらインライン数式によるパフォーマンス劣化を疑ってみて下さい。

原因を特定したので近く修正版を出します。これにより、インライン数式によるパフォーマンス劣化は起きない見込みです。

[追記 2020/12/7] こちらの問題を修正したv1.0.3がリリースされました。こちらのテンプレートもそれに合わせてバージョンアップしv1.0.0をリリースしました。

まとめ

 LaTeXソースを静的解析するtextlintのプラグインを利用することで、校正作業の一部を自動化する方法を示し、そのテンプレートを紹介しました。体裁は自動で指摘し、内容を人が集中してレビューすることでレビュアーの負荷を少しでも下げることができれば幸いです。
 私自身はアカデミアから遠く離れてしまい、既に論文を書く身ではなくなっていますが、textlint-plugin-latex2eへのコントリビュートは続けていきますのでissueやPRお待ちしています。


*1:creativecommons.jp

*2:ただしメンテナーはサポート担当ではないので、それを誤解されませんよう…

*3:https://github.com/textlint-ja/textlint-rule-no-doubled-joshi/issues/26

*4:他のプライベートリポジトリと共有であることに注意が必要です。

*5:https://help.github.com/ja/github/teaching-and-learning-with-github-education/applying-for-a-student-developer-pack

*6:docs.github.com

*7:これを書きながらインライン数式が(textlint-plugin-latex2eの不具合により)ASTを破壊している気がしてきたのでたぶん直します