A hands-on experience with Configure Blocks in Jenkins Job DSL.

Jenkins Job SDL is a crown jewel of all the Jenkins plugins. I had a basic write up about it already, and another one in regards to DSL script properties.

This post is an example of using Configure Blocks. I’ll make an effort an try to explain what Configure Blocks are with my own words.

Basically, the whole DSL language output is a job configuration XML file. You are given a high level API to shape out that XML, that’s it. In some cases, where there’s no simple high level API available yet, you can use a bit lower level methods to mess around with resulting XML. That’s exactly what configure blocks are - a fallback mechanism to squeeze more juice out of Job DSL plugin.

Here’s an example, a default configuration of Git plugin will not update submodules recursively and will use default 10 minutes timeout for submodules update operation.

Default Submodule Update Configuration

Job DSL provides an API to enable recursive submodules update. This is how you can use it in DSL

job {
    scm {
        git {
            remote {
                url("git-remote-url")
            }
            branch("branch-name")

            // All submodules recursively
            recursiveSubmodules(true)
        }
    }
}

That was easy. Here’s how the Jenkins job will look like now.

Default Submodule Update Configuration

What if you want to change default timeout for submodules operations now? Unfortunately there’s no DSL command for that yet. This is exactly the case where you’d want to use Configure Block. Scanning through Configure Block examples, I have found this one. Looks like it’s quite easy to add new nodes to the job XML, but you have to figure out how to name those nodes first. The best way to find that out is to modify the job via Jenkins UI and then look at the job XML. So open the job configuration page in the browser, type in the 20 minutes custom timeout value and click save.

Default Submodule Update Configuration

Now it’s time to locate the XML on file system. All the jobs data is located in JENKINS_HOME, the easiest way to find Jenkins Home location is again via Jenkins UI. Go to Jenkins > Manage Jenkins > Configure System and have a look at the top of the page.

Default Submodule Update Configuration

Navigate to Jenkins Home, then to jobs directory, then find the directory of your particular job, this is very straightforward task, finally you will see config.xml in that directory, open it and have a look. This is the node you are looking for

<scm class="hudson.plugins.git.GitSCM" plugin="git@2.3.5">
    <!--...-->
</scm>

Specifically you are interested in this block of code

<extensions>
      <hudson.plugins.git.extensions.impl.SubmoduleOption>
        <disableSubmodules>false</disableSubmodules>
        <recursiveSubmodules>true</recursiveSubmodules>
        <trackingSubmodules>false</trackingSubmodules>
        <timeout>20</timeout>
      </hudson.plugins.git.extensions.impl.SubmoduleOption>
</extensions>

See that <timout>20</timeout> node? This is exactly what you want to generate using Configure Block. This is how you can do that

job {
    scm {
        git {
            remote {
                url("git-remote-url")
            }
            branch("branch-name")

            // All submodules recursively
            recursiveSubmodules(true)

            // Increase submodule clone timeout using config block (set 20m, default is 10m)
            configure { node ->
                // node represents <hudson.plugins.git.GitSCM>
                node / 'extensions' << 'hudson.plugins.git.extensions.impl.SubmoduleOption' {
                    timeout 20
                }
            }
        }
    }
}

That looks easy, doesn’t it? But hold on a sec before you celebrate. Run a DSL script first then have a look at resulting XML before looking at job configuration via Jenkins UI. Locate the SCM node again

<scm class="hudson.plugins.git.GitSCM">
    <!--Skipped nodes-->
    <disableSubmodules>false</disableSubmodules>
    <recursiveSubmodules>true</recursiveSubmodules>
    <!--Skipped nodes-->
    <extensions>
        <hudson.plugins.git.extensions.impl.SubmoduleOption>
            <timeout>20</timeout>
        </hudson.plugins.git.extensions.impl.SubmoduleOption>
    </extensions>
</scm>

Hm… Looks a bit strange doesn’t it? The disableSubmodules and recursiveSubmodules nodes are outside of hudson.plugins.git.extensions.impl.SubmoduleOption for some reason. At least the values look right. So now go ahead and open the job configuration in Jenkins UI or hit refresh if you had it open all this time.

Default Submodule Update Configuration

Wait… What did just happen there? The recursive update checkbox is cleared!

Let’s have a look at job XML one more time.

<scm class="hudson.plugins.git.GitSCM" plugin="git@2.3.5">
    <!--Skipped nodes-->
    <extensions>
      <hudson.plugins.git.extensions.impl.SubmoduleOption>
        <disableSubmodules>false</disableSubmodules>
        <recursiveSubmodules>false</recursiveSubmodules>
        <trackingSubmodules>false</trackingSubmodules>
        <timeout>20</timeout>
      </hudson.plugins.git.extensions.impl.SubmoduleOption>
    </extensions>
</scm>

Well, the scm node is moved up in the XML and is changed a bit. Also, the recursiveSubmodules as well as disableSubmodules are moved inside the hudson.plugins.git.extensions.impl.SubmoduleOption node, but somehow recursiveSubmodules has lost its custom value in the process. Whatever Jenkins is doing under the hood is a mystery for me. This may be a bug in Jenkins Job DSL plugin or a known limitation. Brief search in project JIRA and discussion group didn’t come back with any results. That means if you are working with Configure Blocks, keep the following in mind

When changing one particular node, either do all changes via Job DSL API or via Configure Block, but never mix the two.

If you want to have both recursive submodule update and custom timeout configured, set both of them via Configure Block.

job {
    scm {
        git {
            remote {
                url("git-remote-url")
            }
            branch("branch-name")

            // Increase submodule clone timeout using config block (set 20m, default is 10m)
            configure { node ->
                // node represents <hudson.plugins.git.GitSCM>
                node / 'extensions' << 'hudson.plugins.git.extensions.impl.SubmoduleOption' {
                    recursiveSubmodules true	// Clone submodules recursively
                    timeout 20
                }
            }
        }
    }
}


blog comments powered by Disqus

Published

30 May 2015

Category

Mobile CI

Tags