Gitlab CI 拉取 submodules

Posted 麦田里的守望者-Jiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gitlab CI 拉取 submodules相关的知识,希望对你有一定的参考价值。

文章目录

前言

在项目开发中,有时需要使用另外一个项目(第三方或独立项目),这时可以通过 Git 工具 - 子模块 来管理。当在本地添加好子模块(git submodule add <project gitlab url>)并推送到 gitlab 上,我们期望 gitlab CI 能够自动的去 clone 或 pull 对应的 依赖项目并正常构建。但是,这时我们可能会遇到:

fatal: could not read Username for 'https://gitserver.com/ ': No such device or address

等问题,本篇文章将叙述如何 在 Gitlab 上正确的使用 submobules。

第一步,配置 .gitmodules 文件

方式一:官网提供

在 Gitlab CI/CD 使用 submodules,官网提供的方式:Using Git submodules with GitLab CI/CD,大概说了两点:

  1. 如果主项目和子项目(submodule)在同一个 gitlab server 下,比如,主项目地址:https://gitlab.com/android/android-main,子项目地址:https://gitlab.com/android/android-subhttps://gitlab.com/android/common-project/android-sub1,那么在.gitmodules文件可以使用 相对 url 地址 配置方式:
[submodule "android-sub"]
  path = android-sub
  url = ../../android-sub.git
  1. 如果主项目和子项目(submodule)在同一个 gitlab server 下,在.gitmodules文件可以使用 绝对 url 地址 配置方式:
[submodule "android-sub"]
  path = android-sub
  url = https://gitserver.com/group/android-sub.git

方式二:实际项目需要(推荐)

对于官网提供的方式,不管是主项目和子项目(submodule)在或不在同一个 gitlab server 下,子项目开放的成员(members)权限通常是收敛的,一个项目组中,可能只有部分人有 read 和 write 权限,而其他人只有 read 权限。

这时,就需要使用 Gitlab 提供的 Deploy tokens 来配置.gitmodules 文件。

关于 Deploy tokens 有两点:

  1. 由有项目权限 MaintainerOwner的成员负责 Deploy tokens 的管理(创建和删除) ;
  2. Deploy tokens 允许对项目 clone 或 push 或 pull,但是无需 账号和密码。

创建和配置 Deploy tokens

进入子项目,左侧菜单栏,打开settings/repository/deploy_tokens:

创建完成后,复制 usernamedeploy_token 来配置 .gitmodules 文件:

[submodule "android-sub"]
 path = android-sub
 url = https://<username>:<deploy_token>@gitserver.com/android/android-sub.git

使用这种方式,可以避免遇到 Gitlab CI/CD 权限问题。

第二步,配置 .gitlab-ci.yml 文件

在 Gitlab jobs 使用 submodules,官网提供的方式:Use Git submodules in CI/CD jobs,大概就是说:

  1. 确保子项目 和 主项目 在 同一个 gitlab server 上;
  2. .gitlab-ci.yml 文件 配置 GIT_SUBMODULE_STRATEGY:normal 或 recursive
variables:
  GIT_SUBMODULE_STRATEGY: recursive

配置 GIT_SUBMODULE_STRATEGY:normal 相当于执行:

# 将新的URL更新到文件.git/config
git submodule sync
# 从新 URL 更新子模块
git submodule update --init

配置 GIT_SUBMODULE_STRATEGY:recursive相当于执行:

# 将新的 URL 复制到本地配置中
git submodule sync --recursive
# 从新 URL 更新子模块
git submodule update --init --recursive

第三步,确保权限

在上面两个步骤中,需要确保执行上面命令的项目成员,在主项目和子项目中都有项目的 MaintainerOwner 权限。

遇到的问题

1.fatal: repository not found

如果 配置 .gitmodules 文件使用的是 相对 url 地址 配置方式,Gitlab CI 遇到

Synchronizing submodule url for 'android-sub '
Entering 'android-sub'
Entering 'android-sub'
HEAD is now at 5b2e725 Feat. ci submodule test
remote: The project you were looking for could not be found.
fatal: repository 'https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@gitlab/android-sub.git/' not found
Unable to fetch in submodule path 'android-sub'
stdin: is not a tty
ERROR: Job failed: exit status 1

