Skip to content

Instantly share code, notes, and snippets.

@sile
Last active October 14, 2017 15:50
Show Gist options
  • Select an option

  • Save sile/3acc977b1b1030ecadbe12f3733b2ef3 to your computer and use it in GitHub Desktop.

Select an option

Save sile/3acc977b1b1030ecadbe12f3733b2ef3 to your computer and use it in GitHub Desktop.
Rustの「RFC 2141: cargo_alternative_registries」の要約メモ

RFC 2141: cargo_alternative_registries

要約

パブリックなcrates.io以外に、プライベートなcrates.ioのインスタンスも利用可能にしよう。

動機

  • クローズドな開発用にあると便利
  • 今でもgitのurlを指定すれば似たようなことはできる:
    • ただし、バージョニングやディスカバリティといった面での恩恵が受けられない
    • ! 個人的にはdocs.rsもセットで使いたい ( https://github.com/onur/docs.rs を適当に立てれば良い? )
  • パブリック・プライベートなcrates.ioの両方を併用可能にしたい

ガイドレベルの説明

レジストリ定義の仕様

  • .cargo/configで複数レジストリを定義可能にする
    • .cargo/../の子孫ディレクトリに対して有効
    • Cargo.tomlで個別に定義しなくても良い
    • プロジェクトコードからの分離は、セキュリティの面でもより望ましい

.cargo/config内ではregistriesキーを使って、crates.io以外のレジストリを指定:

[registries]
choose-a-name = "https://my-intranet:8080/index"

次のようにも指定可能:

[registries.choose-a-name]
index = "https://my-intranet:8080/index"

認証情報を指定する必要がある場合には.cargo/credentialsを使う(典型的には.cargo.configよりも強いパーミッションの制限が必要):

[registries.my-registry]
username = "myusername"
password = "mypassword"

CI

  • 「TravisCIのようなCIシステムがレジストリ設定を取得できない」という問題はある
  • ただし現状でもCargoは、.cargo/config内の任意の設定を環境変数経由で指定可能
  • 例えばTravisの暗号化された環境変数機能を使ってCARGO_REGISTRY_MY_REGISTRY_INDEX=https://my-intranet:8080/indexのような変数を設定すれば良い

別のレジストリに登録されているcrateを依存に指定する

Cargo.tomlで、以下のように記述すれば良い:

[dependencies]
secret-crate = { version = "1.0", registry = "my-registry" }

※ この文法は最初は不安定な機能として、nightlyのCargoにのみ導入される予定

別のレジストリにパブリッシュする (意図せぬパブリッシュは防止)

Cargo.tomlpublish設定を拡張:

  • 現状はpublish = falseで、パブリッシュを禁止できる
  • それをpublish = ["my-registry"]のように、許可レジストリ群を指定可能にする
    • その場合cargo publish --index my-registryのように、パブリッシュ時に明示的に対象レジストリを指定する必要がある
    • --indexオプションがない場合はエラー
  • NOTE:
    • publishキーを省略した場合はpublish = ["crates.io"]と等しい(! 若干意訳)
    • publish = falsepublish = []と等しい

最低限のレジストリを動作させる

最小限のレジストリの構成要素:

完全なレジストリを動作させる

  • このRFCはcrates.ioのAPIの標準化等は行わない
  • ただしcrates.ioのコードベースを使って、代替レジストリにcrates.ioの機能を提供可能なようにはできて然るべき

Crates.io

  • crates.ioはオープンソース用なので、代替レジストリへの依存を持つcrateのパブリッシュは拒否される
    • 代替レジストリの可用性をcrates.ioが保証できないので、許容すると信頼性を損ないかねない
    • 現状、git指定の依存を拒否しているのと同様
  • crates.ioのコードベースには「許可レジストリリスト」の設定を追加予定
    • 「プライベートレジストリおよびcrates.ioだけを許可」といった指定を可能にするため

既存の機能との相互作用

このRFCの提案は、以下の機能には影響を与えない(ようにすべき):

  • source replacement
    • ! この機能を使えば、現在でもプライベートなレジストリは実現できそう(ただしcrates.ioとの併用は無理?)
  • cargo-vender

リファレンスレベルの説明

レジストリインデックス形式の仕様

レジストリインデックス:

有効なレジストリインデックスは、次の基準を満たす:

  • gitリポジトリに格納されている
  • トップレベルにconfig.jsonというファイルがある:
    {
      // [required]
      // 登録crateのソースファイル(tarball)の取得先
      "dl": "https://my-crates-server.com/api/v1/crates",
    
      // [optional]
      // crates.io相当のAPIを提供するサーバ
      "api": "https://my-crates-server.com/",
    
      // [optional]
      // 許可レジストリ一覧
      "allowed-registries": ["https://github.com/rust-lang/crates.io-index", "https://my-intranet:8080/index"]
    }
  • crateのメタデータを保持するためのディレクトリ群:
    • 1/ - 名前が一文字のcrate用のファイル群を保持
    • 2/ - 名前が二文字のcrate用のファイル群を保持
    • 3/ - 名前が三文字のcrate用のファイル群を保持
    • それ以外は{最初の二文字}/{次の二文字}/以下に保持される
      • sampleという名前のcrateならsa/mp/
  • 各crateのメタ情報は、その名前をファイル名としてJSONに保持されている:
    {
      "name": "my_serde",
      "vers": "1.0.11",
      "deps": [
          {
              "name": "serde",
              "req": "^1.0",
              "registry": "https://github.com/rust-lang/crates.io-index",
              "features": [],
              "optional": true,
              "default_features": true,
              "target": null,
              "kind": "normal"
          }
      ],
      "cksum": "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9",
      "features": {
          "default": [
              "std"
          ],
          "derive": [
              "serde_derive"
          ],
          "std": [
    
          ],
      },
      "yanked": false
    }

新しいコマンド: cargo generate-index-metadata

cargoを使ってcrate用のメタデータが作成できると便利だね。

関連する事柄

複数レジストリを便利に扱うために、以下もサポート予定:

  • cargo add-registryコマンドの追加
  • インデックスではなくAPIのURLも指定可能にする(cargo/issues/4208)
  • .cargo/credentialに複数トークンを保存可能にする(cargo/issues/3365)
    • パブリッシュ先のレジストリ変更時に、再ログインが不要なように
  • 現在--indexを受け取る全てのCargoコマンドで、--registry registry-nameも指定可能にする
  • crate名のリネーム:
    • 複数レジストリに同じ名前を持つcrateが存在し、その両方を使いたい場合等に必要
    • 関連: RFC 2126
      • random = { version = "0.3", crate = "rand" }のように指定可能にする
  • .cargo/configと同様に.cargo/credentialsの項目も環境変数経由で指定可能にする
  • 認証不要なレジストリはCargo.toml内で直接URLを指定可能にする
    [dependencies]
    my-crate = { version = "1.0", registry = "http://crate-mirror.org/index" }

欠点

  • 代替レジストリと複数の公開レジストリのサポートは、エコシステムを破壊する可能性がある
  • ただし、利点の方が大きいと考えている

論拠と代替案

  • 以前のRFCでは、Cargo.tomlに必要な全ての情報を記載することを提案していた:
    • 問題点:
      • 複数プロジェクトで重複した情報の記載が必要
      • 認証情報がVCSに保存される
    • 後、このRFCではレジストリインデックスの形式が未定義
  • 代替案としては「レジストリのURLは.cargo/configないしCargo.tomlのどちらかのみで指定可能」なようにすることが考えられる:
    • 今回のRFCの欠点:
      • 選択肢が増えるので、間違ったプラクティスをユーザが選びかねない
      • 実装がより複雑
    • 利点:
      • いろいろなシチュエーションに合わせて、より便利な方法を選択可能

未解決の問題

  • 名前はこれで大丈夫?
    • cargo generate-index-metadata??
    • registry = my-registry?
    • publish-registries = []?
  • .cargo/credentialsでサポートが必要な認証パラメータは?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment