2

一点背景...

我们已经使用 Gerrit + Jenkins 一年多了,取得了巨大的成功。添加代码审查和构建验证使我们的开发人员对他们提交到源代码的内容更加负责。当我们的项目开始时,我为我的团队设置了两者之间的集成。

现在,我希望能够为使用 Gerrit 进行代码审查的库进行多分支构建。一旦 CR 通过经过验证的构建并且更改使其成为源代码,我希望进行分发构建(Gerrit 触发器可以侦听此事件)。

简单示例

我在下一节中写了一个详细而具体的示例来说明我正在尝试做的事情

为了便于交流我正在尝试做的事情,我将参考项目 A 和库 B。两者都在 Gerrit 中用于 CR 和构建验证。这为我们分发的每个分支提供了 2 个 Gerrit 触发构建以及每晚构建。

图书馆 B 被项目 A 使用(通过凉亭)。当用户向库项目提交更改时,Gerrit 触发器会选择此更改,然后 Jenkins 会构建更改。审核并提交更改后,将手动启动 dist 构建。然后,此构建更新包中的 dist。这将在项目 A 的下一个版本(或当用户手动更新 bower 时)中得到支持。

一个更详细的例子

我们创建了一个库,它是一组可消耗的通用样式和 JavaScript,可以在我们组织的不同 Web 应用程序项目中使用。我们尝试尽可能多地创建大多数人都熟悉的 bower.io 包(我们模仿 Bootstrap)。该库的 git 分支布局旨在模仿 gitflow;开发分支总是下一个版本,等等。

该库有一个src/包含所有基本代码等的文件夹。该bower.json文件指向一个dist/包含已编译、缩小等文件的文件夹。正是通过这个设置,我们在我们的 Web 应用程序中使用了这个包。

使用 Gerrit,我们审查了我们团队为此项目提交的所有提交。这相当容易。带有 Gerrit-Trigger 的 Jenkins 会收到有关新更改的通知并构建补丁集。我们告诉开发人员不要在文件夹中提交更改,dist/因为它会带来合并的噩梦,但是文件在那里,因此库的每个使用者都不必进行编译输出。

在这一点上,希望对我们正在做的事情有一个很好的高级视图。现在可能更容易解释这个问题。

当我们为我们的主要 Web 应用程序的 QA 团队进行日常构建时,我们会做bower install. 在我们的 bower.json 文件中,我们指向#developref。这意味着 Web 应用程序将使用库dist/文件夹中最新的内容。dist/如果在 Web 应用程序的每日 QA 构建之前尚未完成对更新文件夹的库的提交,则该库实际上不会在该构建中更新。

这让 QA 很难过。他们向开发人员发送一封电子邮件,说明已关闭的票证实际上还没有准备好进行测试。这让我很沮丧,因为我又收到了一封来自开发人员的电子邮件,询问 WTF。

我希望发生的事情

  1. 为每个项目定义一个多分支管道构建,以便每个分支不需要自己的每日/每晚构建作业。
  2. 对于库作业,除了用于夜间构建的管道外,它还会在补丁集提交到源代码时启动。

特别是关于第 2 点和上述详细示例:我希望以dist/受控方式自动更新文件夹,而无需开发人员交互,并且每当潜在客户向源提交批准的补丁集时。

对于第 1 点和关于这个问题,我不是在为项目 A 构建管道构建寻求帮助。

问题

我为库项目创建了一个多分支管道。在其中我想提取源代码:

try {
  stage('Checkout') {
    // Grab the source to build
    checkout scm
  }
}
catch (err) {
  currentBuild.result = "FAILURE"

  emailext body: "The Library build has failed. The source for the build was unable to be pulled from Gerrit. Please view the build information here: ${env.BUILD_URL}",
  from: 'Jenkins CI Server <jenkins-no-reply@example.com>',
  subject: 'Git Pull Issue With foundation-controls',
  to: 'Mike@example.com'

  throw err;
}

这行得通!但是,它只是为分支提取最新的。它没有定义构建发生的时间。我打开了 SCM 轮询。

构建完成后,我有一个步骤可以执行此操作:

stage('Publish') {
  if (env.BRANCH_NAME == "master" || env.BRANCH_NAME == "develop" || env.BRANCH_NAME.startsWith("release/") || env.BRANCH_NAME.startsWith('hotfix/')) {

    sh 'git add dist'
    def gitDiffStatusCode = sh script: 'git diff --cached --exit-code', returnStatus: true

    if (gitDiffStatusCode != 0)  {
      sh 'git commit -m "chore(release): Internal release"'
      sshagent(['xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx']) {
        sh "git push --force-with-lease origin HEAD:${env.BRANCH_NAME}"
      }
    } else {
      echo 'Nothing to commit';
      sendEmail = false
    }
  }
  else if (env.BRANCH_NAME.startsWith('feature/')) {
    echo "On A feature branch. Not publishing!"
    sendEmail = false
  }
  else {
    echo "Skipping publish - This build is not ocurring on a publish-able branch!"
    sendEmail = false
  }
}

这里的问题是推送导致轮询触发并进入无限循环。

我想做的是使用 Gerrit-Trigger 的能力在合并更改/补丁时触发构建(提交已发生)。我希望它不是一个自由形式的工作,而是一个管道构建,以便它利用 Jenkins 文件。

我怎样才能让它工作,以便 Gerrit 触发器告诉何时进行构建?

其他解决方法尝试

我确实想出了一种跳过构建的方法。它涉及在构建运行时查看最后的提交消息。然后我可以跳过管道中的所有其他步骤。这只是意味着总会有两个构建,一个包含所有管道步骤,然后一个仅包含“Checkout”阶段。不理想。

4

1 回答 1

0

我认为您正在创建一个经典的无限事件循环。但问题如下。

我可能错了,但是您将 git 用作源代码控制和工件存储库,即您正在添加可能已构建的 Python 包并将其推送到同一个存储库。

这意味着您至少必须将触发器推送到您忽略的特殊分支。

我认为流程应该是: 1. 在测试特定构建之后,您应该使用标签来标记提交。2. 单独的作业将对添加的正则表达式匹配标签做出反应并构建一个包。另一个步骤是将包推送到 kosher pypi 索引中,如果你需要学习如何,互联网上到处都是

因此,在我看来,问题在于您使用 Gerrit + CI 的方式,

我最初担心你真的需要做那些 git push 操作,但你不需要。

所以你的行动项目是一个:

决定是否要

  • 临时解决方案(单独的分支)

  • 真正的解决方案:将你的包放入 pypi 兼容的服务器

在任何一种情况下,你都会有几个 groovy 文件。

于 2017-07-14T14:52:24.500 回答