19
votes

In a normal freestyle project, I configure the SCM plugin to point to the Git repo that I want to release, and I enable the "Poll SCM" option, which allows me to configure a Stash webhook to tell Jenkins whenever there has been a change to that repo. In this way, the job can be triggered whenever a change is pushed to the repo.

But when I use a workflow instead of a freestyle project, the SCM of the code that I need to build is specified programmatically in the groovy workflow script, which means that it is not listening for the Stash webhook. Instead, the SCM that is configured directly in the workflow is the SCM of the groovy script itself, which is different than the codebase that I am trying to build/release, so I don't want the trigger to be based on that.

node('docker_builder') {
    git url: serviceRepo
    releaseVersion = getVersion()
    pipelineSpec = getPipelineSpec()
    sh "./gradlew clean build pushDockerImage"
}

Any ideas about how to achieve SCM polling when using the workflow plugin?

1

1 Answers

33
votes

I have resolved this question with lots of research and experimentation. This documentation got me on the right track: https://github.com/jenkinsci/workflow-scm-step-plugin/blob/master/README.md. It says:

Polling is supported across multiple SCMs (changes in one or more will trigger a new build), and again is done according to the SCMs used in the last build of the workflow."

This means that SCM polling is still supported with a Jenkins workflow, but unlike a normal freestyle project, you have to run it once manually before it starts listening for SCM changes. This makes sense because the SCM's are defined in Groovy code; they are not known until they run once.

One tricky element of this is that you can define many SCM's in your workflow. For example, I have three: one for the service itself, a deployment script, and the Groovy workflow DSL. By default, changes to any of those three SCM's would cause the "SCM poll" option to trigger a build, which may not be desirable. Luckily, setting the "poll: false" option on the "git" step in the Groovy code will disable polling on that repo. If you are reading your Groovy DSL from an SCM, then you can disable polling on that repo by clicking "additional behaviors" in the Jenkins UI and adding "Don't trigger a build on commit notifications".

Another tricky element is that the Stash web hook plugin by default includes the SHA1 hash code of the commit in the RESTful URL that it hits Jenkins with. Unfortunately, Jenkins makes the mistake of using that same commit code when it tries to pull any of the multiple SCM's that you may have defined. The hashcode is of course only relevant to one SCM, so it breaks. You can get around this by setting "Omit SHA1 Hash Code" in the Stash web hook plugin. Then Jenkins will just use the latest commit on whatever branch you build from in each of your SCM's.