12

I'm trying to automatically trigger 'Branch Indexing' on a Multibranch Pipelines job in Jenkins.

At the moment, only one method seems to actually work, which is polling, but I am unable to do that and polling is a bad solution anyway.

The plug-in doesn't support 'Trigger builds remotely (e.g., from scripts)' (options are not saved), so I cannot trigger it via a web hook on push etc.

I tried creating a 'trigger' freestyle build on the repo but the 'Post-build Actions - Build other projects' claims the Multibranch Pipeline project is not a buildable project.

If polling is the only way I can do this, then I need to disable automatic SCM triggering (otherwise we get duplicate builds when we re-index) because I'll need to enable web hook triggering on the branch projects.

But that doesn't work, because I'm setting up the web hook via a pipeline script in the branch project, and you need to have built it at least once to have that property registered.

I've been going around in circles for a while, so hopefully I've just missed something obvious, but any help would be appreciated.

I imagined being able to do one of the following

  • Somehow trigger the multi-branch project as a downstream project

  • Poll the multibranch project, and only build branch projects which have not been built before

Cheers

StephenKing
  • 36,187
  • 11
  • 83
  • 112
Lee Winder
  • 857
  • 12
  • 35

3 Answers3

9

The method ComputedFolder.scheduleBuild() can be invoked from a groovy script.

I have just triggered branch indexing in one multibranch pipeline project from the groovy code in a different multibranch pipeline project, which is then triggering a downstream build in that project.

The code is something like:

@NonCPS
void scanRepo(String downStreamProjectName) {
    Jenkins.instance.getItemByFullName(downStreamProjectName).scheduleBuild()
}
...
String downStreamProject = 'my-folder/my-multibranch-project'
String downStreamJob = "${downStreamProject}/${env.BRANCH_NAME}"
if (Jenkins.instance.getItemByFullName(downStreamJob) == null) {
    scanRepo(downStreamProject)
    while (Jenkins.instance.getItemByFullName(downStreamJob) == null) {
        sleep(1)
    }
}
build([job: downStreamJob, wait: false, quietPeriod: 0])

Notice that Jenkins.instance.getItemByFullName(downStreamProjectName) is the WorkflowMultiBranchProject which is not Serializable, so some care needs to be taken.

StephenKing
  • 36,187
  • 11
  • 83
  • 112
jjc
  • 310
  • 4
  • 8
  • Thanks! `Jenkins.instance.getItemByFullName(downStreamProjectName).scheduleBuild()` was exactly what I was looking for to trigger a rescan of my Multibranch Pipeline – Jason De Arte Jul 17 '17 at 20:52
  • Is there a way to wait for this job to finish rather than doing 'sleep(1)'? – Steve Magness Nov 17 '17 at 14:32
  • The only downside of this approach are the pretty evil permissions that it needs (through script approval). The `pipeline-build-step` plugin's `build` step unfortunately does not yet support it ([TODO in code](https://github.com/jenkinsci/pipeline-build-step-plugin/blob/3ff14391fe27c8ee9ccea9ba1977131fe3b26dbe/src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepExecution.java#L66)), which would be probably a better approach. – StephenKing Dec 04 '17 at 08:42
  • Probably this is a bit hard exactly because we cannot wait for it, as the call is non-blocking. – StephenKing Dec 04 '17 at 08:43
3

Based on @jjc's answer, I've created a version using the build step also for triggering the scan:

String downStreamProject = 'my-folder/my-multibranch-project'
String downStreamJob = "${downStreamProject}/${env.BRANCH_NAME}"
if (Jenkins.instance.getItemByFullName(downStreamJob) == null) {
    // we would need "wait: true", which is not possible as of now
    // https://github.com/jenkinsci/pipeline-build-step-plugin/blob/3ff14391fe27c8ee9ccea9ba1977131fe3b26dbe/src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepExecution.java#L66
    build job: downStreamProject, wait: false
    // continue only once the expected job appears
    while (Jenkins.instance.getItemByFullName(downStreamJob) == null) {
        sleep(1)
    }
}
build downStreamJob

This requires the following signatures to be approved:

  • method jenkins.model.Jenkins getItemByFullName java.lang.String
  • staticMethod jenkins.model.Jenkins getInstance
StephenKing
  • 36,187
  • 11
  • 83
  • 112
0

The easiest option by far (that I'm aware of) is to remotely tell the Jenkins Git plugin that there's a new commit for a defined repository. However, this will not trigger Jenkins to start a job immediately. What happens is that the Git plugin starts (re-)indexing the specific repository. The Jenkins job is then started if changes are detected.

From your repository (GitHub, GitLab, etc.) you should trigger the following URL:

http://my-jenkins-host/git/notifyCommit?url=git@gitlab.example.com:group/repository.git&delay=0sec

The value for url must match the SCM URL you configured in the Jenkins job (Git plugin)!

Gotcha: it may be that your Jenkins is not deployed under the root context (/) in which case the URL would be http://my-jenkins-host/context-path/git/...

Marcel Stör
  • 22,695
  • 19
  • 92
  • 198
  • Can you explain what is configurable in this url - http://my-jenkins-host/git/notifyCommit?url=git@gitlab.example.com:group/repository.git&delay=0sec? For eg http:///git/notifyCommit?url=&delay=0s is this correct? Also how to trigger this URL? What are headers? Can you give a working example? in python preferably? Thanks – Chaitanya Bapat Mar 06 '20 at 03:55