新しいパッケージ形式のサポート開発者
この文書では、新しいパッケージ管理システムのサポートを GitLab に追加する方法を説明します。
すでにサポートされているフォーマットについてはPackages and registries ドキュメントを参照してください。
バックエンドを変更するだけで、新しい書式を追加することができます。このガイドは表面的なものであり、コードの書き方をカバーするものではありません。しかし、以下のマージリクエストを見ることでよい例を見つけることができます:
一般情報
既存のデータベースモデルには以下が必要です:
- すべてのパッケージはプロジェクトに属します。
- すべてのパッケージファイルはパッケージに属します。
- パッケージは1つ以上のパッケージファイルを持つことができます。
- パッケージモデルは、パッケージとそのバージョンに関する情報を保存することに基づいています。
APIエンドポイント
パッケージシステムはAPI経由でGitLabと連携します。例えばlib/api/npm_project_packages.rb
は npm クライアントと連携するための API エンドポイントを実装しています。そこで、まず最初にすべきことは、パッケージシステムのクライアントを動作させるために必要な API エンドポイントを新しいlib/api/your_name_project_packages.rb
ファイルに追加することです。通常、それは次のようなエンドポイントを持つことを意味します:
- パッケージ情報を取得します。
- パッケージファイルの内容を取得します。
- PUT アップロードパッケージ。
パッケージはプロジェクトに属しているので、アップロードとダウンロードのためにプロジェクトレベルのエンドポイント(リモート)を持つことが期待されます。例えば
GET https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/
PUT https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/
グループレベルやインスタンスレベルのエンドポイントは、プロジェクトレベルのエンドポイントが本番環境で利用できるようになってから考えるべきです。
リモート階層
パッケージは様々なアクセスレベルでスコープされ、一般的にはリモートを設定することで設定されます。リモートのエンドポイントをプロジェクトレベルで設定すると、パッケージをインストールするときに、そのプロジェクトに属するパッケージだけが見えるようになります。別の方法として、グループレベルのエンドポイントを使用すると、指定したグループ内のすべてのパッケージを見ることができます。最後に、インスタンスレベルのエンドポイントを使うと、GitLabインスタンス全体のすべてのパッケージを見ることができます。
MVC としては、プロジェクトレベルのエンドポイントから始めることをおすすめします。リモート階層の典型的な反復プランは、次のようになります:
- プロジェクトへのパブリッシュとインストール
- グループからのインストール
- インスタンスにパブリッシュしてインストール(これはセルフマネージメントのお客様向けです)
インスタンスレベルのエンドポイントを使用するには、より厳格な命名規則が必要です。
命名規則
インスタンスレベルのエンドポイントの名前の衝突を避けるには、パッケージの命名規則を定義して、パッケージが属するプロジェクトを識別できるようにする必要があります。一般的には、プロジェクト ID や完全なプロジェクトパスをパッケージ名に使用します。例としてConan の命名規則を参照してください。
グループやプロジェクトレベルのエンドポイントでは、名前付けの制約を少なくすることができ、2つのパッケージ名に衝突がないことを確認するのはグループやプロジェクトのメンバー次第です。しかし、システムはユーザーが与えられたスコープ内で既存の名前を再利用できないようにする必要があります。
そうでなければ、命名はパッケージマネージャの命名規則に従い、そのパッケージタイプのpackage.md
モデルで検証を含めるべきです。
サービスとファインダー
パッケージやパッケージファイルのレコードの作成、パッケージの検索などのタスクを実行するためのロジックはAPIファイル内に存在するべきではありません。共通のパッケージロジックを可能な限りグループ化するために、既存のサービスやファインダは可能な限り使用または拡張されるべきです。
設定
GitLabには設定ファイルにpackages
セクションがあります(gitlab.rb
またはgitlab.yml
)。これはGitLabがサポートするすべてのパッケージシステムに適用されます。通常、そこに何かを追加する必要はありません。
パッケージはオブジェクトストレージを使うように設定できるので、あなたのコードはそれをサポートしなければなりません。
MVCアプローチ
新しいパッケージシステムをGitLabにインテグレーションする方法は、MVCを使います。そのため、最初のイテレーションでは最低限のユーザーアクションをサポートしなければなりません:
- GitLab ジョブによる認証、個人アクセス、プロジェクトアクセス、デプロイトークン。
- パッケージのアップロードとユーザーインターフェイスでの基本的なメタデータの表示
- 荷物の引き上げ
- 必要なアクション
必須アクションとは、対応するパッケージマネージャCLIが適切に動作するように、GitLabが処理しなければならないすべての追加リクエストです。それは検索機能であったり、パッケージのメタ情報を提供するエンドポイントであったりします。例えば
- NuGetの場合、Visual Studioをサポートするために、最初のMVCイテレーションの間に検索リクエストが実装されました。
- npm については、
npm
が tarball URL を取得するために使用するメタデータエンドポイントがあります。
最初の MVC イテレーションでは、リモート階層のプロジェクトレベルにとどまることをお勧めします。他のレベルは将来のマージリクエストで取り組むことができます。
MVC には通常 2 つのフェーズがあります:
繰り返しは小さく
新しいパッケージマネージャを実装するとき、基本的な使い方をサポートするために必要なすべてのエンドポイントとサービスを含む大きなマージリクエストを作成したくなります。そうではありません:
- API エンドポイントを機能フラグの後ろに置きましょう。
- レビュープロセスを短縮するために、各エンドポイントまたは動作(ダウンロード、アップロードなど)を別のマージリクエストで提出してください。
分析
このフェーズでは、パッケージシステムで使用されるAPIについて可能な限り多くの情報を収集します。ここでは、いくつかの有用な側面について説明します:
- 認証:認証: どのような認証メカニズムが利用可能か (OAuth、Basic Authorization、その他)。GitLab ユーザーはしばしば個人アクセストークンを使いたがります。MVC の最初のイテレーションでは必要ありませんが、CI/CD ジョブ トークンは将来のある時点でサポートされなければなりません。
- リクエスト:MVCを動作させるために必要なリクエスト。理想的には、MVCに必要なすべてのリクエスト(必要なアクションを含む)のリストを作成します。さらに調査を進めると、リクエストとレスポンスボディを持つ各リクエストの例を提供できるかもしれません。
- アップロード:アップロードプロセスがどのように動作するか注意深く分析してください。このリクエストは実装が最も複雑でしょう。アップロードは様々な方法(bodyやmultipart)でエンコードされ、全く異なるフォーマット(例えば、パッケージファイルが特定のフィールドのBase64値であるJSON構造)であることさえあるので、ここでは詳細な分析が必要です。これらのエンコーディングの違いにより、GitLabとGitLab Workhorseでは実装が若干異なります。より詳細な情報については、ファイルアップロードをレビューしてください。
- エンドポイントGitLabに実装するエンドポイントURLのリストを提案してください。
-
作業の分割:MVCを段階的に構築するための変更点のリストを提案してください。これによって、どれだけの作業があるのかがわかります。以下は、ケースバイケースで適合させる必要があるリストの例です:
- 空のファイル構造(APIファイル、このパッケージのベースサービス)
- パッケージマネージャに「ログイン」するための認証システム
- メタデータの識別と該当するテーブルの作成
- オブジェクトストレージ直接アップロードのWorkhorseルート
- アップロード/パブリッシュに必要なエンドポイント
- インストール/ダウンロードに必要なエンドポイント
- 必要なアクションに必要なエンドポイント
分析が完了するには通常マイルストーン全体が必要ですが、同じマイルストーンで実装を開始することも不可能ではありません。
特に、GitLab Workhorseプロジェクトではアップロードリクエストにいくつかの要件があります。このプロジェクトはRailsバックエンドとはリリースサイクルが異なります。アップロードリクエストの分析が終わったら、すぐにそちらにイシューをオープンすることを強くお勧めします。こうすることで、railsバックエンドにアップロードリクエストが実装されたときに、GitLab Workhorseはすでに準備ができています。
実施
異なるマージリクエストの実装は異なるパッケージシステムのインテグレーションによって異なります。貢献者は実装フェーズのいくつかの重要な点を考慮に入れてください。
認証
MVCは最初からパーソナルアクセストークンをサポートする必要があります。トークンには2つのオプションがあります:OAuthとBasic Accessです。
OAuth認証はすでにサポートされています。npm API で例を見ることができます。
Basic Access認証のサポートは、APIヘルパーの特定の関数をオーバーライドすることで行われます。この認証メカニズムでは、クライアントによっては認証されていないリクエストを最初に送信し、WWW-Authenticate
フィールドを含む 401 Unauthorized レスポンスを待ってから更新された (認証された) リクエストを送信することができることに注意しましょう。この場合、GitLab は401 Unauthorized
レスポンスを処理しなければならないので、より複雑になります。NuGet APIはこのケースをサポートしています。
作成者
read_package
,create_package
,destroy_package
には、プロジェクトおよびグループレベルの権限が存在します。各エンドポイントは、処理を続行する前に、プロジェクトまたはグループに対して要求ユーザーを承認する必要があります。
データベースとメタデータの処理
現在のデータベースモデルでは、パッケージごとに名前とバージョンを保存できます。新しいパッケージをアップロードするたびに、Package
の新しいレコードを作成するか、既存のレコードにファイルを追加します。PackageFile
は、name
、side
、sha1
などのファイル関連の情報をすべて保存できる必要があります。
1つのパッケージシステムのサポートにのみ保存する必要がある特定のデータがある場合は、別のメタデータモデルを作成することを検討してください。パッケージ固有のデータの例としてpackages_maven_metadata
テーブルとPackages::Maven::Metadatum
モデルを、パッケージファイル固有のデータの例としてpackages_conan_file_metadata
テーブルとPackages::Conan::FileMetadatum
モデルを参照してください。
あるパッケージマネージャに対してパッケージ固有の動作がある場合、それらのメソッドをメタデータモデルに追加し、パッケージモデルからデリゲートします。
既存のパッケージ UI はpackages_packages
とpackages_package_files
テーブルの情報のみを表示します。メタデータテーブルに格納されたデータを表示する必要がある場合、~frontend
の変更が必要です。
ファイルのアップロード
ファイルのアップロードは、GitLab Workhorseによってオブジェクトアクセラレーションアップロードを使って処理されるべきです。これは、GitLabへのすべてのリクエストをチェックするWorkhorseプロキシがアップロードリクエストをインターセプトし、ファイルをアップロードし、ファイルそのものではなくメタデータとファイルの場所のみを含むリクエストをメインのGitLabコードベースに転送するということです。このプロセスの概要は開発者向けドキュメントにあります。
コード的には、これは追加されるアップロードエンドポイント(インスタンス、グループ、プロジェクト)ごとにGitLab Workhorseプロジェクトにルートを追加しなければならないことを意味します。このマージリクエストでは、インスタンスレベルの Conan 用エンドポイントを Workhorse に追加する例を示します。Maven プロジェクトレベルのエンドポイントも同じファイルに実装されています。
ルートが追加された後、/authorize
アップロードエンドポイントの /authorize
追加バージョンを/authorize
API ファイルに /authorize
追加する必要があります。/authorize
この例では、Maven用に追加されたエンドポイントを示しています。この /authorize
エンドポイントはWorkhorseからのリクエストを検証し、作成者を承認します。その後、典型的なアップロードエンドポイントが以下に実装され、Workhorseがパッケージレコードを作成するために提供するメタデータを消費します。Workhorse は、タイプ、サイズ、さまざまなチェックサム形式など、さまざまなファイルのメタデータを提供します。
テスト目的で、ローカルの開発環境でオブジェクトストレージを有効にするとよいでしょう。
ファイルサイズの制限
GitLabパッケージレジストリにアップロードされるファイルはフォーマットによって制限されています。GitLab.comでは、タイムアウト問題や悪用を防ぐために、通常5GBに設定されています。
新しいパッケージタイプがPackages::Package
モデルに追加されたときは、この例と同じようにサイズ制限を追加する必要があります。ファイルサイズの制限が適用されない場合は、関連するテストを更新する必要があります。サイズ制限が適用されない唯一の理由は、パッケージ形式がパッケージファイルをアップロードして保存しない場合です。
GitLab.com のレート制限
パッケージマネージャークライアントは、GitLab.com標準のAPIレートリミットを超える高速リクエストを行うことができます。その結果、429 Too Many Requests
エラーが発生します。
私たちは、より高いレートリミットを許可するための一連のパスをオープンしました。それが不可能でない限り、新しいパッケージマネージャは拡張されたパッケージレート制限を利用できるように、これらの規約に従うべきです。
これらのルートプレフィックスはより高いレート制限を保証します:
/api/v4/packages/
/api/v4/projects/:project_id/packages/
/api/v4/groups/:group_id/-/packages/
MVCチェックリスト
新しいパッケージマネージャのサポートを GitLab に追加する場合、最初のイテレーションには以下の機能が含まれていなければなりません。必要に応じて多くのマージリクエストを通して機能を追加することができますが、機能フラグが削除されたときにはすべての機能が実装されていなければなりません。
- プロジェクトレベルの API
- プッシュイベント追跡
- プルイベントトラッキング
- パーソナルアクセストークンによる認証
- ジョブ・トークンによる認証
- デプロイトークンによる認証(グループとプロジェクト)
- ファイルサイズ制限
- ファイル形式ガード (パッケージタイプに有効なファイル形式のみ受け付けます)
- バリデーション付き名前正規表現
- バリデーション付きバージョン正規表現
- アップロードを加速するWorkhorseルート
- パッケージのメタデータを抽出するバックグラウンドワーカー(該当する場合)
- ドキュメント (機能の使用方法)
- API ドキュメント (curlの例を含む個々のエンドポイント)
- シード
db/fixtures/development/26_packages.rb
- Grafanaチャート用ランブックの更新
- 最低限)パッケージの公開とインストールのためのエンドツーエンドの機能テスト
今後の作業
MVCに取り組んでいる間に、コントリビューターはMVCに必須ではないが、より良いユーザーエクスペリエンスを提供できる機能を見つけるかもしれません。一般的には、そのような機能やイシューをオープンにしておくのがよいでしょう。
以下はその例です。
- 検索に必要なエンドポイント
- 追加パッケージ情報とメタデータを表示するフロントエンドの更新
- ファイルサイズの制限
- メトリクスのトラッキング
- パッケージからより多くのメタデータフィールドを読み取り、フロントエンドで利用できるようにします。例えば、パッケージにタグを付けることができます。これらのタグはバックエンドで読み込まれて保存され、パッケージの UI に表示されます。
- リモート階層の上位レベルのエンドポイント。このステップでは、命名規則を作成する必要があるかもしれません
例外
このドキュメントは、GitLabにすでに存在する既存の構造とロジックに合わせてパッケージマネージャを実装する方法のガイドラインにすぎません。この構造は、どのようなパッケージマネージャにも対応できるように拡張可能で柔軟であることを意図していますが、もしあるパッケージマネージャの制約や必要性から外れる正当な理由がある場合は、最も効率的な結果を得るために、実装のイシューやマージリクエストで提起し、議論すべきです。