我有jenkins groovy管道触发其他构建。它按以下脚本完成:
for (int i = 0; i < projectsPath.size(); i++) {
stepsForParallel[jenkinsPath] = {
stage("build-${jenkinsPath}") {
def absoluteJenkinsPath = "/${jenkinsPath}/BUILD"
build job: absoluteJenkinsPath, parameters: [[$class: 'StringParameterValue', name: 'GIT_BRANCH', value: branch],
[$class: 'StringParameterValue', name: 'ROOT_EXECUTOR', value: rootExecutor]]
}
}
}
parallel stepsForParallel
问题是我的工作依赖于其他常见工作,即工作X触发工作Y而工作Z触发工作Y.我想要实现的是工作X触发工作Y并且工作Z等待结果Y由X触发。
我想我需要迭代所有正在运行的构建,并检查是否有任何相同类型的构建正在运行。如果是,那么等待它。以下代码可以等待构建完成:
def busyExecutors = Jenkins.instance.computers
.collect {
c -> c.executors.findAll { it.isBusy() }
}
.flatten()
busyExecutors.each { e ->
e.getCurrentWorkUnit().context.future.get()
}
我的问题是我需要告诉我需要等待哪个正在运行的工作。为此,我需要检查:
我如何检索这类数据?
我知道詹金斯有静默期特征,但在期满后会触发新工作。
EDIT1
只是为了澄清为什么我需要这个功能。我有构建应用程序和库的作业。应用程序依赖于libs和libs依赖于其他libs。当触发构建时,它会触发下游作业(它所依赖的库)。
示例依赖关系树:
A -> B,C,D,E
B -> F
C -> F
D -> F
E -> F
所以当我触发A然后B,C,D,E被触发并且F也被触发(4次)。我只想触发一次F。
我有beta / PoC解决方案(下面)几乎可以工作。现在我对此代码有以下问题:
我有这个丑陋的“等待”(对于(i = 0; i&lt; 1000; ++ i){})。这是因为get方法返回时没有设置结果字段
import hudson.model.*
def getMatchingJob(projectName, branchName, rootExecutor){
result = null
def busyExecutors = []
for(i = 0; i < Jenkins.instance.computers.size(); ++i){
def computer = Jenkins.instance.computers[i]
for(j = 0; j < computer.getExecutors().size(); ++j){
def executor = computer.executors[j]
if(executor.isBusy()){
busyExecutors.add(executor)
}
}
}
for(i = 0; i < busyExecutors.size(); ++i){
def workUnit = busyExecutors[i].getCurrentWorkUnit()
if(!projectName.equals(workUnit.work.context.executionRef.job)){
continue
}
def context = workUnit.context
context.future.waitForStart()
def parameters
def env
for(action in context.task.context.executionRef.run.getAllActions()){
if(action instanceof hudson.model.ParametersAction){
parameters = action
} else if(action instanceof org.jenkinsci.plugins.workflow.cps.EnvActionImpl){
env = action
}
}
def gitBranchParam = parameters.getParameter("GIT_BRANCH")
def rootExecutorParam = parameters.getParameter("ROOT_EXECUTOR")
gitBranchParam = gitBranchParam ? gitBranchParam.getValue() : null
rootExecutorParam = rootExecutorParam ? rootExecutorParam.getValue() : null
println rootExecutorParam
println gitBranchParam
if(
branchName.equals(gitBranchParam)
&& (rootExecutor == null || rootExecutor.equals(rootExecutorParam))
){
result = [
"future" : context.future,
"run" : context.task.context.executionRef.run,
"url" : busyExecutors[i].getCurrentExecutable().getUrl()
]
}
}
result
}
job = getMatchingJob('project/module/BUILD', 'branch', null)
if(job != null){
echo "found already running job"
println job
def done = job.future.get()
for(i = 0; i < 1000; ++i){}
result = done.getParent().context.executionRef.run.result
println done.toString()
if(!"SUCCESS".equals(result)){
error 'project/module/BUILD: ' + result
}
println job.run.result
}
答案 0 :(得分:0)
我有类似的问题需要解决。但是,我正在做的是迭代作业(因为活动作业可能还没有在执行程序上执行)。
触发在我的解决方案中如下所示:
这样,作业按其触发原因分组,可以使用
检索@NonCPS
def getTriggerBuild(currentBuild)
{
def triggerBuild = currentBuild.rawBuild.getCause(hudson.model.Cause$UpstreamCause)
if (triggerBuild) {
return [triggerBuild.getUpstreamProject(), triggerBuild.getUpstreamBuild()]
}
return null
}
我给每个工作提供了它所拥有的直接上游工作清单。然后,作业可以检查上游作业是否已使用
在同一组中完成构建@NonCPS
def findBuildTriggeredBy(job, triggerJob, triggerBuild)
{
def jobBuilds = job.getBuilds()
for (buildIndex = 0; buildIndex < jobBuilds.size(); ++buildIndex)
{
def build = jobBuilds[buildIndex]
def buildCause = build.getCause(hudson.model.Cause$UpstreamCause)
if (buildCause)
{
def causeJob = buildCause.getUpstreamProject()
def causeBuild = buildCause.getUpstreamBuild()
if (causeJob == triggerJob && causeBuild == triggerBuild)
{
return build.getNumber()
}
}
}
return null
}
从那里开始,一旦上传构建列表完成,我就等着它们。
def waitForUpstreamBuilds(upstreamBuilds)
{
// Iterate list -- NOTE: we cannot use groovy style or even modern java style iteration
for (upstreamBuildIndex = 0; upstreamBuildIndex < upstreamBuilds.size(); ++upstreamBuildIndex)
{
def entry = upstreamBuilds[upstreamBuildIndex]
def upstreamJobName = entry[0]
def upstreamBuildId = entry[1]
while (true)
{
def status = isUpstreamOK(upstreamJobName, upstreamBuildId)
if (status == 'OK')
{
break
}
else if (status == 'IN_PROGRESS')
{
echo "waiting for job ${upstreamJobName}#${upstreamBuildId} to finish"
sleep 10
}
else if (status == 'FAILED')
{
echo "${upstreamJobName}#${upstreamBuildId} did not finish successfully, aborting this build"
return false
}
}
}
return true
}
如果其中一个上游构建失败,则中止当前构建(这很好地转换为“中止构建”而不是“构建失败”)。
我的解决方案的主要缺点是,当有大量构建等待时,等待是昂贵的CPU。有内置的waitUntil
,但它导致了死锁(我没有尝试过最后一个版本的管道插件,可能已经解决了)。我正在寻找解决这个问题的方法 - 这就是我找到你问题的方法。