如何将一个 git 存储库的构建输出集成到另一个存储库中

How to integrate build output from one git repo into another

我正在处理存储在 2 个 git 项目 1 和项目 2 中的 2 个项目

Project1 是一个java脚本项目。它有自己的回购协议(例如 https://github.com/gandra/project1.git
Project2 是一个 java Maven 项目。它有自己的回购协议(例如 https://github.com/gandra/project2.git

这是我想要改进的当前工作流程:

  1. 提交 Project1 中的更改并将其推送到原点
  2. 运行 项目 1 中的 grunt。这会生成 Project1/build 目录
  3. 手动复制 Project1/build 内容到 Project2/libs/project1-lib 目录
  4. 在 Project2
  5. 中提交更改(Project2/libs/project1-lib)
  6. 运行k jenkins 构建和部署

我想以某种方式避免第 3 步(手动将 Project1/build 内容复制到 Project2/libs/project1-lib 目录中) 我考虑过将 Project1 作为子树集成到 Project2 中,但这种方法的问题是因为它将所有 Project1 目录结构放入 Project2/libs/project1-lib 而我只想获取 Project1 的子目录 (Project1/build/*)

一些重要说明: Project1 更改仅发生在其自己的存储库 (https://github.com/gandra/project1.git) 中,并且此更改应传播到 Project2。所以 Project2/libs/project1-lib 没有更新 Project1 换句话说:
- Project1 中的提交会影响 Project2
- 项目 2 中的提交不会影响项目 1

如果您控制正在使用的 Git 服务器,那么您可以使用 post-receive server-side hook.

来完成您的要求

但是,我不禁觉得应该有比将更改从 Project1 推送到 Project2 更好的方法。很明显,Project1 是 Project2 的依赖项。我更习惯于使用 Maven 和 Gradle:

来处理依赖关系
  • 让 Project1 的构建工具(例如 Gradle)将构建工件发布到构建工件存储库(例如 Artifactory)中。
  • 让 Project2 的构建工具根据需要从构建工件存储库中提取最新的工件。

我认为这种方法的优点是:

  • Project1 独立于 Project2。由于是 Project2 需要 Project1(反之亦然),因此保持 Project2 更新不应该是 Project1 的责任。
  • Project2 控制它使用 Project1 的方式。例如,您可以自由地冻结某个 Project1 版本的依赖项(例如,因为 Project1 当前已损坏并且您希望继续开发 Project2 而无需等待修复)。
  • 您不会用与 Project2 的源代码无关的更改污染 Project2 的提交。如果每次更新 Project1 时,您都会在 Project2 中获得新的提交,很快就会让您在合并、变基、平分或您通常必须做的任何其他事情时变得困难。

缺点主要在于基础设施要求(突然间您需要另一台服务器)以及选择和配置您的构建工具。当谈到 Java 时,我会推荐 Gradle 用于构建工具和 Artifactory 用于构建工件存储库。但是你说你的 Project1 是 Javascript 而我没有在那个生态系统中工作过,所以我在那里没有什么好的建议。

编辑:我刚刚意识到我混淆了 Project1 和 Project2。问题说 Project2 消耗了 Project1,而我最初的回答写得好像 Project1 消耗了 Project2。我现在解决了这个问题,以避免混淆。

您是否考虑过 Gradle 而不是 Maven?

https://blog.oio.de/2014/10/24/handling-javascript-dependencies-with-gradle/

沃伊斯拉夫说的是对的。这两个项目的构建(以您描述的方式)应该是分离的。如果最终产品需要这两个组件,那么构建应用程序的工作就是构建工具 (jenkins) 的工作。这两个项目应该完全不可知。

我有一段时间没有使用 Jenkins 但在 Bamboo 中我有一个名为 BuildProduct 的任务,它有两个任务(构建项目 1)和(构建项目 2),其中项目 2 的构建将使用第一次构建的结果(构建的 JS)。

好的,让我们在这里回顾一下最重要的事实:

  1. Project2 是 maven 项目(可能带有 war 打包,因为您将部署它)。
  2. Project2 在某种程度上依赖于 Project1,它期望他的输出构建在路径 Project2/libs/project1-lib

在我看来构建(甚至部分构建)并不意味着在任何源代码管理下,所以我不会保留 Project2 的任何路径,如 Project2/libs/project1-lib 在 git 下. Maven war 插件有这个不错的功能 maven-war-plugin-overlays。 因此,如果 Project2 将 Project1 视为具有 war 类型 packaginig 的 Maven 依赖项,例如

  <dependencies>
    ...
    <dependency>
      <groupId>your.group.id</groupId>
      <artifactId>project1</artifactId>
      <version>1.0-SNAPSHOT</version>
      <type>war</type>
      <scope>runtime</scope>
    </dependency>
    ...
  </dependencies>

,您不必对 Project2/libs/project1-lib 位置做任何处理,因为 Maven 会在打包阶段为您做这件事。 但是要做到这一点,您必须将 Project1 的 war 工件安装到您的关系中。 这里有几个解决方案:

解决方案 1)

  1. 使 Project1 成为完整的 maven 项目,并确保构建的输出在他的 war 中的路径 ./libs/project1-lib 上完成。 由于 Project1 现在将使用 maven 构建,因此您必须集成 Project1 的先前构建工具(grunt,gulp 或任何一个),以便在打包阶段之前的某个阶段由 maven 调用。
  2. 在 Project2 中添加这样的新依赖项:

    <dependency>
      <groupId>your.group.id</groupId>
      <artifactId>project1</artifactId>
      <version>1.0-SNAPSHOT</version>
      <type>war</type>
      <scope>runtime</scope>
    </dependency>
    

解决方案 2).

  1. 使用您当前的 Project1 构建器,确保将您的项目打包到具有以下结构的 war 中。/libs/project1-lib。 使用相同的构建器将其作为 war 工件安装在你的 nexus 上(注意:你必须在你的 nexus 上安装 pom.xml 以便其他项目可以引用 Project1) 如果你幸运地使用 grunt 作为 js 构建器,那么这个 npm 组件 grunt-nexus-deployer 将完全按照我在这里描述的进行操作。
  2. 与解决方案 1) 相同...

解释:

当您推送对 Project1 的更改时,您的 CI 将触发作业,该作业将在您的 nexus 上安装 project1-1.0-SNAPSHOT.war 完成后,将触发 Project2 的 CI 作业,它将拥有构建 project2 所需的一切。

注意: 在这两种解决方案中,删除 Project2/libs/project1-lib 层次结构,因为它不再使用...

编辑:

对于解决方案2)也许你应该使用grunt-maven-tasks而不是grunt-nexus-deployer因为它有更多的选择并且更合适。