gopkg.in/yaml のアーカイブと乗換先やメンテナンス継承議論
この話は、goccy/go-yaml 作者のgoccyさんと、YAMLの話を…止めない!という私のポッドキャストエピソードでも話した内容だが、口頭では説明が難しかったり、上手くまとまってなかった部分もあったので、補足的にエントリーを書いた。ポッドキャストでは裏話的な話やgoccyさんの生の意見も聞けるので、そちらも是非聞いてみて欲しい。
GoのYAMLライブラリとそのアーカイブ事件
GoのメジャーなYAMLライブラリには大きく以下の2つがある。
- gopkg.in/yaml.v3 (
gopkg.in/yaml
) 7k stars- github.com/go-yaml/yaml が開発リポジトリ
- github.com/goccy/go-yaml (goccy/go-yaml) 1.7k stars
他にもYAMLライブラリはいくつかあるが、実態は、gopkg.in/yaml のラッパーであることがほとんどだ。例えば、github.com/ghodss/yamlや sigs.k8s.io/yaml等。
gopkg.in/yaml
は k8sやdocker compose内部でも使われている世界的に標準的なライブラリで、我々ソフトウェアエンジニアを支えている重要なライブラリと言える。そして、その開発リポジトリが正式にメンテナンスを停止し、アーカイブされるという事件があり、乗り換え先選定やメンテナンス継承等に関わる色々な動きが起きている。
アーカイブの影響
直ちに問題はなく、大事になっていない。ライブラリとしては利用可能なままだし、そもそも、gopkg.in/yaml
のメンテナンスは実質的に大分前から止まっていたようなものなので、状況が大きく変わったわけではない、という見方もある。
ラッパーライブラリが多く存在するのもそのためだ。足りない機能やGoらしくないインターフェースをラップするために、ラッパーライブラリ経由で gopkg.in/yaml
を操作する使い方がされている。YAMLの仕様は余りにも膨大であるため、イチからライブラリを実装するのは多くにとって現実的ではないという話もある。
とは言え、アーカイブされたライブラリに依存するのは長期的には不安定なので、乗り換え先を選定するか、既存のソースのメンテナンス継承を検討する必要がある。
そこで、有力な乗り換え先として注目されているのが goccy/go-yaml
である。
2つのYAMLライブラリの比較
私は元々、goccy/go-yaml
を好んで使っていた。そっちの方が使いやすく、品質も高いと考えていたからだ。作者のgoccy(五嶋)さんに対する信頼度が高いことも後押ししている。
2つのライブラリの簡単な比較は以下。
gopkg.in/yaml
- 古く(2011年)からあるGoのYAMLライブラリ
- 世界的に広く使われている
- Cで書かれたlibyamlをGoに移植したような作りになっている
- 移植なので、libyaml実装に引っ張られた作りになっている
- 変数名や内部のインターフェースなど
- libyaml自体が歴史があるプロジェクトなのでソースコードの統一感に欠ける部分も
- 古く(2011年)からあるGoのYAMLライブラリ
goccy/go-yaml
- 後発(2019年)のYAMLライブラリ
- YAMLの仕様を元に、Go向けにスクラッチで実装されたライブラリ
- Goらしいコード・インターフェースで書かれている
- ライブラリ利用者からしたインターフェースも自然で使いやすい
- 若いプロジェクトであることもあり、メンテナンスの統制が取れており、ソースコードの統一感が高い
- YAML Test Suiteのスコアも、
gopkg.in/yaml
よりも高い
実装をもとに作られたgopkg.in/yaml
と、仕様をもとに作られたgoccy/go-yaml
とアプローチが異なるのが面白い。開発の世界では良くある話でもある。
個人的には、goccy/go-yaml
への乗り換えが進んでいくのだろうと思っていた。gopkg.in/yaml
はそもそもメンテナンスに困っており、引継先なども模索した上で、それが難しいと判断してアーカイブされたのだろうから、今後引き取り手が現れる可能性も低いと思っていた。
ただ、goccy/go-yaml
も個人プロジェクトではあるし、gopkg.in/yaml
とのインターフェースの差異もあるため、乗り換えコストを払うことが見合うかどうかは様子見されている雰囲気も感じる。
そして、ここで、(あまり注目されていないが)大きな動きがある。YAML本家による、gopkg.in/yaml
のメンテナンス継承である。
YAML本家によるメンテナンス継承
YAMLオーガニゼーション はYAMLの総本山であり、YAMLの仕様に加えて、LibYAMLやPyYAMLの実装、YAMLテストスイートなども公開・開発・管理している。YAML自体がPerl出自の技術であることもあってか、Perl6の実装も公開しているのも面白い。そこが、gopkg.in/yaml
のメンテナンスを引継を計画して進めている。そのリポジトリが以下だ。
- https://github.com/yaml/go-yaml (まだ46 stars)
go.yaml.in/yaml
というライブラリ名で公開するようだ
(ちなみに、元々の gopkg.in/yaml
のリポジトリはgithub.com/go-yaml/yamlなので、仕方がないのだが、紛らわしく、説明に苦労する。)
これは、客観的に見たら悪くない話ではあるだろう。メンテナンスに困ったOSSの受け皿として、このようなオープンな団体が手を挙げるのは良いことだ。ただ、リーダーシップ不在のまま引き取られたOSSが、結局放置される事例は多い。「墓場」の様な揶揄がされることもある。
gopkg.in/yaml
の保守性の悪さからメンテナンスに苦労していた現実もある。そういう「死にかけている」ライブラリに対して無理に延命措置を講じることが本当に良いことなのか、という話もある。gopkg.in/yaml
がその性質上、Goらしくないコードになっていることや、YAML本家のチームにGoのエキスパートがいなさそうなのも不安要素である。
この継承に関する議論は、CNCFのSlackの #go-yaml
チャンネルで行われており、誰でも閲覧可能だ。CNCF内で議論されているというのが面白い。
ただ、最近のCNCF Slackのプラン変更により、90日以上前のメッセージが閲覧できなくなるので見たい方はお早めに。該当チャンネルは、4/25作成のチャンネルなので、今ならまだ全部のログが読める。
goccyさんとYAML本家との対話
goccyさんも上のSlack上に投稿し、議論がなされている。YAMLの大本の作者である、Ingy döt Netさんが精力的に議論に参加していてアツい。
ここで、出てきた面白い観点としては、gopkg.in/yaml
はLibYAMLの移植であり、Goらしいコードになっていないことが彼らにとって寧ろ好ましいという点だ。
これは言われてみれば無理もない話だろう。彼らは、LibYAML, PyYAMLも同時にメンテナンスしているわけで、go-yamlも含めて、それらが似通った実装になっている方がメンテしやすいというのは道理だろう。Goに詳しい人がいないから尚更だ。
そして、もう一つの観点として、「仕様が正か。実装が正か」というソフトウェア開発で頻出の話がある。彼らは、YAMLの仕様も、汎用的で網羅的なテストスイートも公開しているので、元々は仕様を正にすることも考えていたのだと思う。ただ、実際はLibYAMLやPyYAMLの振るまいが事実上の標準仕様となっていることを受け入れ、その方針で進めているようだ。だから、尚更、gopkg.in/yaml
の実装がLibYAMLに近いことが好ましいという話になる。
実際、YAML仕様の記述には曖昧な点があり、テストスイート自体が正しいか、という話もある。
yaml-test-suite対応、『なぜこの結果になるのか』がいまいちわからない、かつ online yaml parser も go-yaml/yaml も異なる挙動をするケースがそれなりにあって、仕様を読みに行くんだけどそこにも書かれてなくて頭を抱えてる。最後はPerlの実装を読みに行くしかない…
— Masaaki Goshima (@goccy54) November 29, 2024
ちなみに、gopkg.in/yaml
のテストスイート網羅率は73%であり、goccy/go-yamlは88%である (2024年12月時点)。そもそも100%を目指す様な者でもなく、その必要性も疑わしいという話もある。
私は、YAMLのテストスイートが網羅されている実装は存在しないと認識していたが、実は2020年に、本家が全てのテストケースが通る参照実装を公開していた事を今回の議論の中で知った。そして、それを参考にテストスイートを網羅するライブラリも少ないながら出てきているとのことだ。
https://github.com/yaml/yaml-reference-parser
それと同時に、この参照実装は実用性に欠け、彼らがメンテナンスしているPyYAMLやLibYAMLも意図的に仕様から逸脱していて、テストスイートを網羅していないことも議論の中で明かしている。
現実問題としては仕方ないとも思うが、仕様から実装を進めていたgoccyさん的にはびっくりする話だっただろうが、その辺りの公式のスタンスが今回知れたのは良かったとは思う。
KubernetesのYAMLライブラリの移行
ちょうど本日、6月26日、Kubernetes本体から、gopkg.in/yaml
の依存がドロップされ、新しい go.yaml.in/yaml
(yaml/go-yaml
のライブラリ名) へ移行するpull requestがmasterに取り込まれた。
現実問題としては、インターフェースやコードベースが同一の後続ライブラリに移行するのは丸い選択肢だとは思う。この新しいyaml/go-yaml
はKubernetesが正式に採用することになり、CNCFも巻き込んで議論されているので、メンテナンス体制の不安もある程度払拭されたと言えるかも知れない。
私Songmu個人的には、引き続き、goccy/go-yaml
を使い、推していきます。
おまけ: yamlscript
今回の議論の中で、YAML作者のIngy氏は現在yamlscriptという恐ろしい名前のプロジェクトに積極的に取り組んでいることも分かった。YAML愛が凄い。Ingy氏についての話や、yamlscriptについては、冒頭にも書いた、YAMLの話を…止めない!というポッドキャストエピソードで話しているので是非聞いて欲しい。
また、今回のSlack上での議論については、その半公開の性質上引用は控えた(多分やっても問題ないとは思うが)。議論を見たい方は、Slackに参加して #go-yaml
チャンネルを覗いてみて欲しい。6/4~6/6辺りの議論なので、8月一杯くらいでアーカイブが消えてしまうのでお早めに。