1 背景
java项目命名为 simple2。 命名有点随意,不要在意这个,不重要。
simple2的代码维护在gitlab中。
simple2项目有两个git分支: dev 和 master
开发中的代码在 dev分支,dev分支需要合并(merge)到master主分支。
基于此目的,在普元devops中创建一个构建,该构建的任务列表中,只有一个:代码库分支合并。
任务的配置如下:
执行该构建,会在jenkins中创建一个临时job,该job的类型是流水线,该流水线会创建一个gitlab的分支合并请求。
正常情况下,devops的构建执行成功,jenkins的临时job也执行成功,然后jenkins的临时job会自动删除,gitlab中会看到simple2项目下多出来一个合并请求。
相关代码管理员在gitlab中手动对该合并请求进行审批,并确认合并。
至此,分支合并完成。
2 环境说明
普元Devops: Devops 6.6_GA
Gitlab: 基于Docker安装,Gitlab镜像为 gitlab/gitlab-ce:latest 。具体的gitlab基于Docker安装的细节就不赘述了。
Jenkins: 普元devops安装介质中提供的Jenkins。 根据我的经验,可以自行从官网下载Jenkins,并非一定要使用普元devops提供的jenkins版本。
关键点是Jenkins启动的时候需要增加若干参数
-Dhudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION=true
-Dorg.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.ADMIN_AUTO_APPROVAL_ENABLED=true
-Dorg.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.ALLOW_ADMIN_APPROVAL_ENABLED=true
这几个参数的含义,请自行百度或询问文心一言。
启动脚本如下:
/works/apps/jdk17/bin/java -Djava.awt.headless=true -Dfile.encoding=utf-8 -Xmx2048m -Xms1024m -DJENKINS_HOME=/works/devops/jenkins-2.426/work -Dhudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION=true -Dorg.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.ADMIN_AUTO_APPROVAL_ENABLED=true -Dorg.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.ALLOW_ADMIN_APPROVAL_ENABLED=true -jar /works/devops/jenkins-2.426/jenkins.war --httpPort=9080
这段脚本中,java路径、jenkins的安装路径,都是我的测试环境的路径,执行的时候需要针对性修改一下。
3 问题描述
Devops的构建 执行构建后
经常性卡住执行不下去,持续时间不断增加,始终无法完成。
经过检查后发现,构建执行后,会在Jenkins中创建一个临时Job,查看该Job的构建历史,Console Output,发现最后一行日志是 sleep 1hr 23min ,个人分析感觉是流水线脚本中执行了sleep命令,而休眠时间值过长,需要休眠1小时23分钟。(其实分析得到这个结果用了我很长时间)
检查该Jenkins临时job的配置,看到流水线脚本中有一段代码如下:
// 获取merge request判断changes内容
// 如果mergeStatus为 can_be_merged 则accect
def startTime = System.currentTimeMillis()
def endTime = startTime + 2 * 60 * 1000 // 两分钟的毫秒数
def pollingInterval = 5000 // 间隔5秒轮询一次
def mergeRequest
while (System.currentTimeMillis() < endTime) {
mergeRequest = callDevOpsRestApi(pipelineContext, "api/vcs/repos/${stageAttrs.codeRepositoryId}/merge-requests/${mergeRequestId}/changes", "GET", null)
if (mergeRequest==null || isNullOrBlank(mergeRequest.mergeStatus) || mergeRequest.mergeStatus == "unchecked" || mergeRequest.mergeStatus == "checking") {
// 继续轮询
sleep(pollingInterval) // 休眠指定的间隔时间
} else {
break
}
}
这段代码在while循环,每次循环中会调用普元devops的 merge-requests/${mergeRequestId}/changes 接口,检查合并请求的状态,状态不对,就执行一次 sleep方法。
看注释是间隔轮询,每次计划休眠5000毫秒。
但Jenkins的流水线脚本中调用的sleep是jenkins内置函数,休眠单位不是毫秒,而是秒,因此造成每次休眠5000秒,大概就是 83分钟。
4 解决办法
Jenkins的临时Job是普元devops创建的,那么这段流水线脚本应该也是devops创建的。
由此想到普元devops中应该存储了这段脚本的模板。
经过若干分钟的查找和文档阅读,最后在普元Devops部署文件夹下找到了这个脚本的模板文件,路径如下
$devops安装路径$/WEB-INF/_srv/work/user/com.primeton.devops.engine/META-INF/pipeline/stages/code/gitlab-branch-merge.groovy
编辑这个文件,修改58行,将 5000改为 5 ,就是休眠5秒钟了。
再次执行Devops的分支合并构建,devops构建执行成功,jenkins的临时Job执行成功,Gitlab中项目simple2下新增了一条合并请求。
至此,问题完美解决。