Findy Engineer Lab

エンジニアの"ちょい先"を考えるメディア

試行錯誤と改善を続けたRubyリリースマネジメントの歴史。その歩みを歴代の担当者たちが振り返る

f:id:findy-lab:20201224113108j:plain

世界中のエンジニアから愛されるオブジェクト指向スクリプト言語Ruby。多くの人々がこの言語にコントリビューションし、その成長を支えてきました。なかでも、特定バージョンのリリースの責任を持つ“リリースマネージャー”の功績はとても大きいものです。彼らの存在があったからこそ、Rubyのリリースは滞りなく行われてきました。

しかし、リリースマネジメントの歴史はけして平坦な道のりではありませんでした。歴代の担当者たちが、適切な運用方法について試行錯誤しながら、少しずつ改善を続けてきたのです。その過程には、全てのエンジニアにとって参考になるプロジェクトマネジメントの知見が詰まっています。

今回は、歴代のRubyリリースマネージャーである卜部昌平さん(@shyouhei)、園田裕貴さん(@yugui)、遠藤侑介さん(@mametter)、成瀬ゆいさん(@nalsh)にインタビュー。これまで担ってきた役割について対談していただきました。Ruby言語仕様の歴史や開発体制の変遷など、Rubyist必見の内容が語られています。

  • … 取材はリモートにて実施しました。

バージョン1.8.5から創始したリリースマネージャーという役割

──まずは、みなさんがリリースマネジメントを担当されたRubyのバージョンや就任の経緯についてお話しください。卜部さんからお願いします。

卜部:私はRubyの1.8.5、1.8.6、1.8.7というバージョンでリリースマネージャーを務めていました。もともと、私が就任する以前はRubyの開発においてリリースマネージャーという役割は存在していませんでしたね。Rubyの創始者であるまつもと(ゆきひろ)さんが、リリースまわりの管理もしていました。

f:id:findy-lab:20201224113058j:plain
卜部昌平さん

──どのような経緯でRubyにリリースマネージャーが設けられたのでしょうか?

卜部:1.8.4以前のバージョンでは新機能の開発やバグフィックス修正のような、性質の異なるコード修正が混然一体となって同一のブランチ*に入っていました。

*…当時のバージョン管理システムはConcurrent Versions System(CVS)。

現在のように、目的の違うコード修正を別々のブランチで管理するという時代ではありませんでした。その運用には問題があり、例えば1.8.3と1.8.4ではリリースの直前に混入したコードが原因となって、特定のライブラリなどが動かなくなる不具合が立て続けに発生したんです。

f:id:findy-lab:20201224113133p:plain
1.8.3では、Ruby on RailsやtDiaryなどが動かなくなるなどのトラブルが発生した。画面キャプチャは http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-list/41199?41177-41576+split-mode-vertical より引用

また、当時のRubyにはリリースが定期的に行われないという課題もありました。とはいえ、それはRubyの開発プロジェクトが特別だったわけではなく、当時はオープンソースソフトウェア(以下、OSS)の開発において、定期的にリリースが行われるプロジェクトの方が少数派だったという時代背景はありましたけどね。こういった前提から、私や成瀬さんなどはRubyのリリースプロセスに対する課題意識を持っていました。

f:id:findy-lab:20201224113118p:plain
当時のメーリングリスト。卜部さんや成瀬さんなどが、リリースマネジメントについて強い課題意識を持ち、積極的に意見を述べるようになる。画面キャプチャは http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-dev/27919?27787-28605+split-mode-vertical より引用。

解決策についてメーリングリストなどで議論し合った結果として、リリースマネージャーを置くといいのではないかという話になり、当時このテーマについて強く意見を述べていた私がその役割を務めたという経緯です。

──卜部さんがリリースマネージャーになってから、新しく始まった取り組みはあるでしょうか?

卜部:パッチレベル*というバージョン体系番号を新しく導入しました。

*…1.8.6-p36を例に取ると、 1 : Major version 8 : Minor version 6 : Teeny version 36 : patch level バグフィックスのためにリリースが行われるたび、patch levelの数値が増えていく。

また、私がリリースマネージャーを務めるようになってから、特定バージョンのバグフィックスリリースを行なうためのブランチが作成・運用されるようになりました。

