すべてのステージングテストを継続的に実行するJenkinsジョブを構築していますが、すべてを一度に実行するわけではありません(共有ハードウェアに依存しています)。そこで、セマフォーを使って並行ジョブを作成し、一度に限られた量しか実行されないようにしています。Jenkinsパイプラインとセマフォ
import java.util.concurrent.Semaphore
def run(job) {
return {
this.limiter.acquire();
try {
println "running ${job}"
build job
println "finished ${job}"
} finally {
this.limiter.release();
}
}
}
def getJobs() {
def allJobs = Jenkins.getInstance().getJobNames()
def stagingJobs = []
for(String job : allJobs) {
if (job.startsWith("staging/temp")) {
stagingJobs.add(job)
}
}
println "${stagingJobs.size()} jobs were found."
return stagingJobs
}
this.limiter = new Semaphore(2)
def jobs = [:]
for (job in getJobs()) {
jobs[job] = run(job)
}
parallel jobs
私はセマフォなしで実行すると、すべてが正常に動作します: はここに問題を再現し、私のパイプラインの簡易版です。
[Pipeline] echo
6 jobs were found.
[Pipeline] parallel
[Pipeline] [staging/temp1] { (Branch: staging/temp1)
[Pipeline] [staging/temp2] { (Branch: staging/temp2)
[Pipeline] [staging/temp3] { (Branch: staging/temp3)
[Pipeline] [staging/temp4] { (Branch: staging/temp4)
[Pipeline] [staging/temp5] { (Branch: staging/temp5)
[Pipeline] [staging/temp6] { (Branch: staging/temp6)
私はパイプラインのステップを表示した場合、私は最初の2つのジョブが開始見て、そのログメッセージを出力することができます。しかし、上記のコードで、私は除いて出力された何も得ます。しかし、ランナーはステージングジョブが完了したという通知を受け取らないようです。その結果、セマフォーは決して解放されず、他の4つのジョブは開始できません。
Thread #7
at DSL.build(unsure what happened to downstream build)
at WorkflowScript.run(WorkflowScript:9)
at DSL.parallel(Native Method)
at WorkflowScript.run(WorkflowScript:38)
Thread #8
at DSL.build(unsure what happened to downstream build)
at WorkflowScript.run(WorkflowScript:9)
Thread #11
at WorkflowScript.run(WorkflowScript:6)
Thread #12
at WorkflowScript.run(WorkflowScript:6)
結局それ倍、いくつかのjava.lang.InterruptedException
エラーと出:下流のは間違いなく終了したビルド後にここでは、スレッドダンプ半ばテストです。
セマフォをパイプラインで使用することは可能ですか、または一度に実行されるジョブの一部だけを確実にするためのよりよい方法がありますか?私はむしろ単純なテストランナーに相当する分だけノードを回転させないようにしたいと思います。
ノートを見てすることができます:ジェシーグリックはジェンキンスJIRA上でこれを指摘:「あなたはパイプラインスクリプトからネイティブJava並行処理プリミティブを使用することはできません。 -itがシングルスレッドのVMで実行されている " – Crummy