这种是子项目和主项目的 相对 url 地址 不正确,比如,一个公司有两个项目:https://gitlab.com/android/project1/android-mainhttps://gitlab.com/android/project2/android-main,现在有一个公用子项目:https://gitlab.com/android/common-project/android-sub1,那么使用在主项目中 引入 公用子项目 的时候,使用的 相对 url 地址应该是:

[submodule "android-sub"]
  path = android-sub1
  url = ../../../android-sub.git

2.构建失败,找不到子项目的相关文件(类)

集成 submodule 后,第一次在 Gitlab 构建项目,遇到 找不到子项目的相关文件(类)导致构建失败。查看 job 控制台日志显示:

HEAD is now at 691bc88845 Feat. ci 拉取submodule 打包
From https://gitlab.com/android/android-main
 + 691bc88845...246c8cfd6f feature/2.3.0-wangjiang -> origin/feature/2.3.0-wangjiang  (forced update)
Checking out 246c8cfd as feature/2.3.0-wangjiang...
Updating/initializing submodules recursively...
Synchronizing submodule url for 'android-sub'
Cloning into '/home/gitlab-runner/builds/aWHpgegt/0/studio/android/android-sub'...
Submodule path 'android-sub': checked out 'd26c5afc724dde0b78a64c45b3333900b32a6cf9'

此时,只是表示 已经 clone 子项目到主项目,但是 clone 后的主项目中只含有子项目的根目录文件夹,文件夹里面没有下载任何 子项目(submodule)的文件。

解决此问题,可以在主项目编写一个脚本(算是双重校验)去执行命令:git submodule update --init --recursive,比如(Android 项目脚本):

    def repositoryPath = "android-sub"
    def repositoryFile = file(repositoryPath)
    def childFiles = repositoryFile.listFiles()
    if (!repositoryFile.exists() || childFiles == null || childFiles.length == 0) 
        def cmd = 'git submodule update --init --recursive'
        exec 
            ExecSpec execSpec ->
                executable 'bash'
                args '-c', cmd
        
    

另外,构建成功情况下,job 控制台日志应该显示:

HEAD is now at 0b26b59181 Feat. ci 拉取submodule 打包 test
Checking out 0b26b591 as feature/2。3.0-wangjiang...
Updating/initializing submodules recursively...
Synchronizing submodule url for 'android-sub'
Entering 'android-sub'
Entering 'android-sub'
HEAD is now at c8914ee Feat. Android todo list

表示此时已经执行了GIT_SUBMODULE_STRATEGY:recursive

3.权限问题

在 Gitlab 执行 pipeline ,读取子项目(submodule),遇到:

fatal: could not read Username for 'https://gitserver.com/': No such device or address
fatal: clone of 'https://gitserver.com/android/android-sub.git' into submodule path '/home/gitlab-runner/builds/hF55UpTC/0/studio/android/android-sub' failed
Failed to clone 'android-sub'. Retry scheduled
Cloning into '/home/gitlab-runner/builds/hF55UpTC/0/studio/android/android-sub''...
fatal: could not read Username for 'https://gitserver.com/'': No such device or address
fatal: clone of 'https://gitserver.com/android/android-sub.giit' into submodule path '/home/gitlab-runner/builds/hF55UpTC/0/studio/android/android-sub' failed
Failed to clone 'android-sub' a second time, aborting
stdin: is not a tty
ERROR: Job failed: exit status 1

这是项目权限问题,把执行主项目的权限给对应的子项目也添加上,权限至少是 MaintainerOwner 。或者 使用 第一步,配置 .gitmodules 文件 中的 方式二.gitmodules 文件 进行配置。

以上是关于Gitlab CI 拉取 submodules的主要内容,如果未能解决你的问题,请参考以下文章

问:Gitlab CI 谁重试旧管道

在gitlab-ci.yml中`git clone project2`?

gitlab-ci docker-in-docker 访问不安全的注册表

[ci] 构建触发器,实现当gitlab有push动作时候,jenkins自动拉代码.

Jenkins + Gitlab + harbor + Kubernetes实现CI/CD

Jenkins + Gitlab + harbor + Kubernetes实现CI/CD