成瀬:こうしたブランチ管理の手法や、リリース前の一定期間は新機能を入れずバグ修正のみ行うといった方法論は、FreeBSDなど他のプロジェクトを参考にして取り入れたものです。リリースプロセス改善の運動を私や卜部さんが主導的に行い、その結果として徐々に仕組みが整備されてきたという流れですね。

──卜部さんがリリースマネージャーを担当された1.8.5、1.8.6、1.8.7というバージョンでは、どのような新機能が盛り込まれましたか?

卜部:細かな改善はありましたが、目立った新機能は何かというとパッとは思い出せないですね。Ruby1.8系における後半のバージョンですから、機能としてだいぶ成熟していたのだと思います。1.8系はちょうどRuby on Railsが出たくらいの時期に登場したバージョンで、多くの人々にRubyが普及した時代でした。ちなみに当時はRubygemsがまだ標準添付ではなく、1.9以降から標準添付になりました。

Rubyのプロジェクト管理のためにRedmineを導入

──園田さんは1.9系(1.9.0-3以降)のリリースマネージャーを務められています。就任の経緯について教えてください。

園田:順を追ってお話しすると、1.9系の目玉機能は多言語対応でした。この機能は各コミッターが以前から頑張って実装を続けていたもので、いよいよ1.9系でリリースしようということになったんです。しかし、もともとは2007年のクリスマス*に安定版である1.9.1がリリースされる予定だったものの、その時点ではまだ安定性に不安が残るということで、バージョン番号を1.9.0に変更してリリースされました。

*…Rubyのリリースはクリスマスに行われるのが恒例となっている。

f:id:findy-lab:20201224113129j:plain
園田さん

1.9系については当初まつもとさんがリリースマネジメントをやっていたものの、なかなか上手くいっていなかったんです。では、代わりに誰かがやるべきだろうと思い、私が手を挙げて1.9.0-3からリリースマネージャーを務めました。

──その時代に導入された仕組みはありますか?

園田:リリースマネージャー就任前の段階から、Rubyのプロジェクト管理のためにRedmineを導入しました。それまで、バグ報告やフィーチャーリクエストなどは全てメーリングリストでやりとりされていたんです。メーリングリストを追わなければ過去に行われたコミュニケーションが全くわからないという問題がありました。これはイシュートラッカーの仕組みを入れなければダメだと考えて、Redmineをセットアップしたという流れです。

ただ最初は、Redmineの利用に抵抗のある方もいましたから、そうした方々も無理なく移行できるような仕組みを自前で構築しました。メーリングリストの特定条件を満たすメールをRedmineのチケットへと変換するプラグインを書いたり、Redmineに報告をしたらメーリングリストにも同じ内容が流れるようにしたり。メーリングリストは日本語版と英語版がありますから、チケットに記載された言語から判別して適切なメーリングリストへと振り分けるプラグインを作ったりもしました。

さらに、RedmineのWikiフォーマットを変更できる機能も私が実装したものです。当時のRedmineはtextileというフォーマットしか使えませんでしたが、さすがに全Rubyistにtextileの利用を強制するわけにはいかないと思いました。そこで、まずRedmineでWikiフォーマットをカスタマイズできる仕組みをつくり、RD(Ruby Document format)をサポートするプラグインを書きました。今はRDも廃止されて、MD(Markdown)になっていますけどね。

卜部:Rubyのプロジェクト管理に用いられているRedmineは、十数年以上もさまざまなコミッターたちがカスタマイズしながら使い続けています。特に今回のインタビューに登場している人々は、自発的にそういった環境整備などに取り組む傾向が強いです。みんな根がプログラマーですから、可能な限りコードを書いて問題解決したいというモチベーションがありますね。

──コミッターの方々による地道な改善がRubyのプロジェクトを支えてきたのですね。先ほど話されていた多言語対応以外に、1.9系において目玉となった機能はあるでしょうか?

園田:YARVやネイティブスレッドなどですね。1.9系あたりからRubyの実行性能が大幅に良くなってきました。Rubyの性能改善は、コミッターである笹田(耕一)さんが継続的に大きな貢献をされています。

