2017-06-19 39 views
1

他のビルドをトリガーするジェンキングルーヴパイプラインがあります。次のスクリプトで行われます。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トリガーとジョブZは、私が達成したいのですがどのような仕事の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に依存し、libsは他のlibsに依存します。ビルドがトリガされると、ダウンストリームジョブ(依存するlibs)がトリガされます。

    サンプルの依存関係ツリー:

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

    Iは、次いで、B、C、D、Eをトリガするときにトリガされ、Fはまた、(4回)でトリガされます。私はFを1回だけトリガーしたいと思います。

    私はほとんど動作するベータ/ 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が組み込まれていますが、デッドロックが発生しました(私はパイプラインプラグインの最後のバージョンで試していませんが、解決されている可能性があります)。私はそれを今修正する方法を探しています - それがあなたの質問を見つけた方法です。

    関連する問題