What is the best way to bulk upgrade Jenkins projects?

We have hundreds of Jenkins projects (mainly created from several templates), often they need to make the same changes for all of them. for example today I need to add a step after assembly to remove the workspace at the end. Then I need to change the step to copy the build result to a shared drive in the Nexus repository.

What is the best way to apply such a massive transition to Jenkins projects?

+12
jenkins
source share
5 answers

Groovy is by far the best way to bulk update jobs. You may need to dig into the jenkins / plugin APIs a bit to find out what API calls you need to make, but the script console ( http: // yourJenkinsUrl / script ) provides an easy way to play around with the code until you get it right.

First, you can add / remove steps after the build by calling the getPublishersList() method for the job, and then calling the add / remove methods.

 def publishersList = Jenkins.instance.getJob("JobName").getPublishersList() publishersList.removeAll { it.class == whatever.plugin.class } publishersList.add(new PluginConstructor()) 

If you are not sure which publisher class you want to remove the workspace from, I would suggest manually adding the necessary configurations to one job and then running getPublishersList() from the script console for this job. You will see the class you are working with in the list, and then you can look at the API to see what it takes to create it.

Then you can view all your assignments and add a publisher by doing something like this:

 Jenkins.instance.getView("All Jobs").items.each { job -> //Maybe some logic here to filter out specific jobs job.getPublishersList().add(new PluginConstructor()) } 

Alternatively, you can use the Jenkins CLI API or the REST API, but to update the actions after the build, you will have to modify the project configuration XML file (which is not a trivial programmatic way) and then overwrite the job configuration using the new configuration file .

+7
source share

The REST API is quite powerful. The following sequence worked for me:

In the loop for all relevant projects (the list of projects is available, for example, via /api/xml?tree=jobs[name] ):

  • download config.xml via /job/{name}/config.xml
  • edit using your favorite XML editor with scripts (mine was xmlstarlet )
  • upload new config xml via /job/{name}/config.xml

A few random notes:

  • do * BACKUP * before doing anything
  • Maybe I could post an example bash script if anyone is interested

Good luck

EDIT> Example bash script:

 #!/bin/bash jenkinsUrlBase='http://user:token@jenkins' callJenkins() { # funcPath curl --silent --show-error -g "${jenkinsUrlBase}${1}" } postJenkinsFile() { # funcPath fileName curl --silent --show-error -g -d "@${2}" "${jenkinsUrlBase}${1}" } callJenkins '/api/xml?tree=jobs[name]' | xmlstarlet sel -t -v '//hudson/job/name' | while read projectName ; do echo "Processing ${projectName}..." origFile="${projectName}_old.xml" newFile="${projectName}_new.xml" callJenkins "/job/${projectName}/config.xml" > "$origFile" echo " - Updating artifactory url..." cat "$origFile" \ | xmlstarlet ed -P -u '//maven2-moduleset/publishers/org.jfrog.hudson.ArtifactoryRedeployPublisher/details/artifactoryUrl' -v "http://newServer/artifactory" \ > "${newFile}" if false ; then echo " - Commiting new config file..." postJenkinsFile "/job/${projectName}/config.xml" "$newFile" else echo " - Dry run: not commiting new config file" fi done 
+7
source share

You can use the configuration plugin that is designed for this.

It supports many configuration options.

+7
source share

You can edit the config.xml file with your favorite text tool (I use Python) and then reload the jenkins configuration.

In my setup, jobs are stored in ~/.jenkins/jobs/*/config.xml .

See: https://wiki.jenkins-ci.org/display/JENKINS/Administering+Jenkins

Here is a small example of updating foo to bar :

  </com.cwctravel.hudson.plugins.extended__choice__parameter.ExtendedChoiceParameterDefinition> <hudson.model.StringParameterDefinition> <name>additional_requirements</name> <description>foo</description> ... 

Scenario:

 #!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import absolute_import, division, unicode_literals, print_function import sys from lxml import etree from collections import defaultdict def change_parameter_description(config_xml_path, parameter_name, new_description): tree=etree.parse(config_xml_path) for tag in tree.findall('.//hudson.model.StringParameterDefinition'): name_tag=tag.find('./name') if not name_tag.text==parameter_name: continue description=tag.find('./description') description.text=new_description tree.write(config_xml_path) for config_xml_path in sys.argv[1:]: change_parameter_description(config_xml_path, 'additional_requirements', 'bar') 

In this small example, a regular expression would work, but if things span multiple lines, it's better to work with xml tools :-)

+6
source share

Other answers are good, but if you use pipelines, I would advise you to use Pipeline Shared Libraries .

We have all our work in the git repository. To develop a new function, we try it in a branch, since you can specify only one work per specific branch. When we need to update them, just merge with the master. Jobs are processed as code with the appropriate release process.

0
source share

All Articles