Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parameterize selector for copy artifacts in Jenkins pipeline

We're heavily using pipeline jobs in our Jenkins system and need to be able to parameterize the copyArtifacts step using the Build selector for Copy Artifact job parameter.

In the first place I found that - while the parameter returns a String - the copyArtifacts step required an instance of BuildSelector.

I found the BuildSelectorParameter.getSelectorFromXml method to convert the parameter into an instance of BuildSelector like:

properties([parameters([
    [$class: 'BuildSelectorParameter',
    defaultSelector: upstream(fallbackToLastSuccessful: true),
    description: '',
    name: 'copyArtifactSelector']])
])

@NonCPS
static BuildSelector getSelectorFromParam(String xmlText) {
    BuildSelectorParameter.getSelectorFromXml(xmlText)
}

node {
    def selector = getSelectorFromParam(params.copyArtifactSelector)
    copyArtifacts(
            projectName: 'sourceJob',
            selector: selector
    )
}

However I just realized that the BuildSelector which is created is not Serializable. Therefore I'm getting now the expected exception:

hudson.plugins.copyartifact.TriggeredBuildSelector
Caused: java.io.NotSerializableException: hudson.plugins.copyartifact.TriggeredBuildSelector
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:860)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)

After that I tried to check how the copy artifact plugin deals with that - unfurtunately I couldn't find any clue in the source code. Maybe it only works by chance? The methods to create a BuildSelector do not seem to create any kind of serializable class.

But maybe someone already came accross this issue and has a hint?

Edit

What I found so far:

  • If I store the BuildSelector object in some variable it'll throw me the NotSerializableException.
  • However if I do not pass it to some variable first but do the call in the method call to copyArtifacts the NotSerializableException will not occur - at least not for now:

    node {
        copyArtifacts(
                projectName: 'sourceJob',
                selector: getSelectorFromParam(params.copyArtifactSelector)
        )
    }
    

Thoughts

Is there probably even a hidden bug in the Copy Artifact plugin which could cause NotSerializableException exceptions to occur - or am I missing something?

Question

Is it safe to use my getSelectorFromParam method like done in the updated example? If it is not safe, is there a safe solution?

like image 616
Joerg S Avatar asked Aug 09 '18 13:08

Joerg S


People also ask

Under which section is the copy artifacts option present in Jenkins?

Next you need to install the Copy Artifact plugin in the Manage Plugins section of Jenkins. Go to "[PROJECT-NAME]-Output" > configure and add a new build step. Because you have installed the Copy Artifact plugin you should see an option called 'copy artifacts from another project' in the drop down menu.

How do you pass parameters in Jenkins pipeline?

Using build parameters, we can pass any data we want: git branch name, secret credentials, hostnames and ports, and so on. Any Jenkins job or pipeline can be parameterized. All we need to do is check the box on the General settings tab, “This project is parameterized”: Then we click the Add Parameter button.

What is the use of copy artifact plugin in Jenkins?

The plugin lets you specify which build to copy artifacts from (e.g. the last successful/stable build, by build number, or by a build parameter). You can also control the copying process by filtering the files being copied, specifying a destination directory within the target project, etc.


1 Answers

I had the same issue after spending a good few hours on this I found this and it worked perfectly for me.

The name of Build selector for Copy Artifact job parameter here is copyArtifactSelector and up stream job name here is sourceJob:

    copyArtifacts(projectName: 'sourceJob',
                  selector: [$class: 'ParameterizedBuildSelector', 
                             parameterName: 'copyArtifactSelector'] );

Note : plugin="[email protected]"

EDIT: In the meantime - using copyartifact V1.43 - the following syntax is supported:

    copyArtifacts(projectName: 'sourceJob',
                  selector: buildParameter('copyArtifactSelector'));
like image 119
David Tam Avatar answered Oct 02 '22 23:10

David Tam