如何检索 Jenkins 构建的 SVN 变更集注释?

How can I retrieve the SVN Changeset comments for a Jenkins build?

我的流程是,Jenkins 每三分钟轮询一次 SVN 的构建,在发生更改时执行构建,并创建一个部署包,然后将其推送到 Octopus。部署完成后,它会通过电子邮件向所有相关人员发送部署报告。

现在,报告中的构建说明只是典型的样板文件,即 Jenkins Build 35。如果我可以提取触发构建的变更集的评论并关闭发布说明,那将会很棒

如果我能得到评论,将它们放入发行说明中就非常简单了。如果有人对此有任何想法,我将不胜感激。

更新:有一个关于如何使用 email-ext 插件执行此操作的相关问题,但我没有使用该插件,据我所知,答案是使用该插件的语法表达的插件,我不知道如何调整它。我将不胜感激直接与我在这里的使用有关的答案。

您可以通过 3 种方式获取 SCM 更改

Groovy

Groovy is similar to Java and is native to Jenkins, hence you can reference Jenkins object models and data directly with Groovy. You still requires plugins to execute Groovy code, such as Groovy Plugin。这是从这个答案中采用的一些示例代码:
How to get the list of changed file in SVN from Jenkins

import hudson.model.*
import hudson.util.*
import hudson.scm.*
import hudson.scm.SubversionChangeLogSet.LogEntry

// work with current build
def build = Thread.currentThread()?.executable

// for testing, use last build or specific build number
//def item = hudson.model.Hudson.instance.getItem("Update_SRC_Branch") 
//def build = item.getLastBuild()   
//def build = item.getBuildByNumber(35)   

// get ChangesSets with all changed items
def changeSet= build.getChangeSet()
List<LogEntry> items = changeSet.getItems()

从那里开始,items 列表现在包含更改集。随意使用。这是我打算使用 Groovy 的范围,因为坦率地说我不使用它。

文件系统

Jenkins 在 $JENKINS_HOME/jobs/$JOB_NAME/builds/$BUILD_ID 下的文件系统上存储构建。在版本 1.597 之前,$BUILD_ID 是格式类似于 2015-03-16_00-13-19 的时间戳。 After version 1.597$BUILD_ID 现在是内部版本号 $BUILD_NUMBER,类似于 123(与您在构建历史日志中看到的相同) .

那里有一个文件:$JENKINS_HOME/jobs/$JOB_NAME/builds/$BUILD_ID/changelog.xml。它包含您在 UI 中看到的所有相同的 SCM 变更集,从您的 SCM 中提取,全部在一个 XML 文件中。解析文件,每个 <msg>...</msg> 元素都包含注释。可能不止一个。

但是,尽管在构建期间所有变量都可以在运行时使用(将 $VAR 更改为 %VAR% if on Windows),但具体的构建位置是 NOT 在构建完成之前创建,因此您无法在当前构建期间访问它。但是,您可以将所有这些变量传递给下游构建(例如您的部署作业,如果它是单独的),并且该下游构建可以提取变更日志文件。您需要 Parameterized Trigger Plugin 才能将变量传递给另一个构建。

电子邮件

Jenkins 自带的 mailer action 除了 "boilerplate" 消息几乎什么都做不了。如果你想 任何东西 处理电子邮件,你需要 Email-ext (Extended Email) Plugin. There are a ton of questions/answers on SO here about email-ext, even a tag ,但是我建议搜索文本 email-ext 而不是使用标签,因为很多问题没有完全标记。

您的第一个起点是“Content Token Reference”页面帮助(单击 ? 该文本旁边的图标。它列出了可以在电子邮件中使用的所有可能标记 title/body

您想要 "SCM comments"。这些是通过 ${CHANGES_SINCE_LAST_SUCCESS} 令牌的 %m 引用的。要获得 评论,请使用以下内容:

${CHANGES_SINCE_LAST_SUCCESS, changesFormat=" %m<br>"}

只需将以上行放入电子邮件正文配置即可。你可以用任何你想要的纯文本包围它。

要获得格式更好的输出,请使用

${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="<b>Changes for Build #%n</b><br>%c<br>", changesFormat="<br>[<a href='${JENKINS_URL}/user/%a/builds'>%a</a>] - (%r) %p<br> %m<br>"}

如我提供的重复问题中所引用:
How can I get the SVN log entry in Jenkins when sending email

P.S.

如果您的要求是 "no plugins",那么您需要找到与 Jenkins 不同的构建系统。 Jenkins 是一个开源项目,它为几乎所有其他东西提供核心和插件,由开放社区维护。 Jenkins 中的一切都是 "plugin",甚至 Subversion SCM 步骤和 FreestyleMaven项目是 "plugins"。有的是安装自带的,大部分需要安装后添加。

这是使用 Jenkins Pipeline 脚本时的解决方案。此处输出的格式为 HTML table。 table 放在引号内,在我的例子中,在将结果发送到其他脚本时需要引号。

#!groovy

@NonCPS
def getChangeString(buildItem) {
    def buildChanges = ''
    if (buildItem.size() > 0) {
        def changeNbr = 1;
        buildItem.each { buildChanges += changeNbr++ + '. ' + it.msg.text() + '<br>'}
        // Escape quotation marks
        buildChanges = buildChanges.replaceAll('"','\"')
        // Replace new lines with HTML
        buildChanges = buildChanges.replaceAll('\n','<br>')
    } else {
        buildChanges += 'No changes in this build'
    }
    buildChanges
}

node(){
    stage ('deploy') {
        // work with current build
        def buildUrl = BUILD_URL
        // for testing
        //def buildUrl = "http://localhost:8082/job/job_name/167/"

        def buildXml = new XmlSlurper().parse("${buildUrl}api/xml")
        def buildCause = buildXml.action.cause.shortDescription.text()
        def buildCh = getChangeString(buildXml.changeSet.item)

        def releaseNotes = "\"<table><tr><td>Jenkins build</td><td><a href='$BUILD_URL'>$BUILD_NUMBER</a><br></td></tr><tr><td>Build cause: </td><td>$buildCause</td></tr><tr><td>Changes:</td><td>$buildCh</td><tr></table>\""
        // Set variables to null to avoid NotSerializableException
        buildXml = null
        buildCause = null
        buildCh = null
        echo "releaseNotes is $releaseNotes"
    }
}

您需要取消选中 "Use Groovy Sandbox" 才能正常工作。