【问题标题】:How do I include a Gradle auto-incremented version number in my code's repo?如何在我的代码仓库中包含 Gradle 自动递增的版本号?
【发布时间】:2020-08-27 06:48:34
【问题描述】:

我的 github 公共存储库中有 Spring Boot 应用程序。我使用 gradle 作为这个 Spring Boot 应用程序的构建工具。我正在使用 jenkins 作为 CI/CD。

我的 build.gradle 文件中有以下任务,用于自动增加内部版本号,以便我生成的可执行 jar 在生成的 jar 文件中具有唯一的版本名称。

task versionIncr {
    Properties props = new Properties()
    File propsFile = new File('gradle.properties')
    props.load(propsFile.newDataInputStream())
    Integer nextbuildnum = ( ((props.getProperty('artifactBuildNumber')) as BigDecimal) + 1 )
    props.setProperty('artifactBuildNumber', nextbuildnum.toString())
    props.store(propsFile.newWriter(), null)
    props.load(propsFile.newDataInputStream())
}

我在 jenkins 中调用这个任务如下。

"versionIncr bootJar docker --warning-mode=all"

此任务运行良好。 由于以下任务发生在詹金斯服务器中

  1. jenkins 将 git $branch 拉入 jenkins 服务器工作区
  2. task =>versionIncr 正在执行并增加版本号并更新 jenkins 服务器中工作区中的 "gradle.properties" 文件
  3. 生成可执行jar文件
  4. 用新生成的可执行jar文件创建docker镜像

问题:: 对“gradle.properties”文件所做的更改保留在 jenkins 服务器工作区中,并且更新的版本号不会反映在 git hub 分支中。由于 jenkins 在本地进行了更改,因此当我将任何更改推送到 github 并运行 jenkins 作业时,"gradle.properties" 文件中的版本号仍将保持不变。我不想在每次推送我的提交时手动更新版本号。我希望 jenkins 为我处理版本更改。

是否有任何方法或 gradle 插件或 jenkins 插件可用于将修改后的 "gradle.properties" 文件从 jenkins 工作区推回 "github" 存储库。 另外,如果可能的话,我想知道使用github username/password 或使用SSH 的方法。

如果我需要在这里发布更多信息,请告诉我。

更新:: 发布我的 build.gradle 文件以防万一有人对我的做法感兴趣。 build.gradle

buildscript {
    repositories {
    jcenter()
    }
    dependencies {
    classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.3.RELEASE")
    classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4+"
    }
}

