23

I have quite a few free-style jobs in Jenkins that I would like to convert to multi-configuration jobs so I can build across multiple platforms under one job. These jobs specify quite a few build parameters and I would like to not have to set them up manually again by creating new multi-configuration jobs. Each job is currently limiting their builds to the platform we've been building on and the only other option I see is to clone the existing job and change the restriction to the new platform. This isn't ideal as I'll need to maintain 2 jobs where the only difference is the target platform.

I don't see a way to do this via the UI, but wondering if there is another way.

Johan Dahlin
  • 21,541
  • 5
  • 35
  • 52
RC.
  • 25,495
  • 8
  • 69
  • 90

3 Answers3

24

As far as I know, there's no way to convert the type of job in the UI. You'll have to either edit the job's config.xml, or copy and edit the config file and create a new job based on the edited configuration.

You'll have to check the differences between a free-style and multi-configuration job with the various settings that you use. It might be as simple as changing the top-level element in config.xml from project to matrix-project.

If you edit the existing job configuration, you'll need to either do it while Jenkins is offline, or tell Jenkins to reload its configuration via Manage Jenkins -> Reload Configuration from Disk.

If you decide to create new jobs, this previous question might be helpful once you figure out what edits need to be made. Specifically this answer describes how to upload a config file to create a new job.

Community
  • 1
  • 1
Dave Bacher
  • 14,787
  • 2
  • 60
  • 78
  • Though I didn't actually try this, it appears the process you've outlined would work. I decided to just go ahead and do them via the UI. I felt this approach was a little risky and I may end up with subtle issues down the road. Thanks for the response. – RC. Oct 04 '11 at 11:28
  • And with the new "Manage Old Data" feature, it should show stuff which was obsoleted by the job type change. – reechard Dec 19 '12 at 00:22
  • 1
    Works well. Also added the desired element and removed the to save having to do any UI editing. However, it does lose the build history for the job. – OrangeDog Oct 07 '13 at 16:00
  • I tried this with Jenkins 1.647 and all the previous builds had an incorrect timestamp and were red. The previous releases were also no longer logged. – David V Mar 02 '16 at 23:29
4

Just a note for those who would wish to switch from maven to freestyle job.

  1. Change maven2-moduleset tag to project.
  2. Remove tags: rootModule, goals, mavenValidationLevel (should be close to each other).
  3. Merge prebuilders and postbuilders into builders.
Nux
  • 7,204
  • 5
  • 47
  • 62
  • Hrm, after doing this - "manage jenkins" reports unused data, of which a cleanup crashes with an error saying "no parent found", I wonder if there's another element/attribute to tweak? – Mark Derricutt Dec 11 '13 at 04:50
  • 1
    You might have some plugins which mess up (and you need to remove it's tags manually). Or you might need to use option "reload configuration from disk" if you haven't. – Nux Dec 11 '13 at 14:35
  • If you want to keep your builds, use `grep -rl "hudson.maven.MavenModuleSetBuild" .|xargs sed -i 's/hudson.maven.MavenModuleSetBuild/build/g'` in your `builds` folder – MrPowerGamerBR Jun 02 '19 at 19:01
2

I just wrote a script to convert about 10000 Jenkins Jobs from Maven Job Type to Freestyle. Please do not use it blindly. You might lose configuration options or end up in a broken Jenkins setup. The Python Part takes a config xml as argument and overwrites the same file with the converted data. I ran this live on the Jenkins Filesystem with the following command:

cd /path/to/jenkins/jobs

find * -maxdepth 2 -name config.xml -exec /path/to/maven2freestyle.py {} \;

WARNING Again. This might break your Jenkins! Please keep a Backup!

#!/usr/bin/env python2

import copy
import sys
from lxml import etree
from lxml.etree import fromstring, tostring
from StringIO import StringIO

def parseXML(xmlFile):
    print(xmlFile)
    f = open(xmlFile)
    xml = f.read()
    f.close()

    e = etree.parse(xmlFile)
    root = e.getroot()

    if root.tag != 'maven2-moduleset':
        #print("WARNING: Skipping non Maven Project")
        return

    #change project type
    root.tag = "project"
    if 'plugin' in root.attrib:
        del root.attrib["plugin"]

    #get maven data
    rootModule = root.find('./rootModule')
    rootPOM = root.find('./rootPOM')
    goals = root.find('./goals')
    mavenName = root.find('./mavenName')
    mavenOpts = root.find('./mavenOpts')

    # merge prebuilders into builders
    prebuilders = root.findall("./prebuilders/*")
    builders = etree.Element("builders")
    root.insert(99, builders)
    if len(prebuilders) > 0:
        builders.append(copy.deepcopy(prebuilders[0]))

    #create maven builder
    maven = etree.Element("hudson.tasks.Maven")

    if not goals is None:
        etree.SubElement(maven, "targets").text = goals.text
    if not mavenName is None:
        etree.SubElement(maven, "mavenName").text = mavenName.text
    if not rootPOM is None:
        etree.SubElement(maven, "pom").text = rootPOM.text
    if not mavenOpts is None:
        etree.SubElement(maven, "javaOpts").text = mavenOpts.text

    builders.append(maven)

    #cleanup
    prebuilder = root.findall("./prebuilders")
    if len(prebuilder) > 0:
        root.remove(prebuilder[0])
    if not rootModule is None:
        root.remove(rootModule)
    if not rootPOM is None:
        root.remove(rootPOM)
    if not goals is None:
        root.remove(goals)
    if not mavenName is None:
        root.remove(mavenName)
    if not mavenOpts is None:
        root.remove(mavenOpts)

    e.write(sys.argv[1], xml_declaration=True, pretty_print=True, encoding='utf-8', method="xml")

if __name__ == "__main__":
    parseXML(sys.argv[1])
Lukas
  • 41
  • 5