アプリケーション依存関係を Git サブモジュールで解決する
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2022年03月09日(水)
Table of Contents
最新のアプリケーションがサードパーティ製ライブラリに大きく依存しているため、これらの依存関係をアプリケーションリポジトリ自体の中で指定しなければなりません。RubyGems、Maven in Java、Python の pip のようなツールはすべて依存関係マネージャです。これらは、表明されたアプリケーション依存関係のリストを、アプリケーションが実行中に使用するコードまたはバイナリに変換します。
しかし、必要なサードパーティ製ライブラリを依存関係マネージャが解決できないこともあります。このようなシナリオの例として、インターネットからアクセスできないプライベートライブラリや、依存関係マネージャを介した配布のためのパッケージングをメンテナーが行っていないライブラリがあります。これらの状況では、Git サブモジュールを使用して外部依存関係を手動で管理できます。
このガイドでは、Git サブモジュールを使った依存関係管理の良い点と悪い点と、サブモジュールを使用しないために考慮するいくつかの代替アプローチを説明します。
Git サブモジュール
Git サブモジュールは、あるリポジトリの内容を別のリポジトリ内に含めることを、参照されるリポジトリの場所を指定するだけでできるようになる Git SCM の機能です。これは、外部ライブラリのソースをアプリケーションのソースツリーに含めるメカニズムを提供します。
たとえば、FooBar
ソースを heroku-rails
プロジェクトに含めるには、git submodule add
コマンドを使用します。
$ cd ~/Code/heroku-rails
$ git submodule add https://github.com/myusername/FooBar lib/FooBar
Cloning into 'lib/FooBar'...
remote: Counting objects: 26, done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 26 (delta 8), reused 19 (delta 5)
Unpacking objects: 100% (26/26), done.
これにより FooBar
と呼ばれる新しいサブモジュールが作成されて、ライブラリのソースツリー全体を持つ FooBar
ディレクトリを lib
アプリケーションディレクトリに置きます。
いったん Git サブモジュールがローカルで追加されたら、ご使用のアプリケーションリポジトリに対して新しいサブモジュール参照をコミットする必要があります。
$ git commit -am "adding a submodule for FooBar"
[master 314ef62] adding a submodule for FooBar
2 files changed, 4 insertions(+)
create mode 160000 FooBar
Heroku がデプロイの一環としてサブモジュールを適正に解決してフェッチします。
$ git push heroku
Counting objects: 13, done.
...
-----> Heroku receiving push
-----> Git submodules detected, installing Submodule 'FooBar' (https://github.com/myusername/FooBar.git) registered for path 'FooBar'
Initialized empty Git repository in /tmp/build_2qfce3fkvrug9/FooBar/.git/
Submodule path 'FooBar': checked out '667e0b5717631a8cca657a0aa306c045f06cfda4'
-----> Ruby/Rails app detected
...
サブモジュールをフェッチできないとビルドが失敗するので注意してください。
ご使用の言語の優先依存関係解決メカニズムが使用可能な場合は、使用することをお勧めします。サブモジュールを使用すると、混乱しやすく間違いが起きやすいからです。
Heroku でのビルドでサブモジュールを使用できるのは、Git プッシュによりトリガーされるビルドだけです。ビルドが API で作成された場合は、サブモジュールを解決しません。これは、GitHub 同期にも当てはまります。
保護された Git サブモジュール
参照される Git リポジトリがユーザー名とパスワードで保護される場合、サブモジュールで参照することも可能です。Heroku のようなリモート環境ではローカルで使用可能な証明書にアクセスできないので、ユーザー名とパスワードをリポジトリ URL に埋め込むことが必要になります。
たとえば、HTTP 基本認証 URL スキームを使用して FooBar
サブモジュールを追加するには、次のコマンドを実行します (username:password
トークンがあることに注意)。
$ git submodule add https://username:password@github.com/myusername/FooBar
これによりプライベートサブモジュール依存関係がアプリケーションに追加され、ローカルでない環境での解決が可能になります。
サブモジュール参照が .git/submodules
ディレクトリにプレーンテキストで保存されるので、これがセキュリティ要件に許容可能か検討してください。
ベンダリング
Git サブモジュールは外部ライブラリソースを迅速に参照する 1 つの方法ですが、ユーザーがよく遭遇するのはその更新ライフサイクルが微妙に異なるという問題です。サブモジュールの使い勝手が非生産的と思われる場合は、コードをプロジェクトにベンダリングすることができます。
数多くのフレームワークで使用可能な「ベンダー化した」コードは、参照ライブラリのソースをアプリケーションのソースツリーにコピーするだけです。
$ git clone <remote repo> /path/to/some/directory
$ cp -R /path/to/some/directory /app/vendor/directory
$ git add app/vendor/directory
このアプローチのマイナス面は、外部ライブラリが更新されると手動のダウンロードおよびコピープロセスが必要になることです。しかし、変化の速度が非常に遅い外部リソースの場合、あるいはこの外部リソースから変化を取り込みたくない場合、これはオプションです。
プライベート依存関係リポジトリ
非常に堅牢でスケーラブルな依存関係管理のアプローチは、プライベートのパッケージリポジトリを使用することです。Ruby、Python、Node.js の場合、これは Heroku で Gemfury アドオンによって使用可能になります。JVM ベース言語の場合、プライベートの S3 バケットを s3-wagon-private ツールで使用するのが簡単です。Heroku でカスタム buildpack 機能を使用して、依存関係をホスティングすることも可能です。
プライベートパッケージリポジトリでは、ご使用の言語の依存関係管理ツールを使用しながら、アクセスをご使用のアプリケーションや組織だけに限定することが可能です。これは参照パッケージをより広範に配布できるよう正しくパッケージングしなければならないという負担が生じますが、ご使用の言語の十分にサポートされ吟味された依存関係ツールセットの利点を生かす、はるかにスケーラブルなアプローチです。