How can I trigger a Jenkins job upon completion of a set of other jobs?
Asked Answered
B

4

4

The simple case where you just have one job depending on the completion of a set of other jobs is easy: either use a multijob or use the build flow plugin with parallel { ... }. The case I am trying to solve is more general, for example:

JobA depends on JobX and JobZ
JobB depends on JobY and JobZ
SuperJob depends on JobA and JobB

I want each of these jobs to trigger as soon as, and only when their prerequisites complete.

It would appear that neither the build flow plugin, nor the join plugin or the job DSL plugin have a good mechanism for this. I can, of course, just start all my jobs and have them poll Jenkins, but that would be quite ugly.

Another dead end is the "Upstream job trigger". I want to trigger off a specific build of a job, not just any run of an upstream job.

update

One answer mentions the multijob plugin. It can indeed be used to solve this problem, but the scheduling and total build time is almost always worst case. For example, assume this dependency graph, with the build times as indicated:

left1 (1m)  right1 (55m)
   |            |
left2 (50m) right2 (2m)
   |____________|
         |
        zip

With the multijob plugin, you get:

Phase 1:
   left1, right1  // done in 55m
Phase 2:
   left2, right2  // done in 50m
Phase 3:
    zip   // total time 105m

If I had a way to trigger the next job exactly when all prerequisites are done, then the total build time would be just 57m.

The answer here should explain how I can obtain that behavior, preferably without writing my own polling mechanism.

update 1 1/2 In the comments below, it was suggested I group the left tasks and the right tasks into a single subtask. Yes, this can be done in this example, but it is very hard to do this in general, and automatically. For example, assume there is an additional dependency: right2 depends on left1. With the build times given, the optimal build time should not change, since left1 is long done before right2 is launched, but without this knowledge, you can no longer lump left1 and left2 in the same group, without running the risk of not having right1 available.

update 2

It looks like there is no ready made answer here. It seems I am going to have to code up a system groovy script myself. See my own answer to the question.

update 3

We ended up forking the multijob plugin and writing new logic within. I hope we can publish it as a new plugin after some cleanup...

Brachiate answered 21/9, 2015 at 20:52 Comment(3)
Please mention the solution if you find one.Freedafreedman
Filed issues.jenkins-ci.org/browse/JENKINS-30580, but I fear I have to code some polling thing on my own... One could, for example, just launch all jobs at once, and then have them wait. Maybe one can use "Flyweight executors" for the polling, and then have them launch the real thing once the poll concludes all prereqs are met.Brachiate
gist.github.com/cg-soft/0ac60a9720662a417cfa is my solution, see also below.Brachiate
K
3

Since you added the jenkins-workflow tag, I guess that using Jenkins Workflow Plugin is ok to you, so perhaps this Workflow script fit your needs:

node {
    parallel left: {
        build 'left1'
        build 'left2'
    }, right: {
        build 'right1'
        build 'right2'
    },
    failFast: true

    build 'zip'
}

This workflow will trigger zip as soon as both parallel branches finish.

Kreutzer answered 25/9, 2015 at 8:57 Comment(6)
I think you need to use the left1/left2/right1/right2 jobs in my second example, as in your solution you are running JobZ twice. But that brings up the second point, namely that partitioning the dependency graph into disjoint portions is not always possible, as shown in the first example. Extending the second example, assume left2 depends on right1 in addition to the existing dependencies will also defeat any attempt at partitioning.Brachiate
Then I think it's even easier, just use parallel and build the final job just after that (see original script updated in my response).Kreutzer
Please read the example again and think about it... The problem isn't that you can't generate a correct build flow. The problem is that waiting for all jobs in the first phase to complete prior to starting the second phase is terribly inefficient, especially when there are many jobs and many phases. You are almost guaranteed to get the worst possible execution time.Brachiate
Really? Given your timing example for left and right, I would say my proposal would take 55 + zip time (which is the optimal time), since parallel branches run - obviously - in parallel. Note that I'm not talking about parallel step in BuildFlow Plugin but in Jenkins Workflow Plugin.Kreutzer
Assume there is an additional dependency: right2 depends on left1. How would you represent that build? How would you resolve an arbitrary dependency graph?Brachiate
Pending JENKINS-27127 that scenario would be a little more awkward to write, but it is already possible using waitUntil as noted in that issue.Any
B
1

As far as I can tell, there is no published solution to my problem, so I have to roll my own. The following system groovy script works, but can obviously use some enhancements. Specifically, I really miss a nice simple one page build status overview...

This gist implements my solution, including proper handling of job cancellations: https://gist.github.com/cg-soft/0ac60a9720662a417cfa

Brachiate answered 25/9, 2015 at 20:33 Comment(3)
I'm not super happy with this solution, as it has its own set of problems - specifically on how to display progress and how to safely deal with cancellations, but I don't see anything better except maybe switching to TeamCity :)Brachiate
The gist solves the cancellation problem, but creating a nice display is still beyond me... will work on it.Brachiate
I am going to "un-answer" my answer. On a large scale, the published script will cause Jenkins to crash. I have no idea how to debug that. It would appear as if my calls create a lot of objects, quickly running it out of memory.Brachiate
G
0

You can use Build other projects as Post Build Actions in the configuration of one of your parent job which would trigger second parent job on successful build of the job. When the second parent job also gets completed, trigger your child job by same method.

Gwenette answered 21/9, 2015 at 21:45 Comment(3)
Sorry, but no :) That would require me to linearize the build. I want as much parallelism as the dependency graph allows. Some of my jobs have 50 parents, I'm not going execute 50 parents one by one.Brachiate
In that case, it would require you to poll it in customised way programmatically as there is no such plugin available in Jenkins that can solve your purpose as such.Gwenette
So you say, but maybe someone already built something for their own use, and might be willing to part with it, or maybe there is an obscure construct I don't know about. That's the point of me asking. As far as I can tell, it looks like I need to write my own polling solution, but I'd rather not if I can avoid it.Brachiate
G
0

Multijob plugin could be used to make hierarchy of jobs.

First select Multijob Project in new item and then in configuration you can add as many jobs as you want. You need to also specify phase for each Job.

Gasolier answered 22/9, 2015 at 9:49 Comment(1)
I mentioned this in the question text already: in phase one, you build everything with no dependencies. In phase 2 you build everything that only requires phase 1, in phase 3, you build everything that only requires phase 1 and 2 etc. I will edit the question explaining why this algorithm is "worst case is normal case" and why it is insufficient.Brachiate

© 2022 - 2024 — McMap. All rights reserved.