遠藤:笹田さんは1.9系の時代は主にRubyVM周りの評価速度の高速化に、2.0以降はGC(Garbage Collection)の改善に取り組んでいましたね。

互換性を壊さないために設計を歪めすぎると、より大きな不幸を生む

──では、遠藤さんがリリースマネージャーを務められたRubyのバージョンと就任の経緯を教えてください。

遠藤:私がリリースマネージャーを務めたのは2.0ですね。しかし、それ以前の1.9.2の時代から徐々に園田さんの本業が忙しくなってきていたため、リリースマネージャー補佐という役職を自発的に名乗り、リリースマネジメントの手伝いをするようになりました。

その後、園田さんがさらに多忙になり、2.0のリリース時期についての議論がなかなか進まない状態が続いていました。そこで、私が2011年10月にリリースマネージャーに立候補し、まつもとさんに承認されたという経緯があります。承認後すぐに今後のスケジュールを設定し、2013年2月24日(Ruby生誕20周年)を2.0.0のリリース日にするという目標を決めました。

f:id:findy-lab:20201224113124j:plain
遠藤さん

成瀬:2.0を出すならばRubyの誕生日がいいという話をしましたね。

遠藤:そうそう。クリスマスには間に合わなそうだという話をした記憶があります。

──2.0にはどのような機能が盛り込まれたのですか?

遠藤:目玉となったのはRefinementsとキーワード引数ですね。説明が前後しますが、2011年10月上旬に笹田さんから2.0の仕様を決めようという提案がありました。これに対し、私が2.0に必須の機能とそうでない機能とを区別しようという話をし、まつもとさんからRefinementsとキーワード引数を必須とする表明がなされたという経緯があります。

必須機能だけは絶対に盛り込み、他の機能は間に合わなければ割り切って見送る前提でリリースマネジメントをしていきました。ちなみに、1.9系は1.8系を比較するといくつも非互換変更が入っていたんですが、2.0系と1.9系の間には非互換変更を入れないようにする方針をまつもとさんが示していましたね。

卜部:Rubyは1.0が出てから2.0が出るまでの期間が長かったんですよ。実現したい機能についてみんなが夢を語っていたものの、収拾がついていなかった。現実的な落とし所を見つけてリリースをしなければならなかったバージョンでした。リリースマネジメントは大変だっただろうと思いますね。

遠藤:この時代のエピソードとして印象に残っているものがあります。2.0で必須となったキーワード引数は自分が初期版を設計・実装しましたが、コーナーケースの考慮漏れが多かったため、その後にバグ報告が続くような機能になってしまいました。

旧バージョンとの互換性を壊さないことを重視しすぎたために、言語設計上のバグを含む、歪んだ拡張になってしまったからです。リリースマネジメントをやっていて、機能についてしっかり考える余裕がなかったのもあったと思います。

そこで、3.0で思い切ってこの機能をつくり直すことにしましたが、今となってはキーワード引数の現行の挙動に依存している方々がたくさんいるため、結果的に見ればさらに大きな非互換変更を生じさせることになってしまいました。互換性を保つことは大切ですが、そのために設計を歪めすぎると、ときにより大きな不幸を生むという事例だと思います。

“燃え尽きないこと”を目標に

──遠藤さんが2.0のリリースマネージャーを務められた後、2.1からは成瀬さんに交代されています。どのような経緯で就任されたのですか?

成瀬:前任の遠藤さんが、燃え尽きに近い状態になってしまったからです。2.0の頃から、もしも遠藤さんがギブアップしたら私がやろうと心の準備はしていました。

OSS開発におけるリリースマネジメントは大変な役割で、多くのプロジェクトではスケジュールの遅延や関係者の燃え尽きが発生しています。そこで、私の場合は燃え尽きないことを第一の目標に、可能な限り継続しやすい体制を整えていこうと考えていました。2.1以降は、継続して私がリリースマネージャーを担当しています。

f:id:findy-lab:20201224113137j:plain
成瀬さん

──卜部さんや園田さんも、リリースマネージャーを務められた後は燃え尽きに近い状態になられたとWeb記事などで拝見しました。なぜでしょうか?

