依存関係ガイド

このドキュメントでは、Beamの依存関係を最新の状態に保つためのポリシーについて説明します。

古い依存関係は、ユーザーに負担をかけ、システムが一部のユーザーにとって使用できなくなる可能性があります。多くのユーザーはBeamを単独で使用せず、同じデプロイメント環境で他の依存関係もバンドルしています。これらの追加の依存関係は、ユーザーの環境に互換性のない依存関係を引き込む可能性があり、これもBeamパイプラインの破損につながり、場合によっては未定義の動作を引き起こす可能性があります。これを防ぐために、ユーザーはデプロイメント環境を更新する必要があります。さらに悪いことに、他の依存関係と一緒にBeamをまったく使用できなくなる可能性があります。

Beam Java SDKのGradleビルドは、トップレベルの依存関係のセットを定義し、さまざまなコンポーネント(ランナー、IOコネクタなど)はこれらの依存関係を含めることを選択できます。コンポーネントは通常、トップレベルで定義されたバージョンを使用しますが、これらのバージョンをオーバーライドすることを選択できます。

コンポーネント*X*が依存関係*D*のバージョンを*a*から*b*にオーバーライドすることを選択し、別のコンポーネント*Y*が*D*のバージョン*b*と互換性がない場合、両方のコンポーネント*X*と*Y*を使用するユーザーのデプロイは破損した状態になります。

Beamの2つの依存関係が共通ライブラリに依存しているが、そのライブラリの互換性のないバージョンを使用している場合にも、同様の問題が発生する可能性があります。

また、ユーザーはBeamを単独で使用しない場合があります。同じ環境でBeamと他のライブラリの両方に依存しているユーザーは、Beamと他のライブラリが互換性のないバージョンを使用している依存関係を共有している場合、同様の問題に遭遇する可能性があります。

Beam Python SDKは依存関係を少し異なって処理します。すべての依存関係は単一のsetup.pyファイルで定義され、グループ化されます。グループの1つは必須の依存関係を記述し、他のグループはさまざまなオプション機能の依存関係を定義するためのものです。すべてのPythonモジュールは、setup.pyファイルで定義されている依存関係のバージョンを使用する必要があります。さらに、ほとんどの依存関係について、Python SDKは次のメジャーバージョンまでの自動アップグレードを許可します。この設定のため、Python SDKは現在コンポーネントの競合に遭遇していませんが、上記で説明した他の2つの形式の依存関係の競合は依然として発生する可能性があります。

この状況は、実行時にさらに複雑になる可能性があります。ランナー固有のコードは、特定のモジュールに含まれる依存関係と互換性がない場合があり、これらの依存関係がランタイムにリークすると、パイプラインが破損した状態になる可能性があります。

全体的な問題はBeamに固有のものではなく、業界ではダイヤモンド依存関係問題(または依存関係地獄)としてよく知られています。

ダイヤモンド依存関係問題の一般的な解決策の1つは、セマンティックバージョニングです。基本的な考え方は、依存関係が*x.y.z*の形式でバージョン付けされることです。ここで、*x*は*メジャーバージョン*、*y*は*マイナーバージョン*、*z*は*パッチバージョン*です。メジャーバージョンの変更は後方互換性がない場合があり、まれであると予想されます。マイナーバージョンとパッチバージョンはより定期的にリリースされる場合がありますが、後方互換性があると予想されます。しかし実際には、重要な修正(セキュリティパッチなど)がマイナーバージョンまたはパッチバージョンの更新としてリリースされる可能性があり、Beamプロジェクトが依存関係の最近リリースされたマイナーバージョンに依存することは健全です。

古い依存関係の特定

依存関係を最新の状態に保つための大きな部分は、コミュニティがアップグレードを試みるべきBeamの古い依存関係を特定することです。

Beamは現在、さまざまなSDKの古い依存関係を特定しようとするJenkinsジョブを毎週実行しています。このJenkinsジョブは、Beam開発者リストで共有される週次レポートを生成します。

