Jenkins 和 gradle - 使用最新版本的 CI 依赖项构建项目,特定版本用于生产

Jenkins and gradle - build projects with latest versions of dependencies for CI, specific versions for production

我正在使用 Jenkins、Gradle 和我们的 Ivy 存储库。

我们的构建脚本指定了用于构建的依赖项的确切版本。这是生产的好习惯。

对于 CI 如果项目构建使用我们自己的库的最新版本会很有趣,这样我们不仅可以看到库是否更改 "broke the build" 还可以看到它们是否破坏了使用它们的项目。这似乎是 "integration"!

的重点

我知道 gradle 将采用 "1.+" 而不是 "1.2.3" 所以我可以破解 CI 服务器上的项目的 build.gradle 来实现这个。但也许有一种更简洁的方法(构建脚本识别它处于 CI 模式并使用最新而非特定版本,也许通过 运行 build.gradle 上的 sed 脚本来更改它).

我是否遗漏了 Jenkins 或 gradle 中的某些内容?是否有任何 gradle 插件可以实现此目的,或者您使用过其他方法来实现此目的?

如果你想拥有最新的,你可以简单地使用 latest,或者如果它更容易像 [1.0,) 这样的东西会匹配所有大于或等于 1.0 的版本(假设 1.0 是你的 "smallest version ever") 看here for other matching patterns, which you could also combing with statuses

另一种方法是仅在 jenkins slave 上有一个本地文件系统 ivy 存储库,它将拥有所有最新版本的库,关键是开发人员无法访问此存储库 workstations/laptops/VMs。然后你只需以某种方式在 gradle 设置中使用它(例如,只在 jenkins slave 上定义一个环境变量)。这意味着您不需要更改 build.gradle

类似的东西可能适用于 Jenkins:

if(System.getenv("BUILD_EXPERIMENTAL") == null) {

    // known to be stable versions       
    apply from: "dependencies.gradle"

} else {

    // bleeding edge versions 
    apply from: "experimental.gradle"

}

这只需要将同一个项目设置两次,一次使用环境变量,一次不使用环境变量 BUILD_EXPERIMENTAL,用于控制应用哪个 dependencies 块。

如果您希望普遍应用它,当使用 Jenkins 构建项目时,只需将 BUILD_EXPERIMENTAL 替换为 BUILD_NUMBER(默认情况下在该环境中设置)。

我建议利用 Gradle dependency locking 来实现这一目标。

  • 在构建中,您将使用 dynamic versions 作为您的依赖项,锁定到众所周知的状态。
  • 开发人员和生产构建将解决这些锁定的版本。
  • 在 CI 上,您可以有一组(一组)专用作业运行并且 updates the lock state 一次用于一个或多个模块。根据该反馈,您甚至可以提交此依赖项升级或至少为其打开一个拉取请求。

这是我自己的回答,灵感来自@Martin Zeitler 的回答。

我们有一个通用的构建脚本,可应用于所有项目 build.gradle 设置通用选项、设置和任务。我们想添加这个逻辑,但让它成为可选的并且不破坏现有的构建脚本。

逻辑将由 属性 project.ext.buildJenkinsWithLatest 激活和控制,即 truefalse

当逻辑处于活动状态时,将使用项目文件 dependencies-production.gradledependencies-jenkins.gradle 中的依赖项。仅当 属性 为真且通过存在 BUILD_NUMBER 环境变量检测到 CI 环境时才会使用 Jenkins 依赖项。

通用构建脚本包含以下内容:

if (project.ext.has('buildJenkinsWithLatest')) {
    println "Using conditional dependency management..."
    //BUILD_NUMBER is not null if this is a Jenkins build
    if(project.ext.buildJenkinsWithLatest == true && System.getenv("BUILD_NUMBER") != null) {
        println "--- Using alternative dependencies..."
        apply from: "dependencies-jenkins.gradle"
    }
    else {
        println "--- Using production dependencies..."
        apply from: "dependencies-production.gradle"
    }
}
else {
    println "Conditional dependency management is not active"
}

现在,任何已经应用此脚本的项目 build.gradle 都将在 运行:

时打印此脚本

Conditional dependency management is not active

要使用该功能,我们需要为我们的项目执行以下操作:

  1. 创建一个 dependencies-jenkins.gradle,其中包含我们想要动态 select 版本的库的 dependencies {} 子句。
  2. 创建一个 dependencies-production.gradle,其中包含用于这些库的 dependencies {} 子句,但具有给定的特定版本。
  3. 从项目 build.gradle 中保留的任何 dependencies {} 中删除库。
  4. 将 属性 project.ext.buildJenkinsWithLatest 设置为 truefalse
  5. 应用通用构建脚本(设置 属性! 后)。

例如 dependencies-jenkins.gradle 使用最新的 2.x.x 版本:

dependencies {
    compile 'example:my-library:2+'
}

关于如何以动态方式指定版本,请参阅@CantSleepNow 的回答。

并在 dependencies-production.gradle 中使用特定版本:

dependencies {
    compile 'example:my-library:2.3.4'
}

然后在 build.gradle 内设置 属性 并应用通用构建脚本:

...

project.ext.buildJenkinsWithLatest = true;
apply from: '../bxgradle/bx-std.gradle'

...

现在,当在 Jenkins 上 运行 构建时,将使用替代依赖项。如果希望使用生产依赖项在 Jenkins 上构建它,则将 project.ext.buildJenkinsWithLatest 设置为 false.