卜部:私たちは何も仕組みが整備されていない状態から手探りでやりましたから、あまり効率良くできなかった、頑張りすぎるきらいがあったという話だと思いますね。

成瀬:リリースに関連するタスクは非常に多いんですよ。全てに全力で取り組もうとすると絶対に力尽きてしまいます。なるべく無理のないように力をセーブすること、そしてセーブをしつつも高品質のプログラムがリリースされるように省力化を進めることが大切です。

いくつか取り組んだ施策のなかでも、CIの導入が一番効きました。それ以前にも各人が自分の手元で構築したCI相当の仕組みはあったと思いますが、Travis CIを導入するなどRubyのCIとして体系的な仕組みを構築したのは2012年くらいからでした。

CIの導入により、機能取り込みの方針にも変化がありました。以前は明確な実装の締め切りを設けて、間に合うものは入れる/間に合わなければ見送りという運用をしていましたが、CIの整備とともにバグの効率的な検出が可能になったため、極力ギリギリまで取り込む方針に変えましたね。

卜部:こんな話を聞くと、当たり前じゃんと読者のみなさんは考えるでしょうけど、この当たり前にたどり着くまでに長い時間がかかったという話なんだよね。

遠藤:当時は当たり前ではなかったことですからね。

成瀬:バージョン管理ツールやイシュートラッカー、CIなどの仕組みを、みんなが何年も模索しながら整備してきた結果として、今があるということですね。

──時代を経るごとに仕組みが整備されてきたわけですね。2.1系以降に盛り込まれた目玉機能はありますか?

成瀬:RGenGC(世代別GC)とRincGC(インクリメンタルGC)でしょうか。Garbage Collectionの改善により実行性能が大きく改善しました。それから、Bundlerが標準添付されるようになったのも大きいですね。

卜部:まだ目玉になりきれていないかもしれませんが、2.6から実験的実装として搭載され、2.7で性能改善が行われたJIT(Just-in-time)コンパイラも挙げられますね。JITは少しずつ適応領域が広がっているように思います。

成瀬:それから2.7ではオブジェクトのパターンマッチやirbにおける複数行編集の対応などもありました。

卜部:さすがに最近の話になると、記憶が鮮明なので機能を詳細に挙げられますね。

過去と比べて、圧倒的にコミュニケーションの量が増えた

──各バージョンに取り込む機能には、さまざまな選択肢があると思います。どのようにして機能の取捨選択が行われてきたのでしょうか?

園田:イニシャルリリースとパッチリリースでもまた、意思決定の仕組みは違いますね。

卜部:まずは昔の話からしますね。1.8系の頃には、まだGitHubもなかったですし当然ながらPull Requestも発行されませんでした。コミッターの権限を持っている人々は、自由にRubyのリポジトリへとコミットできた時代です。例えば1.8.6が出る際にどうやって新機能を決めていたかというと、各コミッターが各々で機能を実装して自由に入れていく感じだったと記憶しています。開発者同士が議論しあって新機能を決めることは全くなかったです。

園田さんが言ってくれたように、パッチリリースの場合はリリースフローが異なります。リリースマネージャーが各コミットを全てチェックして、入れるべき修正とそうでない修正を一つひとつ見ながら決めていました。かなり苦労の多い作業でしたね。

──園田さんがリリースマネージャーだった頃はいかがでしたか?

園田:1.9.1の頃は、コア機能に関して各人の意見が分かれそうなものはまつもとさんに最終的な判断を委ねていたものの、それ以外は必ずしもまつもとさんに確認をとっていたわけではないですね。コミッターが各々で判断していたケースも多かったと思います。

卜部:そう考えると、昔の運用はワイルドだった。

園田:いろんな人が良かれと思って機能を入れていくので、それらをまとめあげて世に出すという感じでしたね。

卜部:その後は、徐々にRubyの機能開発の大まかな方針をまつもとさんが語るようになり、みんながその目標に向けて頑張るような体制になってきました。この体制って、いつ頃からやり始めたんだろうね。

成瀬:2.0頃から徐々にという感じです。その頃から、まつもとさん自身がRubyのコードを自分で書くことが少なくなり、どんな機能を入れるかという方針決定のみを行うようになりましたね。

