将多个 git 存储库签出到同一个 Jenkins 工作区

Posted

技术标签:

【中文标题】将多个 git 存储库签出到同一个 Jenkins 工作区【英文标题】:Checkout multiple git repos into same Jenkins workspace 【发布时间】:2013-01-28 10:00:57 【问题描述】:

使用 Jenkins 1.501 和 Jenkins Git 插件 1.1.26

我有 3 个不同的 git repos,每个都有多个项目。

现在我需要将 3 个 git 存储库中的所有项目检出到 Jenkins 从站的同一个工作区中。我在 Source code Management: Multiple SCMs 中定义了每个 git repo。但是每次签出一个 repo 时,前一个 repo(及其相关项目)都会被删除。

我已阅读:

http://jenkins.361315.n4.nabble.com/multiple-git-repos-in-one-job-td4633300.html

但它并没有真正的帮助。我尝试在 Local subdirectory for repo (optional) 下为所有 repos 指定相同的文件夹,但结果相同。

如果使用 Jenkins 根本不可能做到这一点,我想可以使用一些预构建步骤/脚本将项目移动到正确的位置。它不是修改项目构建配置的选项。

【问题讨论】:

【参考方案1】:

使用 Jenkins + Git 插件无法在一个工作区中一次签出多个 repo。

作为一种解决方法,您可以拥有多个上游作业,每个作业签出一个 repo,然后复制到您的最终项目工作区(在多个级别上存在问题),或者您可以设置一个 shell 脚本步骤来签出每个在构建时需要 repo 到作业工作区。

以前,Multiple SCM 插件可以帮助解决此问题,但现在已弃用。来自多 SCM 插件页面:“用户应该迁移到 https://wiki.jenkins-ci.org/display/JENKINS/Pipeline+Plugin。管道提供了一种更好的方式来签出多个 SCM,并得到 Jenkins 核心开发团队的支持。”

【讨论】:

为什么第一种方法有问题?拆分工作似乎是一种很好的做法。 一般来说这是一个很好的做法,但是当您需要在同一个物理位置进行多次结账时,维护就成了一个大问题。例如,如果您想创建一个分支构建,则必须克隆 4 个作业,然后单独更改每个作业的路径。当然有插件可以帮助解决这个问题,但是从单个作业中签出到相对路径会更容易。然后,您可以在不更改设置的情况下随意克隆。 您需要从正确答案中更改它,因为它不再相关。 管道要求您学习一种新的 DSL,这对于我们希望它完成的非常简单的工作(检查来自多个存储库的代码)来说有点太多了。坚持使用 Multiple SCM 插件,直到 Jenkins 管道 DSL 周围出现一个像样的 GUI。我可以报告它在 Jenkins 2.17 上运行良好 我刚刚遇到了多个 repos 的相同问题。我现在正在使用 Pipeline 插件,尽管我和 @BurakArslan 一样对新的 DSL 持怀疑态度。它实际上并没有我想象的那么糟糕,并且配备了一个相当不错的 sn-p 生成器。在使用它仅 2 小时后,我现在实际上更喜欢这种方法,因为我最终可以将管道构建脚本与其余代码一起提交到 git。【参考方案2】:

我将Multiple SCMs Plugin 与 Jenkins 一起成功使用了 Git 插件。

【讨论】:

谢谢,太好了,我可以将 2 个 bitbucket 路径放入存储库部分,现在我如何告诉 repo 1 checkout "develop" 分支和 repo 2 checkout "fixes" 分支?我在 jenkins 中看到要构建部分的分支,我如何在分支说明符中设置存储库名称和 Refsec(“任何”为空白),以便每个都可以检查出我想要的相应分支?或者我做错了,我应该点击显示“多个 SCM”的布尔值? @pelos 你找到解决方案了吗? 目前我们没有使用 yml 文件,我们使用常规任务执行了两个不同的工作流【参考方案3】:

使用多 SCM 插件:

为您需要签出的每个存储库(主项目或依赖项目)创建不同的存储库条目。

对于每个项目,在“高级”菜单中(第二个“高级”菜单,每个存储库都有两个标记为“高级”的按钮),找到“本地 repo 子目录(可选)”文本字段。您可以在“工作区”目录中指定要将项目复制到的子目录。您可以映射我的开发计算机的文件系统。

“第二个高级菜单”不再存在,需要做的是使用“添加”按钮(在“其他行为”部分),然后选择“签出到子目录”

如果您使用的是 ant,就像现在带有构建目标的 build.xml 文件不在工作区的根目录中而是在子目录中一样,您必须在“Invoke Ant”配置中反映这一点。为此,在“Invoke ant”中,按“高级”并填写“构建文件”输入文本,包括 build.xml 所在的子目录的名称。

希望对您有所帮助。

【讨论】:

这一定是过时的。在编写多个 SCM 插件时,GIT sn-p 不包含可选的子路径。 在每个存储库中都有一个名为“添加”的下拉列表。您可以在其中找到“结帐到子目录”选项,该选项执行相同的操作。 我按照您的指南使用了多个 SCM 插件和 git,但我还有另一个有趣的问题。它似乎不想为不同的存储库正确签出相同的分支(开发)。它尝试通过哈希检查提交(仅在第一个存储库中有效)。关于如何解决这个问题的任何想法? 多个 SCM 插件最大的问题是:“post-commit 类型的触发器目前不起作用(至少对于 subversion),因此需要配置 'cron' 类型的轮询。” 管道要求您学习一种新的 DSL,这对于我们希望它完成的非常简单的工作(检查来自多个存储库的代码)来说有点太多了。坚持使用 Multiple SCM 插件,直到 Jenkins 管道 DSL 周围出现一个像样的 GUI。我可以报告它在 Jenkins 2.17 上运行良好【参考方案4】:

