GitLab CI で Git サブモジュールを使う

注:

  • GitLab 8.12 では新しいCI ジョブの権限モデルが導入されました。まだ GitLab インスタンスをアップグレードしていない場合は、アップグレードすることをお勧めします。 GitLab 8.12 以降を使用していない場合は、SSHキーを使ってgitlab.com/group/projectなどのソースにアクセスするためにサブモジュールを使いこなす必要があります。
  • GitLab 8.12 以降では、CI ジョブが何にアクセスできるかを評価するために権限が使われます。 このシステムがどのように機能するかについての詳細は、ジョブ権限モデルをご覧ください。
  • HTTP(S) GitプロトコルがGitLabインスタンスで有効になっている必要があります

.gitmodules ファイルの設定

gitサブモジュールを扱う場合、プロジェクトにはおそらく.gitmodulesという名前のファイルがあるでしょう。

次の例を考えてみましょう。

  1. あなたのプロジェクトはhttps://gitlab.com/secret-group/my-projectにあります。
  2. ソースをチェックアウトするには、通常git@gitlab.com:secret-group/my-project.gitのような SSH アドレスを使用します。
  3. あなたのプロジェクトはhttps://gitlab.com/group/projectに依存しています。 はサブモジュールとしてインクルードしたいものです。

GitLab 8.12+ を使っていてサブモジュールが同じ GitLab サーバー上にある場合は、.gitmodules 相対 URL を使うようにファイルを .gitmodules更新しなければなりません.gitmodules 。 Git では .gitmodules設定に.gitmodules 相対 URL .gitmodulesを使うことができるので、すべての CI ジョブのクローンには HTTP(S) を使い、すべてのローカルチェックアウトには SSH を使うことができます。.gitmodules は次のようになります:

[submodule "project"]
  path = project
  url = ../../group/project.git

上記の設定は、ソースをクローンするときに使うべきURLを自動的に推測するようにGitに指示します。 HTTP(S) を使ってもSSHを使っても、Gitは同じチャンネルを使うので、すべてのCIジョブにHTTP(S)を使わせることができ(GitLab CI/CDはソースのクローンにはHTTP(S) しか使わないからです)、内部クローンにはSSHを使い続けることができます。

同じ GitLab サーバーにない他のサブモジュールには、完全な HTTP(S) プロトコルの URL を使ってください:

[submodule "project-x"]
  path = project-x
  url = https://gitserver.com/group/project-x.git

.gitmodules が正しく設定されたら、.gitlab-ci.ymlの設定に移ります。

CI ジョブで Git サブモジュールを使う

サブモジュールをCIジョブで正しく動作させるには、いくつかの手順を踏む必要があります:

  1. まず、同じ GitLab サーバーにあるサブモジュールに相対 URL を使っていることを確認しましょう。
  2. 次に、gitlab-runner v1.10+を使用している場合、GIT_SUBMODULE_STRATEGY 変数をnormal またはrecursive のいずれかに設定することで、ジョブの前にサブモジュールを取得するようランナーに指示することができます:

    variables:
      GIT_SUBMODULE_STRATEGY: recursive
    

    GIT_SUBMODULE_STRATEGYの詳細については、.gitlab-ci.yml リファレンスをご覧ください。

  3. 古いバージョンのgitlab-runnerを使用している場合は、before_scriptgit submodule sync/update を使用してください:

    before_script:
      - git submodule sync --recursive
      - git submodule update --init --recursive
    

    --recursive は、再帰的なサブモジュールがあるかどうかによって、 both または none (sync/update) のどちらかで使う必要があります。

before_scriptsyncupdate を設定する根拠は、Git サブモジュールの仕組みにあります。新しい Runner のワークスペースでは、Git は.gitmodules と現在のリモート URL に基づいて.git/config(あるいは.git/modules/<submodule>/config) にトークンを含むサブモジュールの URL を設定します。同じ Runner の後続のジョブでは、.git/config がキャッシュされ、前のジョブに対応するサブモジュールの完全な URL と前のジョブのトークンがすでに含まれています。sync を使うと、完全な URL を強制的に更新することができます。