──機能開発の意思決定について、他にも変化したものはありますか?

卜部:開発者会議を月に1回開催しています。これはけっこう大きな変化ですね。

遠藤:毎月議題を募って、有志が事前に内容を理解したうえで、当日まつもとさんを交えながらRubyの方針策定をする会議です。毎年12月の定期的なリリースが上手くいっているのも、開発者同士がお互いの進捗状況をその場で確認しあえるのが大きいと思います。

卜部:昔は定期的に開催していたわけではなくて、たまに不定期で開催するような感じでしたね。プログラミング言語で委員会形式で運営されているものはけっこうあるので、ミーティングを開催すること自体は珍しくありません。しかし、毎月やっているというのはなかなか高頻度です。

──時代の変遷とともに、Rubyプロジェクトにおける運営方式も変遷しているのですね。

卜部:コミュニケーションの総量は圧倒的に増えたと思います。対面でのコミュニケーションだけではなく、テキストを書く量もずいぶん増えました。のっぴきならない状況まで問題を放置するのではなく、より早期の段階からみんなで連携しあって対策を考えるような形態になってきています。

──現在は、セキュリティ対応はどのような運用をされているのでしょうか?

卜部:脆弱性報告プラットフォームのHackerOneを活用することが多いです。このプラットフォームに報告された脆弱性を限られた人たちだけで見て、どんな対応をすればいいかを相談しあいます。修正内容を関係者や報告者にレビューしてもらったうえで、リリースフローに乗せるような形ですね。

成瀬:HackerOneでは有益な報告をしてくれた人にポータル上で報奨金を払うことも可能です。OSSを管理していて脆弱性の報告を受け付けたい方は、ぜひ利用してみてください。

印象に残るHashDoSや令和の対応

──セキュリティ対応に関連して、何か印象に残る機能改修はありますか?

成瀬:脆弱性まわりの話でいえばHashDoSですね。

卜部:HashDoSはつらかったですよね。ハッシュ関数と呼ばれる関数に、HashDoSという脆弱性がありました。脆弱性があると報告されたのはRubyの1.9でしたが、そのバージョンは実はすでにコミッターの田中哲さんがパッチを当てていたんですね。この修正を1.8にもバックポートしなければいけないですが、実は1.8と1.9とではハッシュ関数そのものが置き換わっていたので、すんなりバックポートできないという課題がありました。1.9は何だったんだっけ?

園田:1.9はMurmurHashだった気がします。

卜部:という事情により、1.9の対応を流用できず、脆弱性の内容を理解して自分でコードを書かなければいけませんでした。

成瀬:しかも、脆弱性対応なので相談できる相手が限られるのも大変なんですよね。

卜部:一番大変だったのはランダムネスのソースを作っていく部分でした。ハッシュはプロセスのかなり初期に使われるため、ハッシュが使用される瞬間にはすでに乱数がシードされている必要があります。ですが1.8当時はsrandが呼ばれるまで乱数がシードされていませんでした。そこに依存関係が発生して非常につらかったですね。プロセスのブートアップの仕組みから変えなければならなかったと記憶しています。

──それ以外に、何かの対応をしたエピソードで印象に残っているものはありますか。

成瀬:令和。

卜部:令和は印象深いですね。

成瀬:Unicodeでは合字と呼ばれる、複数の文字が組み合わさって1つの文字になっているものがあります。㍿などがそうですね。Rubyではunicode_normalizeという関数を用いて、この文字をバラすことができます。例えば、㍻を平成に変換するという感じです。この機能は、合字の文字コード番号をもとに処理を行うことで実現されています。

卜部:平成30年12月の時点で、次の元号の合字が追加されることと、その文字コード番号が何になるかはわかっていました。しかし新元号がわかるのは翌年の4月です。Rubyの新バージョンのリリースは12月ですから、どのタイミングで対応すべきか議論になりました。

成瀬:これは新機能だからという理由で、12月まで対応しないという意思決定もできました。でも、せっかくのお祝いごとですから早めに対応したいじゃないですか。そこで、4月にRubyの令和対応を行い、2.6.3としてリリースを行いました。

プロジェクトマネジメントはRubyから学んだ