これに加えて、Beamコミュニティメンバーは、手動で実行する必要がある他の重要な依存関係の更新を特定する場合があります。例えば、

この種の緊急に必要なアップグレードは、Jenkinsジョブによって数か月間自動的に取得されない場合があります。そのため、Beamコミュニティは、このような問題を早期に特定し、アップグレードを実行するための行動を起こす必要があります。

Dependabotによる課題の自動化

依存関係のアップグレードプロセスを追跡するために、Dependabotは古い依存関係をアップグレードするためのプルリクエストを自動的に作成します。

特定された古い依存関係のアップグレード

古い依存関係が特定された後、Beamコミュニティは依存関係を定期的にアップグレードするための行動を起こす必要があります。 Beamコミュニティは、依存関係のアップグレードに関する以下のポリシーに合意しています。

Beamの依存関係の状態に関する人間が読めるレポートは、自動化されたJenkinsジョブによって毎週生成され、開発者リストを通じてBeamコミュニティと共有されます。

これらのレポートは簡潔で、コミュニティが対応する必要があるケースを強調する必要があります。

Beamコンポーネントは、トップレベルで依存関係とそのバージョンを定義する必要があります。まれな例外はありますが、それらには説明が伴う必要があります。

コンポーネントには、さまざまなBeamランナー、IOコネクタなどが含まれます。コンポーネントレベルの依存関係バージョンの宣言は、まれな場合にのみ実行する必要があり、依存関係をオーバーライドする理由を説明するコメントを付ける必要があります。たとえば、他のコンポーネントによって利用される可能性が低いランナー固有の依存関係は、ランナーで定義される場合があります。

大幅に古い依存関係(手動または自動化されたJenkinsジョブによって特定された)は、次のリリースのブロッカーとなる問題になります. リリースマネージャーは、ブロッカーを次のリリースにプッシュするか、ブロッカーからダウングレードすることを選択できます.

これは、Beamの次のメジャーバージョンとマイナーバージョンのリリースのブロッカーになります。

手動で特定された重要な依存関係の更新については、Beamコミュニティメンバーは次のリリースのブロッキングイシューを作成する必要があります。これに加えて、Beamコミュニティメンバーは、ユーザーに緊急に提供する必要がある重要な依存関係の修正のためのパッチリリースをトリガーする場合があります。

リークした場合、他のコンポーネントに問題を引き起こす可能性のあるJava SDKコンポーネントの依存関係は、ベンダリングする必要があります。

ベンダリングとは、サードパーティの依存関係のコピーを作成するプロセスです。再パッケージ化と組み合わせることで、ベンダリングにより、Beamコンポーネントは他のコンポーネントと競合することなく、サードパーティライブラリに依存できます。ベンダリングは、ユーザー環境にデプロイされる依存関係の総数を増やす可能性があるため、ケースバイケースで行う必要があります。

依存関係の更新と後方互換性

Beamのリリースは、一般的にセマンティックバージョニングのルールに従います。したがって、コミュニティメンバーは依存関係を更新する際に注意する必要があります。依存関係のマイナーバージョンの更新は、ほとんどの場合、後方互換性があります。ただし、依存関係の一部の更新は、BeamのAPIまたは機能の後方互換性のない変更につながる可能性があります。PRレビュー担当者とコミッターは、マージ前にBeamに後方互換性のない変更を導入する可能性のある依存関係の更新を検出するように注意する必要があり、依存関係を更新するPRには、PRコメントの形式でこの検証に関するステートメントを含める必要があります。Beamの非実験的な機能に後方互換性のない変更をもたらす依存関係の更新は、Beamの次のメジャーバージョンリリースまで保留する必要があります。このポリシーの例外は、極端な場合(たとえば、後続のメジャーバージョンでのみ修正される既存の依存関係のセキュリティ脆弱性のため)にのみ発生する必要があり、Beam開発者リストで議論する必要があります。実験的な機能に対する後方互換性のない変更は、マイナーバージョンリリースで導入される場合があることに注意してください。