pitseeker
pitseeker

Reputation: 2543

Copy Jenkins Multijob job and all its downstream jobs via groovy job

I am trying to write a Jenkins job (say CopyJob) that copies another job (in this job using the Multijob plugin) and also copies all its downstream jobs to new jobs. The idea is to have a Multijob that serves as a template so it can be copied to new Multijobs (e.g. for a specific branch or feature).

See:

MultiJob_Template
   |
   +-- Sub1_Template
   +-- Sub2_Template
   +-- Sub3_Template

CopyJob (Parameters: NewSuffix)

When manually triggering the "CopyJob" it shall create a new MultiJob with new SubJobs:

MultiJob_BranchXYZ
   |
   +-- Sub1_BranchXYZ
   +-- Sub2_BranchXYZ
   +-- Sub3_BranchXYZ

So far I was successful with copiing the Multijob and copiing the Subjobs, but I couldn't find a way to make the new Multijob actually depend on the new Subjobs. My code (for the CopyJob groovy script) so far is:

import jenkins.model.*
import com.tikal.jenkins.plugins.multijob.*

def templateJobName = "MultiJob_Template"

// Retrieve parameters 
def newSfx = build.buildVariableResolver.resolve("NewSuffix")
def templateJob = Jenkins.instance.getJob(templateJobName)

// copy Multijob
def newJob = Jenkins.instance.copy(templateJob, 'Multijob_' + newSfx)
newJob.save()

// copy all downstreamjobs
def subs = newJob.getDownstreamProjects()
for (s in subs) {
  def oldSubJob = Jenkins.instance.getJob(s.getDisplayName())
  def newSubJob = Jenkins.instance.copy(oldSubJob, s.getDisplayName().replaceFirst(/Template/, newSfx))
  newSubJob.save()

  // how to update the MultiJob_newSfx DownstreamJoblist to use the newSubJob?
  // ????
}

Upvotes: 1

Views: 2830

Answers (2)

David I.
David I.

Reputation: 4767

I am using the Scriptler plugin in Jenkins with the parameters:

NewSuffix, TemplateStr, and templateJobName. I tweaked the script from pitseeker to use these and work around a runtime issue in Jenkins v1.580.3:

import jenkins.model.*
import com.tikal.jenkins.plugins.multijob.*

def jenkinsInstance = jenkins.model.Jenkins.instance 

// Retrieve parameters
def newSfx = NewSuffix
println "using new suffix " + newSfx

// create new MultiJob
def templateJob = Jenkins.instance.getJob(templateJobName)
println "Found templateJob " + templateJobName

def newJobName = templateJobName.replaceFirst(/$TemplateStr/, newSfx)

def newJob = Jenkins.instance.copy(templateJob, templateJobName + newSfx)
newJob.save()
println "Copied template job to " + newJob.getName()

// get MultiJob BuildPhases and clone each PhaseJob
def builders = newJob.getBuilders()
builders.each { builder ->
    builder.getPhaseJobs().each() { pj ->
      def pjNameOrig = pj.getJobName()
      def pjNameNew = pjNameOrig.replaceFirst(/$TemplateStr/, newSfx)
      println "pjNameOrig = $pjNameOrig, pjNameNew=$pjNameNew"

      if (pjNameNew != pjNameOrig)
      {
          println "cloning phasejob: " + pjNameOrig

          def subTemplate = Jenkins.instance.getJob(pjNameOrig)

          def newSubJob = Jenkins.instance.copy(subTemplate, pjNameNew)
          newSubJob.save()
          pj.setJobName(newSubJob.getDisplayName())
      }
      else
      {
          println "Not cloning phasejob, keeping original job: " + pjNameOrig
      }
    }
}

// update dependencies
jenkinsInstance.rebuildDependencyGraph()

Upvotes: 2

pitseeker
pitseeker

Reputation: 2543

I actually managed to solve it myself. Maybe there are other ways too, but it seems best to step through the list of builders and then the list of PhaseJobs of the MultiJob template.

The code of the MultiJob plugin itself helped for this solution. It is also worth having a look at this question if you are looking for similar things.

import jenkins.model.*
import com.tikal.jenkins.plugins.multijob.*

def jenkinsInstance = jenkins.model.Jenkins.instance 
def templateJobName = "Multijob_Template"

// Retrieve parameters
def newSfx = build.buildVariableResolver.resolve("NewSuffix")

// create new MultiJob
def templateJob = Jenkins.instance.getJob(templateJobName)
def newJob = Jenkins.instance.copy(templateJob, 'Multijob_' + newSfx)
newJob.save()

// get MultiJob BuildPhases and clone each PhaseJob
def builders = newJob.getBuilders()
builders.each { builder ->
    builder.getPhaseJobs().each() { pj ->
      println "cloning phasejob: " + pj.getJobName()

      def subTemplate = Jenkins.instance.getJob(pj.getJobName())
      def newSubJob = Jenkins.instance.copy(subTemplate, pj.getJobName().replaceFirst(/Template/, newSfx))
      newSubJob.save()
      pj.setJobName(newSubJob.getDisplayName())
    }
}

// update dependencies
jenkinsInstance.rebuildDependencyGraph()

Upvotes: 2

Related Questions