アプリケーション依存関係を Git サブモジュールで解決する
最終更新日 2024年05月09日(木)
Table of Contents
多くの最新のアプリケーションはサードパーティ製ライブラリに大きく依存しているため、これらの依存関係をアプリケーションリポジトリの中で指定する必要があります。RubyGems、Java の Maven、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"
[main 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
このアプローチのマイナス面は、外部ライブラリが更新されると手動のダウンロードおよびコピープロセスが必要になることです。しかし、変化の速度が遅い外部リソースや、変化を取り込みたくない外部リソースの場合は、このアプローチは選択肢の 1 つになります。
プライベート依存関係リポジトリ
依存関係管理の堅牢でスケーラブルなアプローチは、非公開のパッケージリポジトリを使用することです。Ruby、Python、Node.js の場合、このリポジトリは Heroku で Gemfury アドオンで入手可能です。JVM ベースの言語の場合、プライベート S3 バケットを s3-wagon-private ツールで使用できます。もう 1 つの選択肢は、カスタム buildpack 機能を使用して Heroku で依存関係をホストすることです。
プライベートパッケージリポジトリでは、ご使用の言語の依存関係管理ツールを使用しながら、ご使用のアプリケーションや組織にのみアクセスを限定できます。このアプローチは参照パッケージをより広範に配布できるように適切にパッケージ化するという負担が生じます。しかし、使用している言語の十分にサポートされ精査された依存関係ツールセットの利点を生かす、はるかにスケーラブルなアプローチです。