plugins {
    id 'org.springframework.boot' version '2.2.7.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'java'
    id 'maven-publish'
    id 'com.palantir.docker' version '0.25.0'
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
//apply plugin: 'io.spring.gradle.dependencymanagement.DependencyManagementPlugin'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'
//apply plugin: 'org.jfrog.gradle.plugin.artifactory.ArtifactoryPlugin'

group 'com.javasree'
version project.properties.containsKey("releaseVersion") ? "${artifactMajorVersion}" : "${artifactMajorVersion}-${artifactBuildNumber}"
sourceCompatibility = 1.8

ext {
    springCloudVersion ='Greenwich.RELEASE'
    artifactName ='<artifact>'
    artifactory = 'http://localhost:8081/artifactory/'
    artifactoryRepo = 'gradle-lib-release'
    artifactorySnapShotRepo = 'gradle-lib-snashot'
    artifactoryRepo3pp = 'pub-gradle-remote'
    artifactoryUser = System.getProperty("user", "")
    artifactoryPassword = System.getProperty("password", "")
}

repositories {
    mavenCentral()
    maven {
    url "${artifactory}${artifactoryRepo3pp}"
    allowInsecureProtocol = true
    credentials {               // Optional resolver credentials (leave out to use anonymous resolution)
        username = "admin" // Artifactory user name
        password = "password" // Password or API Key
    }
    }
}

publishing.publications {
    maven(MavenPublication) {
    artifact bootJar
//      groupId 'gatewayengine'
//      artifactId artifactName
//      version '1.0-SNAPSHOT'
    from components.java
    }
}

publishing.repositories {
    maven {
    allowInsecureProtocol = true
    credentials {
        username = "admin" // Artifactory user name
        password = "password" // Password or API Key
    }
    if(project.version.endsWith('-SNAPSHOT')) {
        url "${artifactory}${artifactorySnapShotRepo}"
    } else {
        url "${artifactory}${artifactoryRepo}"
    }
    }
}

dependencyManagement {
    imports {
    mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    //mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
    }
}

docker {
    name "localhost:5000/${project.name}:${project.version}"
    files tasks.bootJar.outputs
    //tag 'localhost:5000/${project.name}:${project.version}'
    dockerfile file('Dockerfile')
    //buildArgs([HOST_APP_JAR_LOC: 'version'])
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web',
        'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:2.2.2.RELEASE',
        'org.springframework.cloud:spring-cloud-starter-netflix-zuul:2.2.2.RELEASE'
}




task versionIncr {
    Properties props = new Properties()
    File propsFile = new File('gradle.properties')
    props.load(propsFile.newDataInputStream())
    Integer nextbuildnum = ( ((props.getProperty('artifactBuildNumber')) as BigDecimal) + 1 )
    props.setProperty('artifactBuildNumber', nextbuildnum.toString())
    props.store(propsFile.newWriter(), null)
    props.load(propsFile.newDataInputStream())
}

【问题讨论】:

    标签: git jenkins gradle


    【解决方案1】:

    我之前以两种不同的方式解决了您提出的问题。首先,通过使用 Gradle 插件,类似于上面链接的 nebula-release 插件 @sghill。

    但是,该插件通过计算补丁版本的所有提交来工作,通过 Gradle 扩展配置主要和次要版本并附加元数据信息,例如分支名称以及它是否脏。对于我的需求来说,这似乎过于复杂的工作流程,并且对于不使用 Gradle 的项目没有用处。但是,对于您的情况,这是一个快速现成的解决方案。

    就我而言,我所需要的只是在 PR 被合并到 developmaster 时自动标记的唯一版本号,以及分支上每个提交的唯一版本号。为此,我确实使用了 Git 标签并为它编写了一个脚本。

    版本控制的 3 种情况是:

    • 一个新的、未初始化的 repo => 生成一个带有默认分支的新 version.json 文件(master,但可以根据 repo、主要和次要版本进行更改以配置这些凹凸)
    • 任何合并到默认分支中的提交都会生成一个新版本并对其进行标记。如果version.json 中的主要或次要版本已更改,则会发生主要或次要颠簸并将补丁版本重置为0。
    • 分支上的唯一版本:git describe 的输出和分支名称,例如0.1.0-x-branch-name 其中x 是默认分支之前的提交次数。

    你可以找到它here 和 docker 容器here

    至于将 Jenkins 配置为对 repo 具有写入权限,您是否按照此处的说明进行操作?这就是我在所有回购中成功做的事情: Git push using jenkins credentials from declarative pipeline

    【讨论】:

    • 你的回答可能会解决我的问题但我是一只新蜜蜂,我不知道如何为詹金斯纠正这样的描述性文件。我总是使用 UI 选项来设置我的 repo 和目标,例如如何将 jar 构建和发布到人工制品。你的答案看起来很有希望,但我如何将我所有的 jenkins 配置转换为一个文件,我可以在其中添加建议的脚本以将文件推送到 github。请帮忙
    • 这是一个比我在此评论中所能给出的更复杂的答案,因为我不知道您通过 UI 配置的所有步骤和阶段。但是,它的要点是,您可以通过在您的 repo 中拥有一个 Jenkinsfile 来做到这一点,并且当您为 repo 创建一个 jenkins 作业时,您可以从 Jenkinsfile 指定配置。本质上,来自 UI 的所有配置都应该可以直接转换为声明性管道语法。看看这个入门页面,如果您有任何问题,请告诉我:jenkins.io/doc/book/pipeline/getting-started
    【解决方案2】:

    nebula.release Gradle plugin 能够使用 git 标签自动增加版本。开始:

    plugins {
        id 'nebula.release' version '15.0.0' // or current latest
    }
    

    插件为发布类型添加了几个任务,以及增加版本组件的选项。默认情况下,它将增加次要版本。这是一个如何在单个分支上增加版本的示例:

    $ ./gradlew final                       # releases 0.1.0; tags repo v0.1.0
    $ ./gradlew final                       # releases 0.2.0; tags repo v0.2.0
    $ ./gradlew final -Prelease.scope=minor # releases 0.2.1; tags repo v0.2.1
    

    由于找到上一个git标签后版本会增加,因此可以通过在最近的提交上手动创建一个git标签来调整起始版本。

    注意事项:

    1. Jenkins 需要对 repo 的写入权限才能推回标签
    2. 插件假定 repo 中的所有内容都将使用相同的版本发布
    3. 它强烈喜欢semver-like 版本

    如果这不符合您的用例,Gradle 插件门户上还有更多 versioning plugins 可供选择。

    【讨论】:

    • 感谢您的回答。我今天会试试这个,然后告诉你。但是我如何为我的 github repo 授予 jenkins 完全许可?我应该配置用户并在 github 中授予权限吗?我可以在我的詹金斯机器中创建 ssh 密钥并将其添加到 github 中吗?这是我应该授予访问权限的方式还是有其他方式?
    • 有一些选项取决于你想要做什么。请参阅Machine Users,了解授予对多个存储库的自动化访问权限的常见模式。
    • 抱歉耽搁了。上面的插件用于版本控制。我目前正在寻找的构建脚本是出于开发目的,因为每天将多次推送到 repo 和多个构建。我不想将标签选项用于开发目的。当我为 QA / RELEASE 发布构建时,我将使用标签。我可以使用建议的插件进行版本自动递增。
    • 但是,我真正的挑战不是版本控制。挑战是我如何将 jenkins 所做的更改推回我的 github 存储库。正如我之前的评论中所述,因为我想为我的 QA/RELEASE 使用基于标签的推送,而不是我的开发版本,因为我最终会创建数百个标签。我尝试使用 shell 脚本检查修改过的文件并通过说“git push”来添加它们,但这并没有发生,因为它无法验证用户身份(即使我能够使用 CLI 在同一台詹金斯机器中推送更改)
    • > 我不想将标签选项用于开发目的。当我为 QA / RELEASE 发布构建时,我将使用标签。考虑有两个作业: 1. 在更新分支时运行 ./gradlew devSnapshot,这不会创建标签 2. 在创建新标签时发布运行 ./gradlew -Prelease.useLastTag=true final 的作业。您可以使用 GitHub 发布来创建标签。在此设置中,Jenkins 不需要写入权限。 > 即使我能够使用 CLI 在同一台 jenkins 机器中推送更改需要检查的内容:用户、ssh 密钥、repo 的克隆 uri。
    【解决方案3】:

    版本号几乎是自动-增量,但内部版本号是。

    Jenkins 为每个项目公开了它自己的自动增量 ${BUILD_NUMBER}

    使用System.getenv("BUILD_NUMBER") 可以在构建时获取:

    // $BUILD_NUMBER only exists when building with Jenkins
    project.ext.set('BUILD_NUMBER', System.getenv("BUILD_NUMBER") ?: "0")
    

    昨天使用 Google Cloud Build,我还定义了 BUILD_NUMBER
    因为我需要区分手动构建和自动构建。
    ...不同的构建器可能提供不同的环境变量。

    Jenkins 通常在分支发生更改时构建。因此,可以通过 Git 更新 version.properties 文件(本地 pre-commit hook 可以增加)。
    如果你真的想在每次提交到 Github 时增加版本。

    【讨论】:

    • 同意我们可以使用 jenkins 的“BUILD_NUMBER”,但是假设我的构建失败了 5 次并且在第 6 次构建时成功,那么我生成的构建 jar 在构建时将有 6 个。这可能会造成混乱,好像有人对剩余的 1.2....5 构建做了一些事情,就好像它们丢失了一样。所以我对当前使用 Gradle 任务自动递增的方法感到满意。但是,我真正的问题不是自动增加版本。但是将自动递增的版本号提交/推送回 git hub。我不想使用 TAG,因为这个脚本是用于开发环境的。
    • 在我的情况下分支不会改变。人们将为每个更改创建单独的/私有分支,并将创建 PR(拉取请求)。经过仔细的完整代码审查后,此 PR 将合并到开发分支。构建将始终仅针对“开发”分支触发。所以对于 PR 的每次合并,我想自动发布带有新版本号的 jar。所以如上所述,我的要求是“我如何将修改后的版本号推回 GITHUB”
    猜你喜欢
    • 1970-01-01
    • 2011-10-09
    • 2017-05-31
    • 2015-02-23
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 2014-02-19
    • 2017-07-05
    相关资源
    最近更新 更多