def call (Map config = [:]) { def branch = config.branch def tag = config.tag def description = config.description def credentialsId = config.credentialsId def master = "origin/master" def targetBranch = "origin/${branch}" def conflictCheck = sh(script: "git merge-base --is-ancestor ${master} ${targetBranch}", returnStatus: true) def targetTag = "v${tag}" def targetDesc = "${description}" // 检查目标分支与 master 分支是否有冲突 if (conflictCheck != 0) { def errorMessage = "分支: ${targetBranch}与${master}有冲突, 无法打tag" currentBuild.description = getErrorBuildDescription(targetTag, errorMessage) error(errorMessage) } // 检查tag是否合法 def tagPattern = /^v\d+\.\d+\.\d+$/ def latestTag = '' try { latestTag = sh(script: "git describe --tags `git rev-list --tags --max-count=1`", returnStdout: true).trim() } catch (Exception e) { echo "没有找到任何 Git tags,使用默认值" latestTag = 'v0.0.0' } // 校验输入格式 if (!targetTag.matches(tagPattern)) { def errorMessage = "输入的tag格式不正确!必须是1.0.0这种格式, 例如:1.0.1、2.3.4" currentBuild.description = getErrorBuildDescription(targetTag, errorMessage) error(errorMessage) } // 校验版本是否大于远程仓库最新版本 if (!compareVersions(targetTag, latestTag)) { def errorMessage = "目标tag: ${targetTag}小于或等于最新Tag: ${latestTag}, 无法打tag" currentBuild.description = getErrorBuildDescription(targetTag, errorMessage) error(errorMessage) } // 检查版本更新描述 if (targetDesc.trim() == '') { def errorMessage = "请输入版本改动内容" currentBuild.description = getErrorBuildDescription(targetTag, errorMessage) error(errorMessage) } withCredentials([gitUsernamePassword(credentialsId: credentialsId, gitToolName: 'git-tool')]) { sh "git tag -a $targetTag -m '$targetDesc'" sh "git push origin $targetTag" sh "git commit --allow-empty -m '构建tag: $targetTag'" sh "git push origin HEAD:$branch" } // 设置构建描述 currentBuild.description = """

发布tag(${targetTag})成功

构建分支: ${targetBranch}

""" } def getErrorBuildDescription (String tag, String message) { return """

发布tag(${tag})失败

${message}

""" } def compareVersions(String version1, String version2) { // 去掉前缀 "v" version1 = version1.replaceFirst("^v", "") version2 = version2.replaceFirst("^v", "") // 将版本号分割为数组 def ver1Parts = version1.tokenize('.') def ver2Parts = version2.tokenize('.') // 逐段比较版本号 for (int i = 0; i < Math.max(ver1Parts.size(), ver2Parts.size()); i++) { int part1 = i < ver1Parts.size() ? ver1Parts[i].toInteger() : 0 int part2 = i < ver2Parts.size() ? ver2Parts[i].toInteger() : 0 if (part1 != part2) { return part1 > part2 } } return false // 如果所有段都相同,则版本1不大于版本2 }