Matrix job REST API doesn't work when building with parameters

I make use of Matrix Jobs as I use a single codebase for multiple clients, with client specific settings coming from env files. They work pretty well, with some downsides.

One issue I’m facing is that the REST API simply doesn’t work. I have the correct credentials (I can successfully use them in a normal job) and I get the URL from the REST API page, having clicked through on one of the client axis

It gives and URL like the below, for building with parameters

http://myjenkins.com:8080/job/MatrixJob/Client=aClientName/buildWithParameters

It always gives a 500 status. Interestingly, the URL to use to initiate a build without parameters, does work.

Now here is what is confusing. The clients are setup as a user-defined axis, with a label of “Client” and there is a list of client names. This is used as a parameter itself when I trigger a build. I select a git branch and the clients I want to deploy to.

Clicking into an axis (a client) means I get the specific REST API URL for that client, which is fine, but I’d also want to use the base job URL, and pass the client names as a parameter for the axis, but that never works either

eg

http://myjenkins.com:8080/job/MatrixJob/buildWithParameters?Client=aClientName&branch=master

this is accepted and does indeed create a job, but the client param doesn’t work, and the job starts with no clients selected. I have the below error in the console

No such property: aClientName for class: groovy.lang.Binding
09:52:45 groovy.lang.MissingPropertyException: No such property: aClientName for class: groovy.lang.Binding
09:52:45 	at groovy.lang.Binding.getVariable(Binding.java:63)
09:52:45 	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:285)
09:52:45 	at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:375)
09:52:45 	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:379)
09:52:45 	at org.kohsuke.groovy.sandbox.impl.Checker$checkedGetProperty.callStatic(Unknown Source)
09:52:45 	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:55)
09:52:45 	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:197)
09:52:45 	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:233)
09:52:45 	at Script1.run(Script1.groovy:1)
09:52:45 	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runScript(GroovySandbox.java:195)
09:52:45 	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.run(GroovySandbox.java:363)
09:52:45 	at hudson.matrix.FilterScript.evaluate(FilterScript.java:45)
09:52:45 	at hudson.matrix.FilterScript.apply(FilterScript.java:85)
09:52:45 	at hudson.matrix.Combination.evalGroovyExpression(Combination.java:102)
09:52:45 	at hudson.matrix.Combination.evalGroovyExpression(Combination.java:91)
09:52:45 	at hudson.plugins.matrix_configuration_parameter.DefaultMatrixCombinationsParameterValue.combinationExists(DefaultMatrixCombinationsParameterValue.java:82)
09:52:45 	at hudson.plugins.matrix_configuration_parameter.MatrixCombinationsParameterMatrixBuildListener.doBuildConfiguration(MatrixCombinationsParameterMatrixBuildListener.java:57)
09:52:45 	at hudson.matrix.listeners.MatrixBuildListener.buildConfiguration(MatrixBuildListener.java:70)
09:52:45 	at hudson.matrix.DefaultMatrixExecutionStrategyImpl.filterConfigurations(DefaultMatrixExecutionStrategyImpl.java:188)
09:52:45 	at hudson.matrix.DefaultMatrixExecutionStrategyImpl.run(DefaultMatrixExecutionStrategyImpl.java:123)
09:52:45 	at hudson.matrix.MatrixBuild$MatrixBuildExecution.doRun(MatrixBuild.java:375)
09:52:45 	at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:526)
09:52:45 	at hudson.model.Run.execute(Run.java:1895)
09:52:45 	at hudson.matrix.MatrixBuild.run(MatrixBuild.java:323)
09:52:45 	at hudson.model.ResourceController.execute(ResourceController.java:101)
09:52:45 	at hudson.model.Executor.run(Executor.java:442)

So, how do i fix this?

I would love to use pipelines, but no matter what I try, I am unable to create a pipeline job with a branch and user-defined axis parameter, where I can pick my git branch and a check list fo clients to build the job for.

In Classical Matrix jobs you can’t just trigger a single axis. You can only trigger the whole job. It will then build all axis.
An axis is not a parameter of the job so this can’t work

Interestingly, the URL to use to initiate a build without parameters, does work.

Does it really trigger just the axis of the job? I tried but it does nothing for me. The job appears in the queue and then disappears.

My Matrix Job (no idea if its “classical” or not) only has a single axis, a list of client names. where I am able to select one or more at any time. Selecting 5 would create 5 jobs, one for each client name.

Does it really trigger just the axis of the job?

Yup.

You’re using classical matrix jobs.
OK so when you trigger the job it will start builds for all configured clients but you want to only start a single client.

As you might have noticed there is no Build Now link on a single job of an axis (i.e. when you go to http://myjenkins.com:8080/job/MatrixJob/Client=aClientName) . So consequently you can’t trigger just this single job. You can post to the url http://myjenkins.com:8080/job/MatrixJob/Client=aClientName/build but it does nothing for me. When I start it with a delay I can see the job in the queue but then it is never started.

With pipeline jobs it should be fairly easy to achieve what you want.

I would love to use pipelines, but the documentation is simply terrible. There are 2 different syntaxes to use, no idea which one is “correct” and from the various attempts Ive tried, using examples I’ve Googled and asked ChatGPT, there simply isn’t a way to replicate this matrix job setup.

If you know a way to replicate it, I’d love your input, as pipelines is really making me feel dumb right now.

I need 2 parameters that I can manually specify; a git branch/tag from a single prive repo (ideally using a list of the actual branches from the repo) and a list of client names that I can manually select one or more from. Sounds easy, but I’m struggling to understand how to make this script

Just a small snippet with scripted pipeline.
This assumes you have installed Active Choices plugin and defined a parameter with name client that provides the list of clients that can be built. That plugin would even allow you to dynamically calculate the clients that can be built.
Active choices allows to use groovy to calculate the possible parameters values. So this could potentially allow you to get the available branches of the repo.

Then all you need to do is loop over the clients and execute them in parallel. Ideally you run each client on a different agent so maybe you need some mapping from client to agent. But scripted pipeline is just groovy (more or less)

clients = params.client.split(",")
branch = params.branch

clientBuilds = [:]

clients.each { client ->
    clientBuilds[client] = {
        node("linuxx86_64") {
            // here are the steps that you would run in your matrix job under `Build Steps`. But now you can also decide to  run some things only for a certain client in a much simpler way.
            sh "echo build client $client on branch $branch"
        }
    }
}


parallel clientBuilds