──最後に、リリースマネージャーを経験したことで変化した、エンジニアとしての考え方や価値観について伺いたいです。

卜部:自分としては、まだまだ若輩者だった頃に無謀にもリリースマネージャーを務めたという感じでした。もともとソリッドな自分の思想や哲学があるところから始めたわけではないですから、考え方や価値観に影響を与えたかというと、なんとも言えない部分はありますね。

しかし、リリースマネジメントを務めることで、自分以外の人が書いたコードや文章などをたくさん読むようになるので、そこから学べたことはたくさんありました。それに、機能を入れる/入れないのジャッジも自分で担わなければならないケースもあるので、大変ではありましたがプログラマーとしてのスキル向上につながったと思います。

園田:言おうと思っていたことは、卜部さんにほぼ言われた気がします(笑)。数多くの人々と連携しあって開発を進めなければいけない役割ですから、自分にもプロジェクトマネジメントができるんだという自信はつきましたね。それとともに、1.9.1や1.9.2のリリースマネジメントを担った後、燃え尽きてその後はあまり関わっていないので、少しばかりの挫折感はあります。

遠藤:価値観が最も変わったのは、たくさんの人が使うソフトウェアをリリースして、誰かの役に立てることは尊いと思えるようになったことですね。リリースマネジメントに関わったことで、リリースに関する一連のプロセスを経験して、色んな人から感謝される経験をしました。そんな体験をすると、自分たちのやったことの意義を自然と実感しますよね。OSS開発において定期的かつなるべく予定通りにリリースすることが、とても重要なことだと考えるようになりました。

ただし、これを理解できるようになったのはリリースして数年くらい経ってからという気がします。リリースの渦中にあった頃は、あまり実感が持てませんでした。Ruby2.0のリリース前日にリリース記念のパーティが盛大に行われたのですが「実際のリリース作業は自宅で一人細々とやるだけなんだよなあ」とどこか冷めた気持ちだったことは今でも印象深く覚えています。

それから、リリースマネージャーを経験したことは、クックパッドに所属してフルタイムRubyコミッターとして働くことにも結びつきましたから、私の場合はかなり直接的な恩恵を受けられたと思います。

私はかつて完全に趣味でRuby開発に参加しており、Rubyを仕事でそれほど使っていたわけではなかったので、モチベーションの維持やユースケースの理解が課題でした。Rubyを使って成長した企業に雇ってもらい、Rubyが活用されていることを日々の業務で感じながら改良のヒントをもらえる。それによって、クックパッドや他のユーザーにとってもさらにRubyが便利なものになるという好循環が生まれていると思います。

──これまでの貢献が認められて業務としてRubyを開発するようになったという意味ですと、卜部さんも同じですね。同じようなモチベーションの変化はありましたか?

卜部:そうですね。自分がRubyを便利に使っていたからこそリリースマネジメントを始めて、思い入れが強かったからこそ頑張りすぎた反動で燃え尽きた部分がありました。一方、社内のニーズを背景に仕事としてRubyを開発するようになってから、モチベーションには明確な変化が生じましたね。

一般的に、企業では半年あるいは四半期ほどの区切りで、目標設定をしてプロジェクトを進めることが多いです。その区切りに合わせるような形で、自分にとってベストなペース配分を考えながら開発を進めていくサイクルができました。結果として、無理なくRubyの開発に専念できていると思います。

──企業がOSS開発を支援する意義が伝わりますね。では最後に成瀬さんからお願いします。

成瀬:OSS開発は楽しいものだとよく言われますが、リリースマネージャーという役割も私は楽しみながら取り組めています。プロジェクトを取りまとめる過程で、単にプログラミング言語の開発をするだけでは見えてこなかったものが見えてくる。自分にとっての学びが非常に大きいです。

よく考えてみると、エンジニアリングにおいて多人数のプロジェクトで中心になって動いた経験は、業務よりもRubyのほうが先だったかもしれません。いうなれば、プロジェクトマネジメントはRubyで学んだという感じでしょうか。どのようなスケジュールで何の機能を提供すべきかを考えるようになりましたし、機能の開発を通して世の中のどんな課題を解決したいのかをとても意識するようになりました。

取材・執筆:中薗昴