在 GitLab CI/CD 中使用 Git 子模块
- Tier: 免费版、高级版、旗舰版
- Offering: GitLab.com、GitLab 自托管、GitLab 专属托管
使用 Git 子模块 可以将一个 Git 仓库作为另一个 Git 仓库的子目录。你可以将另一个仓库克隆到你的项目中,并保持提交记录的独立性。
配置 .gitmodules 文件
当你使用 Git 子模块时,你的项目应该有一个名为 .gitmodules 的文件。你有多种选项来配置它以在 GitLab CI/CD 作业中工作。
使用绝对 URL
例如,如果你的项目位于 https://gitlab.com/secret-group/my-project,并且你的项目依赖于 https://gitlab.com/group/project(你想将其作为子模块包含),你使用类似 git@gitlab.com:secret-group/my-project.git 的 SSH 地址检出源代码,那么生成的 .gitmodules 配置可能如下所示:
[submodule "project"]
path = project
url = git@gitlab.com/group/project.git在这种情况下,使用 GIT_SUBMODULE_FORCE_HTTPS 变量来指示 GitLab Runner 在克隆子模块之前将 URL 转换为 HTTPS。
或者,如果你本地也使用 HTTPS,可以配置一个 HTTPS URL:
[submodule "project"]
path = project
url = https://gitlab.com/group/project.git在这种情况下,你不需要配置额外的变量,但需要使用 个人访问令牌 在本地克隆它。
使用相对 URL
如果你使用相对 URL,在分叉工作流程中子模块可能无法正确解析。 如果你的项目可能会有分叉,请使用绝对 URL。
当你的子模块位于同一个 GitLab 服务器上时,你还可以在 .gitmodules 文件中使用相对 URL:
[submodule "project"]
path = project
url = ../../project.git上述配置指示 Git 在克隆源代码时自动推断要使用的 URL。你可以在所有 CI/CD 作业中使用 HTTPS 克隆,同时继续使用 SSH 在本地克隆。
对于不在同一 GitLab 服务器上的子模块,始终使用完整 URL:
[submodule "project-x"]
path = project-x
url = https://gitserver.com/group/project-x.git在 CI/CD 作业中使用 Git 子模块
先决条件:
- 如果你在流水线作业中使用
CI_JOB_TOKEN克隆子模块,你必须拥有子模块仓库至少 Reporter 角色,才能拉取代码。 - 上游子模块项目必须正确配置 CI/CD 作业令牌访问。
要让子模块在 CI/CD 作业中正常工作:
-
你可以将
GIT_SUBMODULE_STRATEGY变量设置为normal或recursive,以指示运行器在作业开始前获取你的子模块:variables: GIT_SUBMODULE_STRATEGY: recursive -
对于位于同一 GitLab 服务器上且配置了 Git 或 SSH URL 的子模块,确保设置
GIT_SUBMODULE_FORCE_HTTPS变量。 -
使用
GIT_SUBMODULE_DEPTH来独立配置子模块的克隆深度,与GIT_DEPTH变量无关:variables: GIT_SUBMODULE_DEPTH: 1 -
你可以使用
GIT_SUBMODULE_PATHS过滤或排除特定子模块,以控制哪些子模块被同步:variables: GIT_SUBMODULE_PATHS: submoduleA submoduleB -
你可以使用
GIT_SUBMODULE_UPDATE_FLAGS提供额外的标志来控制高级检出行为:variables: GIT_SUBMODULE_STRATEGY: recursive GIT_SUBMODULE_UPDATE_FLAGS: --jobs 4
故障排除
找不到 .gitmodules 文件
.gitmodules 文件可能难以找到,因为它通常是隐藏文件。你可以查看特定操作系统的文档,了解如何查找和显示隐藏文件。
如果没有 .gitmodules 文件,子模块设置可能在 git config 文件中。
错误:fatal: run_command returned non-zero status
在使用子模块且 GIT_STRATEGY 设置为 fetch 时,作业中可能会发生此错误。
将 GIT_STRATEGY 设置为 clone 应该可以解决问题。
错误:fatal: could not read Username for 'https://gitlab.com': No such device or address
如果你使用 GitLab 托管的运行器,当你的 CI/CD 作业尝试克隆或获取 Git 子模块时,可能会遇到此错误。
在 CI/CD 流水线执行期间,GitLab 运行器会自动执行 Git URL 替换来通过 CI_JOB_TOKEN 进行身份验证:
git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_FQDN}".insteadOf "${CI_SERVER_FQDN}"对于 GitLab 托管的运行器,CI_SERVER_FQDN 与 https://gitlab.com 不同。如果你的子模块位于 https://gitlab.com,则不会执行此替换,从而导致错误。
解决此错误的一种方法是创建 pre_get_sources_script 并手动配置使用 CI_JOB_TOKEN 的 URL 替换:
variables:
GIT_SUBMODULE_STRATEGY: recursive
GIT_SUBMODULE_DEPTH: 1
hooks:
pre_get_sources_script:
- git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_FQDN}".insteadOf "${SUBMODULE_URL}"