To get the ball rolling, here is an example of some use cases that are difficult if not impossible to achieve at the moment which I would hope would be solved by this improvement:

"Part 1: Job Dependency"

Suppose a project has a low level 'framework' module and a higher level 'application' module which depends on it. It stands to reason that after building the 'framework' module successfully we should run a build of the 'application' module automatically so as to incorporate those framework changes. In this situation the latter, which we'll refer to as "Job A" depends on the latter which we'll refer to as "Job F". In this situation the expected behavior would be as follows:

  1. Job F would only run when changes are made to Job F
  2. Job A would be run in either of the following scenarios:
    1. Job A has changes made to it
    2. Job F has changes to it and those changes have been rebuilt successfully
  3. If Job A is currently running and Job F is triggered through some other means it will block until Job A completes
  4. If Job F is currently running and Job A is triggered through some other means it will block until Job F completes
  5. If builds of both Job A and Job F are pending in a build queue Job F will be run before Job A even if they were triggered in the opposite order

In this scenario, the first 2 bullet points are more-or-less built into the Jenkins core via 'triggers', with the exception of item 2.2. So far as I can tell there is no way to prevent dependent projects from building when their upstreams are broken - via plugins or otherwise. Items 3 and 4 are supported by the Jenkins core but for some reason they are disabled by default. IMO if Jenkins implemented correct dependency management these options would be enabled by default. Item 5 is achievable with a fair amount of work through the use of plugins and an assortment of 'tweaks' to the Jenkins configuration.

"Part 2: Parallel Dependencies

Now, lets extend our example to include a server module, which we'll refer to as "Job S". This module will again depend on Job F - the common framework - but will be completely independent to Job A - the application. So in this case this new job would need to exhibit the same behavior as described for "Job A" above, which has the following implications:

  1. When changes are made to Job A only Job A will be rebuilt - Job F and Job S will not
  2. When changes are made to Job S only Job S will be rebuilt - Job F and Job A will not
  3. When changes are made to Job F and those changes are built successfully, both Job A and Job S will be rebuilt to integrate the changes
  4. When Job F is building and either Job A or Job S (or both) get triggered through some other means, they will block until Job F has completed successfully
  5. Job A and Job S should be able to build in parallel
  6. If both Job A and Job S are queued for execution, the order of execution does not matter (ie: FIFO priority would seem appropriate to make the order more explicit)
  7. If Job A, Job S and Job F all have builds waiting in the queue, Job F should be scheduled to run before either of Job A or Job S regardless of the chronological order in which the builds were triggered.

So again, support for the first 3 items is supported by Jenkins core. Item 4 is partially support, with the exception that there is no mechanism that prevents Job A and Job S from building through independent triggers when Job F has finished building unsuccessfully. Items 5 and 6 are inherently supported by the Jenkins core. Finally, item 7 is supported via plugins with some monkeying with the configurations and triggers a bit.

"Part 3: Dreaded Diamond Dependency"

Finally, lets extend our example to include a dreaded diamond dependency. Suppose now we add a forth job to our configuration which 'packages' the artifacts of all three jobs (ie: creates an installer for them). Let's call this Job I. In this situation Job I requires all other jobs to be built successfully for it to work correctly. This has the following implications:

  1. If Job I gets triggered through some means and any of the other jobs are currently running, it must block until their builds are complete
  2. If any of the other jobs are broken Job I should not be allowed to build (no files have been built so there is nothing to package)
  3. If Job F receives changes, after those changes have been successfully built Job A and Job S must be triggered and run in parallel, then upon successful completion of these two jobs Job I must be triggered
    1. As a corollary to this point, if Job F builds successfully, after which Job A and Job S get triggered, if Job A succeeds but Job S fails then Job I should not be executed.
  4. If Job A receives changes and is built successfully, Job I should be triggered - without executing Job F or Job S
  5. If Job S receives changes and is built successfully, Job I should be triggered - without executing Job F or Job A
  6. If Job F and Job I both have builds in the queue, Job F should be scheduled to run before Job I regardless of which one triggered first
  7. If Job F is currently building and Job I gets triggered through some other means it will be queued as per item #1. After Job F completes successfully it must trigger a build of both Job A and Job S, both of which much be executed before the build of Job I that is waiting in the queue.

This scenario is where things start to break down horribly for Jenkins. For example, we have the Join Plugin out our disposal, which looks like at a glance may be designed for just such a scenario. However it breaks down in several situations like items 3.1, 4 and 5 above (if memory serves). Then we have plugins like Build Flow which, again, appear to handle several of these cases correctly. If memory serves it does handle item 3.1 correctly, for example. However it too falls apart on items 4 and 5. Then, the limitations of these plugins gets exacerbated even further because many of them don't play nice with other plugins that are required to get this whole use case working. For example, neither of these aforementioned plugins work with the Priority Queue Sorter plugin, which is also need to achieve the results described above. So then you end up having to trade off one bit of functionality for another (ie: if plugin A and B won't work correctly together then you have to make a choice of which plugin is more valuable to your workflow and ditch the other one).

It is my hope that if job dependencies were modeled in the core Jenkins architecture that not only would many of these plugins become obsolete, but that the resulting behavior of the tool as a whole would become more robust as a result. Put another way, trying to "extend" Jenkins to "add" support for dependency management seems like trying to "extend" a motorcycle to be more like a transport truck by "adding" a few wheels to its axles. At best you end up with a Frankenstein like thing that doesn't quite satisfy the users expectations.

This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators.
For more information on JIRA, see: http://www.atlassian.com/software/jira

--
You received this message because you are subscribed to the Google Groups "Jenkins Issues" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to