How to conditionally build other projects?

Jenkins

Jenkins Problem Overview


I have a fairly complicated Jenkins job that builds, unit tests and packages a web application. Depending on the situation, I would like to do different things once this job completes. I have not found a re-usable/maintainable way to do this. Is that really the case or am I missing something?

The options I would like to have once my complicated job completes:

  1. Do nothing

  2. Start my low-risk-change build pipeline:

  • copies my WAR file to my artifact repository
  • deploys to production
  1. Start my high-risk-change build pipeline:
  • copies my WAR file to my artifact repository
  • deploys to test
  • run acceptance tests
  • deploy to production

I have not found an easy way to do this. The simplest, but not very maintainable approach would be to make three separate jobs, each of which kicks off a downstream build. This approach scares me for a few reasons including the fact that changes would have to be made in three places instead of one. In addition, many of the downstream jobs are also nearly identical. The only difference is which downstream jobs they call. The proliferation of jobs seems like it would lead to an un-maintainable mess.

I have looked at using several approaches to keep this as one job, but none have worked so far:

  1. Make the job a multi-configuration project (<https://wiki.jenkins-ci.org/display/JENKINS/Building+a+matrix+project>;). This provides a way to inject the job with a parameter. I have not found a way to make the "build other projects" step respond to a parameter.

  2. Use the Parameterized-Trigger plugin (<https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugin>;). This plugin lets you trigger downstream-jobs based on certain triggers. The triggers appear to be too restrictive though. They're all based on the state of the build, not arbitrary variables. I don't see any option provided here that would work for my use case.

  3. Use the Flexible Publish plugin (<https://wiki.jenkins-ci.org/display/JENKINS/Flexible+Publish+Plugin>;). This plugin has the opposite problem as the parameterized-trigger plugin. It has many useful conditions it can check, but it doesn't look like it can start building another project. Its actions are limited to publishing type activities.

  4. Use Flexible Publish + Any Build Step plugin (<https://wiki.jenkins-ci.org/display/JENKINS/Any+Build+Step+Plugin>;). The Any Build Step plugin allows making any build action available to the Flexible Publish plugin. While more actions were made available once this plugin was activated, those actions didn't include "build other projects."

Is there really not an easy way to do this? I'm surprised that I haven't found it and even more surprised that I haven't really seen any one else trying to do this? Am I doing something unusual? Is there something obvious that I am missing?

Jenkins Solutions


Solution 1 - Jenkins

If I understood it correct you should be able to do this by following these Steps:

  1. First Build Step:
  2. Does the regular work. In your case: building, unit testing and packaging of the web application
  3. Depending on the result let it create a file with a specific name.
  4. This means if you want the low-risk-change to run afterwards create a file low-risk.prop
  5. Second Build Step:
  6. Create a Trigger/call builds on other projects Step from the Parameterized-Trigger plugin.
  7. Entery the name of your low-risk job into the Projects to build field
  8. Click on: Add Parameter
  9. Choose: Parameters from properties File
  10. Enter low-risk.prop into the Use properties from file Field
  11. Enable Don't trigger if any files are missing
  12. Third Build Step:
  13. Check if a low-risk.prop file exists
  14. Delete the File

Do the same for the high-risk job

Now you should have the following Setup:

  • if a file called low-risk.prop occurs during the first Build Step the low-risk job will be started
  • if a file called high-risk.prop occurs during the first Build Step the high-risk job will be started
  • if there's no .prop File nothing happens

And that's what you wanted to achieve. Isn't it?

Solution 2 - Jenkins

Have you looked at the Conditional Build Plugin? (https://wiki.jenkins.io/display/JENKINS/Conditional+BuildStep+Plugin)

I think it can do what you're looking for.

Solution 3 - Jenkins

If you want a conditional post-build step, there is a plugin for that:
https://wiki.jenkins-ci.org/display/JENKINS/Post+build+task

It will search the console log for a RegEx you specify, and if found, will execute a custom script. You can configure fairly complex criteria, and you can configure multiple sets of criteria each executing different post build tasks.

It doesn't provide you with the usual "build step" actions, so you've got to write your own script there. You can trigger execution of the same job with different parameters, or another job with some parameters, in standard ways that jenkins supports (for example using curl)

Yet another alternative is Jenkins text finder plugin:
https://wiki.jenkins-ci.org/display/JENKINS/Text-finder+Plugin

This is a post-build step that allows to forcefully mark a build as "unstable" if a RegEx is found in console text (or even some file in workspace). So, in your build steps, depending on your conditions, echo a unique line into console log, and then do a RegEx for that line. You can then use "Trigger parameterized buids" and set the condition as "unstable". This has an added benefit of visually marking the build different (with a yellow ball), however you only have 1 conditional option with this method, and from your OP, looks like you need 2.

Try a combination of these 2 methods:

Solution 4 - Jenkins

Do you use Ant for your builds?

If so, it's possible to do conditional building in ant by having a set of environment variables your build scripts can use to conditionally build. In Jenkins, your build will then be building all of the projects, but your actual build will decide whether it builds or just short-circuits.

Solution 5 - Jenkins

I think the way to do it is to add an intermediate job that you put in the post-build step and pass to it all the parameters your downstream jobs could possibly need, and then within that job place conditional builds for the real downstream jobs.

Solution 6 - Jenkins

The simplest approach I found is to trigger other jobs remotely, so that you can use [Conditional Build Plugin][1] or any other plugins to build other jobs conditionally.

[1]: https://wiki.jenkins.io/display/JENKINS/Conditional+BuildStep+Plugin)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionxnickmxView Question on Stackoverflow
Solution 1 - JenkinsjadephantomView Answer on Stackoverflow
Solution 2 - JenkinsDennis S.View Answer on Stackoverflow
Solution 3 - JenkinsSlavView Answer on Stackoverflow
Solution 4 - JenkinsMohamed NuurView Answer on Stackoverflow
Solution 5 - JenkinsIgorView Answer on Stackoverflow
Solution 6 - JenkinsDaishiView Answer on Stackoverflow