SoundCloudのJVMKitライブラリは、サービスのスキャフォールディング、データベースやKafkaとの統合、メトリクスといった共有JVMパターンを、社内の数百のScala、Java、Clojure、JRubyサービスに提供していた。採用が進むにつれ、プラットフォームチームはどのサービスがJVMKitのAPIのどの部分に依存しているかを把握できなくなり、毎回のリリースが賭けになっていた。定例の更新が、チームが影響を受けることすら知らなかったサービスを静かに壊す可能性があった。

SoundCloudでは依存関係が各リポジトリのビルドファイル(JVMはsbt、AndroidはGradle、Webはnpm)で明示的に宣言されていたため、チームは全リポジトリを、5分ごとに更新される正規表現ベースのコード検索エンジンであるZoektでインデックス化した。JVMKitを依存関係として記載しているビルドファイルに対する単純なクエリから、JVMKitの変更によって影響を受ける全サービスを表す生きた逆依存関係グラフが自動生成され、手作業で追跡する必要がなくなった。

そのグラフを手に、チームは検証パイプラインを構築した。依存する各サービスについて、リポジトリをクローンし、未変更のままコンパイルおよびテストしてベースラインを確立し、次に候補のJVMKitバージョンに差し替え、既知の破壊的API変更に対するスクリプト化された修正を適用し、再度コンパイルおよびテストする。ベースラインが通り候補が失敗した場合、原因はJVMKitの変更であり、そのサービスに元々あった破損ではない。このチェックは依存する全サービスの集合に対して夜間に実行され、プルリクエストごとには、より高速な許可リスト方式のサブセットに対して実行された。

ライブラリをリリースする前に、すべての呼び出し元をコンパイルおよびテストする

手作業で誤りやすいプロセス(リリースし、チームからの苦情を待つ)を、リリース出荷前に実行される自動的で反証可能なチェックに置き換えた。

まず未変更のベースラインを実行することで、失敗がJVMKitの変更に由来するのか、その日すでに壊れていたサービスに由来するのかを切り分けた。

検証を夜間の全体実行と高速なPRスコープの実行に分けることで、完全なカバレッジを省くことなくフィードバックを迅速に保った。

逆依存関係グラフは手作業で維持されるのではなくコードから生成されたため、サービスの追加や削除に応じて正確なまま保たれた。

1つの社内ライブラリが数百のサービスの基盤となっている場合、期待に賭けて出荷するのではなく、依存関係グラフをクエリ可能にし、CIにすべての下流の呼び出し元を最初にテストさせるべきだ。

JVMKitは引き続きSoundCloudの数百のサービスと数千の本番インスタンスを支えた。検証パイプラインが整ったことで、プラットフォームチームはJVMKitをより頻繁にリリースできるようになり、失敗は下流で原因不明の破損として表面化するのではなく、特定のステップと特定の原因に追跡可能になったと報告した。

出典をたどる

出典

  1. Did I Break You? Reverse Dependency Verification SoundCloud Engineering · developers.soundcloud.com ·