2017-06-19 36 views
1

我有jenkins groovy管道觸發其他構建。它在下面的腳本來完成:Jenkins管道腳本 - 等待運行構建

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和工作ž觸發工作Y.我想達成什麼是作業X觸發作業Y和作業Z等待由X觸發的Y的結果。

我想我需要遍歷所有正在運行的構建,並檢查是否有相同類型的構建正在運行。如果是,那就等着。下面的代碼可以等待構建做:

def busyExecutors = Jenkins.instance.computers 
         .collect { 
          c -> c.executors.findAll { it.isBusy() } 
         } 
         .flatten() 
busyExecutors.each { e -> 
    e.getCurrentWorkUnit().context.future.get() 
} 

我的問題是,我需要告訴我需要等待它運行的作業。要做到這一點,我需要檢查:

  • 構建參數
  • 構建環境變量
  • 作業名

我如何能檢索到此樣的數據?

我知道詹金斯有沉默期功能,但期滿後會觸發新工作。

EDIT1

我想弄清楚,爲什麼我需要這個功能。我有建立應用程序和庫的工作。應用程序依賴於庫和libs依賴於其他庫。當構建觸發時,它會觸發下游作業(依賴它的庫)。

樣品依賴關係樹:

A -> B,C,D,E 
B -> F 
C -> F 
D -> F 
E -> F 

因此,當我觸發A然後B,C,d,E被觸發和F也觸發(4次)。我只想觸發一次F。

我有幾乎可以工作的beta/PoC解決方案(下圖)。現在,我有以下這個代碼的問題:

  • 回聲文本「發現已經運行工作」不刷新到屏幕上,直到job.future.get()結束
  • 我有這樣的醜陋「等「(for(i = 0; i < 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

我有一個類似的問題來解決。然而,我在做的是迭代作業(因爲活動作業可能不會在執行器上執行)。

在我的解決方案的觸發是這樣的:

  • 如果作業已手動觸發或通過VCS,它會觸發其所有(遞歸)下游工作
  • 如果作業已被另一個觸發上游的工作,它不會觸發任何

這樣,工作是由他們觸發原因,可以用

@NonCPS 
def getTriggerBuild(currentBuild) 
{ 
    def triggerBuild = currentBuild.rawBuild.getCause(hudson.model.Cause$UpstreamCause) 
    if (triggerBuild) { 
     return [triggerBuild.getUpstreamProject(), triggerBuild.getUpstreamBuild()] 
    } 
    return null 
} 
0123檢索分組

我給每個工作都有直接上游工作清單。接下來的工作可以檢查上游的工作是否與

@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 
} 

如果上游的一個建立失敗中止當前版本(其很好地翻譯爲「中止構建」,而不是一個「失敗的構建」)。

完整的代碼有:https://github.com/doudou/autoproj-jenkins/blob/use_autoproj_to_bootstrap_in_packages/lib/autoproj/jenkins/templates/library.pipeline.erb

我的解決方案的主要缺點是,等待是昂貴的CPU,明智的,當有很多的建立等。有內置的waitUntil,但它導致了死鎖(我沒有嘗試過最新版本的管道插件,可能已經解決了)。我正在尋找解決方法 - 這就是我發現你的問題的方法。