You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins Jira Pipeline并发更新问题:Fix Version被意外移除

解决Jenkins流水线并发更新Jira Fix Version的脏写问题

问题背景

当前使用的Jenkins流水线代码用于给指定Jira问题追加Fix Version,代码如下:

stage('JIRA') {
        def searchResults = jiraJqlSearch jql: "project = ${jiraProjectKey} AND issuekey = ${issueKey}'"
        def issues = searchResults.data.issues
        for (i = 0; i <issues.size(); i++) {
            def result = jiraGetIssue idOrKey: issues[i].key
            def newVersion = jiraNewVersion version: [name: "${newVersion}",
                                                project: "${jiraProjectKey}"]
            def fixVersions = result.data.fields.fixVersions << newVersion.data
            def testIssue = [fields: [fixVersions: fixVersions]]
            response = jiraEditIssue idOrKey: issues[i].key, issue: testIssue
        }
    }
}

当多个独立流水线并发更新同一Jira问题的不同Fix Version时,会出现随机丢失版本的脏写问题:例如Job1添加1.1、Job2添加2.1、Job3添加3.1,最终问题可能仅保留1.1和3.1,2.1被移除(活动历史显示该版本被删除)。

问题根源

原代码采用"读取-修改-写入"的全量更新模式:先读取当前的Fix Version列表,追加新版本后再将整个列表写回Jira。并发场景下,多个流水线会同时读取到相同的初始版本列表,后续的写入操作会互相覆盖,导致中间添加的版本丢失。

解决方案:使用Jira增量更新语法

直接利用Jira REST API的增量更新能力,通过add动作单独追加新的Fix Version,无需读取现有列表再覆盖。修改后的流水线代码如下:

stage('JIRA') {
        def searchResults = jiraJqlSearch jql: "project = ${jiraProjectKey} AND issuekey = ${issueKey}"
        def issues = searchResults.data.issues
        for (i = 0; i < issues.size(); i++) {
            def issueKey = issues[i].key
            // 创建目标版本(可添加存在性检查避免重复创建)
            def newVersion = jiraNewVersion version: [name: "${newVersion}", project: "${jiraProjectKey}"]
            // 构造增量更新的请求体,仅追加新版本
            def updatePayload = [
                update: [
                    fixVersions: [
                        [add: newVersion.data]
                    ]
                ]
            ]
            // 执行增量更新
            response = jiraEditIssue idOrKey: issueKey, issue: updatePayload
        }
    }
}

优化补充:避免重复创建版本

如果同一版本可能被多个流水线创建,可以先检查版本是否存在,存在则直接复用:

def targetVersion
try {
    // 尝试获取已存在的版本
    def existingVersion = jiraGetVersion versionOrId: "${newVersion}", project: "${jiraProjectKey}"
    targetVersion = existingVersion.data
} catch (Exception e) {
    // 版本不存在则创建
    targetVersion = jiraNewVersion version: [name: "${newVersion}", project: "${jiraProjectKey}"].data
}

原理说明

使用update字段配合add动作的请求体,会让Jira直接将指定版本追加到问题的Fix Version列表中,每个请求都是独立的原子操作,无需依赖读取到的旧数据,从根本上避免了并发场景下的脏写冲突。

内容的提问来源于stack exchange,提问作者Stephen Paulin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 02:19:59