我们正在使用git-repo 来管理我们的多个 GIT 存储库。还有一个 Jenkins Repo plugin 允许将 git-repo 管理的全部或部分存储库检出到同一个 Jenkins 作业工作区。

【讨论】:

你是如何解决这个问题中提出的问题的?我已经安装了你提到的插件,并阅读了关于 repo 和插件的信息,但是我看不到如何设置 Jenkins 来克隆两个 repos 以在一个项目中执行...... 为了使用 Repo,需要创建一个只包含清单文件的特殊存储库。在此文件中,您指定有关其他存储库的所有信息。清单文件的确切格式在 git-repo 项目 (gerrit.googlesource.com/git-repo/+/master/docs/…) 的 docs/manifest-format.txt 文件中进行了描述。在配置 Jenkins Repo 部分作业时 - 您指定“清单”存储库的位置以及可选的“清单”文件的名称(您可能有多个)。清单中指定的所有存储库都将被克隆。【参考方案5】:

根据存储库的关系,另一种方法是将另一个存储库(存储库)作为git submodules 添加到其中一个存储库。一个 git 子模块创建对其他 repos 的引用。除非您在克隆 "superproject"(官方术语)时指定 --recursive 标志,否则不会克隆这些子模块存储库。

这是在当前项目中添加子模块的命令:

git submodule add <repository URI path to clone>

我们正在使用 Jenkins v1.645,git SCM 将为超级项目进行开箱即用的递归克隆。瞧,您可以在同一个 Jenkins 作业工作区中各自的目录中获得超级项目文件和所有依赖(子模块)repo 文件。

不保证这是正确方法,而是一种方法。

【讨论】:

如何将子模块更改为不同的分支?我想设置 jenkins 在创建 PR 的任何分支上运行测试。【参考方案6】:

因为Multiple SCMs Plugin 已被弃用。

使用Jenkins Pipeline 可以签出多个 git 存储库并在使用 gradle 构建它之后

node    
def gradleHome

stage('Prepare/Checkout')  // for display purposes
    git branch: 'develop', url: 'https://github.com/WtfJoke/Any.git'

    dir('a-child-repo') 
       git branch: 'develop', url: 'https://github.com/WtfJoke/AnyChild.git'
    

    env.JAVA_HOME="$tool 'JDK8'"
    env.PATH="$env.JAVA_HOME/bin:$env.PATH" // set java home in jdk environment
    gradleHome = tool '3.4.1' 


stage('Build') 
  // Run the gradle build
  if (isUnix()) 
     sh "'$gradleHome/bin/gradle' clean build"
   else 
     bat(/"$gradleHome\bin\gradle" clean build/)
  


您可能需要考虑使用git submodules 而不是这样的自定义管道。

【讨论】:

谢谢!!! dir 块是关键,我不明白为什么我只在工作的工作区中看到最近克隆的 repo。 在多个 SCM 下如何考虑“更改”的概念?它只是从构成工作的所有回购中看到的变化的总和吗?如果可能的话,最好将它们逐条列出,23 changes from repo XXX, 3 changes from repo YYY 或沿着这些线更紧凑的东西。 我正在使用 git 子模块,但是当在多个存储库中的任何一个上创建新 PR 时,我需要更改分支。知道如何实现吗? @ArnoldRoa 不确定您的设置。假设您有 github,当创建 pr 时,您将有一个 webhook 事件 - 在这种情况下,该 pr 的分支在事件中提供(或至少某种 ref)。因此,您可以简单地获取该事件的分支名称。不过,Havent,试过了。【参考方案7】:

詹金斯: 多个 SCM - 已弃用。 GIT 插件 - 不适用于多个存储库。

脚本/管道即代码 - 是要走的路。

【讨论】:

【参考方案8】:

我也有这个问题。我在其他项目上使用触发器/调用构建解决了它。对于每个存储库,我使用参数调用下游项目。

主要项目:

This project is parameterized
String Parameters: PREFIX, MARKETNAME, BRANCH, TAG
Use Custom workspace: $PREFIX/$MARKETNAME
Source code management: None

然后对于每个存储库,我都会像这样调用下游项目:

Trigger/call builds on other projects: 
Projects to build: Linux-Tag-Checkout
Current Build Parameters
Predefined Parameters: REPOSITORY=<name>

下游项目:Linux-Tag-Checkout:

This project is parameterized
String Parameters: PREFIX, MARKETNAME, REPOSITORY, BRANCH, TAG
Use Custom workspace:$PREFIX/$MARKETNAME/$REPOSITORY-$BRANCH
Source code management: Git
git@<host>:$REPOSITORY
refspec: +refs/tags/$TAG:refs/remotes/origin/tags/$TAG
Branch Specifier: */tags/$TAG 

【讨论】:

【参考方案9】:

使用 Jenkins + Git 插件可以在单个工作区中一次签出多个 repo(可能仅在较新的版本中?)。

在“Source-Code-Management”部分,不要选择“Git”,而是选择“Multiple SCMs”并添加多个git repositories。

请确保除了一个作为“附加行为”之外的所有操作都添加了“签出到子目录”操作并指定一个单独的子目录。

【讨论】:

我相信您使用的是(已弃用的)Multiple SCM 插件而不是普通的 Git 插件。

以上是关于将多个 git 存储库签出到同一个 Jenkins 工作区的主要内容,如果未能解决你的问题,请参考以下文章

在 Jenkins 中,如何将项目签出到特定目录中(使用 GIT)

将所有项目签出到某个分支

无法从GitHub分叉存储库签出分支

使用 GIT 如何将不同提交中的文件签出到新分支中? [复制]

Jenkins无法签出Git存储库 - 主机密钥验证失败

git-svn 的钩子