Jenkins - Groovy pipeline - Using FilePath gives Could not find matching constructor - jenkins

Building on this suggestion:
Using FilePath to access workspace on slave in Jenkins pipeline I am trying to get the files that are dropped into the workspace by git, and iterate through those files using eachFileRecurse, by passing in the adjusted folder. However, when calling into FilePath, I get errors.
import groovy.io.FileType
import java.io.File
import java.lang.Object
import hudson.FilePath
import jenkins.model.Jenkins
def createFilePath(path) {
return new FilePath(Jenkins.getInstance().getComputer(env['NODE_NAME']).getChannel(), path);
}
#NonCPS // has to be NonCPS or the build breaks on the call to .each
def getFiles(dirLoc) {
def dir = new File (dirLoc)
def list = []
dir.eachFileRecurse (FileType.FILES)
{file -> if (file.name.endsWith('.txt')) {list << file}}
return list
}
I get this error
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.io.File(hudson.FilePath)
at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1737)
at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1537)
I cannot figure out what I am missing here to make this work. Thanks in advance!

There is no Constructor for java.io.file with hudson.FilePath as a parameter.
Refer to java doc at following link: https://docs.oracle.com/javase/7/docs/api/java/io/File.html

Related

How to fix "java.io.NotSerializableException" on running remote library function in Jenkins pipeline

I am setting up a Jenkins Pipeline, which calls an external library with a compare XML function written in Groovy that utilises xmlunit.
The function looks as follows:
import java.util.List
import org.custommonkey.xmlunit.*
// Gives you a list of all the differences.
#NonCPS
void call(String xmlControl, String xmlTest) throws Exception {
String myControlXML = xmlControl
String myTestXML = xmlTest
DetailedDiff myDiff = new DetailedDiff(compareXML(myControlXML,
myTestXML));
List allDifferences = myDiff.getAllDifferences();
assertEquals(myDiff.toString(), 0, allDifferences.size());
}
However when running the pipeline in Jenkins it returns a java.io.NotSerializableException.
Checking StackOverflow it seemed like adding a the #NonCPS annotation might help.
But sadly it did not make a difference.
What more could I try to resolve the java.io.NotSerializableException?

Read .txt file from workspace groovy script in Jenkins

I am new to Jenkins and to groovy scripting, I want to read a .txt file which is located in the workspace of one of the jobs. I am trying to do this way:
myfile = Jenkins.instance.getJob('JobName').workspace.readFileFromWorkspace('file.txt');
But leads to the following error:
groovy.lang.MissingMethodException: No signature of method:
hudson.FilePath.readFileFromWorkspace() is applicable for argument
types: (java.lang.String) values: [file.txt]
Try this:
file = new File("${Jenkins.instance.getJob('JobName').workspace}/file.txt").text
I was struggling to make it work for the pom modules for a file in the workspace, in the
Extended Choice Parameter. Here is my solution with the printlns:
import groovy.util.XmlSlurper
import java.util.Map
import jenkins.*
import jenkins.model.*
import hudson.*
import hudson.model.*
try{
//get Jenkins instance
def jenkins = Jenkins.instance
//get job Item
def item = jenkins.getItemByFullName("The_JOB_NAME")
println item
// get workspacePath for the job Item
def workspacePath = jenkins.getWorkspaceFor (item)
println workspacePath
def file = new File(workspacePath.toString()+"\\pom.xml")
def pomFile = new XmlSlurper().parse(file)
def pomModules = pomFile.modules.children().join(",")
return pomModules
} catch (Exception ex){
println ex.message
}

Groovy DSL for Extended choice parameter plugin

I'm converting my Jenkins job configurations into code using groovy DSL. Am able to convert all the code except extended choice parameter plugin configuration.
I've a groovy script which does some API calls and get the values and return as choice to the defied parameter in the job. I've tested it and working fine. But, when I tried to automate/convert the same into Groovy DSL am not getting enough support from the plugin rather I haven't find any document which helps me with this situation.
kindly help.
I went through the same process a couple of months ago. I found this article tremendously useful - http://www.devexp.eu/2014/10/26/use-unsupported-jenkins-plugins-with-jenkins-dsl.
Here's a sample code snippet:
configure {
project->
project / 'properties' << 'hudson.model.ParametersDefinitionProperty' {
parameterDefinitions {
'com.cwctravel.hudson.plugins.extended__choice__parameter.ExtendedChoiceParameterDefinition' {
name 'TARGET_ENVS'
quoteValue 'false'
saveJSONParameterToFile 'false'
visibleItemCount '15'
type 'PT_CHECKBOX'
value "${deployTargets}"
multiSelectDelimiter ','
projectName "${jobName}"
}
}
}
}
The article suggests appending the 'configure' code block at the end of your DSL job definition, however that didn't work for me. I ended up putting the code block at the start of the definition.
Good luck
Job DSL plugins allows you to add XML configuration to jobs config.xml files. You have to use configure closure and next specify whatever you want. For example I have such configuration:
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions>
<com.cwctravel.hudson.plugins.extended__choice__parameter.ExtendedChoiceParameterDefinition plugin="extended-choice-parameter#0.76">
<name>PRODUCT_REPO_URL</name>
<description>ssh URL of the product repository</description>
<quoteValue>false</quoteValue>
<saveJSONParameterToFile>false</saveJSONParameterToFile>
<visibleItemCount>10</visibleItemCount>
<type>PT_SINGLE_SELECT</type>
<groovyScript>import hudson.slaves.EnvironmentVariablesNodeProperty
import jenkins.model.Jenkins
Jenkins.get().globalNodeProperties.get(EnvironmentVariablesNodeProperty.class).envVars.get(&apos;PRODUCT_REPOSITORIES&apos;)</groovyScript>
<bindings></bindings>
<groovyClasspath></groovyClasspath>
<defaultGroovyScript>import hudson.slaves.EnvironmentVariablesNodeProperty
import jenkins.model.Jenkins
Jenkins.get().globalNodeProperties.get(EnvironmentVariablesNodeProperty.class).envVars.get(&apos;PRODUCT_REPOSITORY_DEFAULT&apos;)</defaultGroovyScript>
<defaultBindings></defaultBindings>
<defaultGroovyClasspath></defaultGroovyClasspath>
<multiSelectDelimiter>,</multiSelectDelimiter>
<projectName>try-to-upgrade-dependencies</projectName>
</com.cwctravel.hudson.plugins.extended__choice__parameter.ExtendedChoiceParameterDefinition>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
Now I can generate it by adding the following code:
configure {
project -> project / 'properties' << 'hudson.model.ParametersDefinitionProperty' {
parameterDefinitions {
'com.cwctravel.hudson.plugins.extended__choice__parameter.ExtendedChoiceParameterDefinition'(plugin: 'extended-choice-parameter#0.76') {
delegate.name('PRODUCT_REPO_URL')
delegate.description('ssh URL of the product repository')
delegate.quoteValue(false)
delegate.saveJSONParameterToFile(false)
delegate.visibleItemCount(10)
delegate.type('PT_SINGLE_SELECT')
delegate.groovyScript("""import hudson.slaves.EnvironmentVariablesNodeProperty
import jenkins.model.Jenkins
Jenkins.get().globalNodeProperties.get(EnvironmentVariablesNodeProperty.class).envVars.get('PRODUCT_REPOSITORIES')""")
delegate.defaultGroovyScript("""import hudson.slaves.EnvironmentVariablesNodeProperty
import jenkins.model.Jenkins
Jenkins.get().globalNodeProperties.get(EnvironmentVariablesNodeProperty.class).envVars.get('PRODUCT_REPOSITORY_DEFAULT')""")
delegate.multiSelectDelimiter(',')
delegate.projectName('try-to-upgrade-dependencies')
}
}
}
}
The final result:
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions>
<com.cwctravel.hudson.plugins.extended__choice__parameter.ExtendedChoiceParameterDefinition plugin="extended-choice-parameter#0.76">
<name>PRODUCT_REPO_URL</name>
<description>ssh URL of the product repository</description>
<quoteValue>false</quoteValue>
<saveJSONParameterToFile>false</saveJSONParameterToFile>
<visibleItemCount>10</visibleItemCount>
<type>PT_SINGLE_SELECT</type>
<groovyScript>import hudson.slaves.EnvironmentVariablesNodeProperty
import jenkins.model.Jenkins
Jenkins.get().globalNodeProperties.get(EnvironmentVariablesNodeProperty.class).envVars.get('PRODUCT_REPOSITORIES')</groovyScript>
<defaultGroovyScript>import hudson.slaves.EnvironmentVariablesNodeProperty
import jenkins.model.Jenkins
Jenkins.get().globalNodeProperties.get(EnvironmentVariablesNodeProperty.class).envVars.get('PRODUCT_REPOSITORY_DEFAULT')</defaultGroovyScript>
<multiSelectDelimiter>,</multiSelectDelimiter>
<projectName>try-to-upgrade-dependencies</projectName>
</com.cwctravel.hudson.plugins.extended__choice__parameter.ExtendedChoiceParameterDefinition>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>

Groovy Script to add new phase job to multi-job in Jenkins

For the already available multi-job in jenkins, need to add new phase jobs using Groovy Scripting. I have written the following groovy code which adds up an already existing job p25_deploy-1.
This code is working to create the multi-job but the phase job is not showing as mapped in the Jenkins UI. Where as if I see it config.xml, its created properly as expected except a tag <killPhaseOnJobResultCondition>. Not sure why the phase job is not mapped properly?
import jenkins.model.*
import hudson.model.*
import com.tikal.jenkins.plugins.multijob.*
import com.tikal.jenkins.plugins.multijob.PhaseJobsConfig.*
import com.tikal.jenkins.plugins.multijob.PhaseJobsConfig.KillPhaseOnJobResultCondition.*
import java.lang.String.*
import hudson.model.Descriptor;
import hudson.tasks.Builder;
def jenkinsInstance = jenkins.model.Jenkins.instance
def templateJobName = 'profile_p25'
def templateJob = jenkinsInstance.getJob(templateJobName)
// get MultiJob BuildPhases and clone each PhaseJob
builders = templateJob.getBuilders();
builders.each { b ->
if (b instanceof MultiJobBuilder){
def pj = b.getPhaseJobs()
hudson.model.Describable p1 = new PhaseJobsConfig("p25_deploy-1",null,
true,PhaseJobsConfig.KillPhaseOnJobResultCondition NEVER,null,false,false,null,0,false,true,null,false,false)
pj.add(p1)
}
}
templateJob.save()
// update dependencies
jenkinsInstance.rebuildDependencyGraph()
Any help will be really appreciated. Have tried many ways but was not able to figure out the problem with the script.
We can use DSL to create but I wanted it to be done in Groovy Scripting and moreover modify the existing job.
Blockquote
Yay! I am back with the answer for my question. Have tried this since very long time. Finally am able to make it though. I was aware that solution would be really simple but not able to figure out the hack of it.
import jenkins.model.*
import hudson.model.*
import com.tikal.jenkins.plugins.multijob.*
import com.tikal.jenkins.plugins.multijob.PhaseJobsConfig.*
import com.tikal.jenkins.plugins.multijob.PhaseJobsConfig.KillPhaseOnJobResultCondition.*
import java.lang.String.*
import hudson.model.Descriptor
import hudson.tasks.Builder
def jenkinsInstance = jenkins.model.Jenkins.instance
def templateJobName = 'profile_p25'
def templateJob = jenkinsInstance.getJob(templateJobName)
// get MultiJob BuildPhases and clone each PhaseJob
builders = templateJob.getBuilders();
builders.each { b -> if (b instanceof MultiJobBuilder)
{ def pj =
b.getPhaseJobs()
hudson.model.Describable newphase = new
PhaseJobsConfig(deploys[i],null,
true,null,null,false,false,null,0,false,false,"",false,false)
newphase.killPhaseOnJobResultCondition = 'NEVER'
pj.add(newphase)
}
}
templateJob.save()

Inject variable in jenkins pipeline with groovy script

I am building a jenkins pipeline and the job can be triggered by remote. I have the requirement to know which IP triggered the job. So I have a little groovy script, which returns the remote IP. With the EnvInject-plugin I can easily use this variable in a normal freestyle job, but how can I use this in the pipeline scirpt? I can't use the EnvInject-plugin with the pipeline-plugin :(
Here is the little script for getting the IP:
import hudson.model.*
import static hudson.model.Cause.RemoteCause
def ipaddress=""
for (CauseAction action : currentBuild.getActions(CauseAction.class)) {
for (Cause cause : action.getCauses()) {
if(cause instanceof RemoteCause){
ipaddress=cause.addr
break;
}
}
}
return ["ip":ipaddress]
You can create a shared library function (see here for examples and the directory structure). This is one of the undocumented (or really hard to find any documentation) features of Jenkins.
If you would put a file triggerIp.groovy in the directory vars, which is in the directory workflow-libs at the root level of JENKINS_HOME and put your code in that file.
The full filename then will be $JENKINS_HOME/workflow-libs/vars/ipTrigger.groovy
(You can even make a git repo for your shared libraries and clone it in that directory)
// workflow-libs/vars/ipTrigger.groovy
import hudson.model.*
import static hudson.model.Cause.RemoteCause
#com.cloudbees.groovy.cps.NonCPS
def call(currentBuild) {
def ipaddress=""
for (CauseAction action : currentBuild.getActions(CauseAction.class)) {
for (Cause cause : action.getCauses()) {
if(cause instanceof RemoteCause){
ipaddress=cause.addr
break;
}
}
}
return ["ip":ipaddress]
}
After a restart of Jenkins, from your pipeline script, you can call the method by the filename you gave it.
So from your pipeline just call def trigger = ipTrigger(currentBuild)
The the ipaddress will be, trigger.ip (sorry for the bad naming, couldn't come up with something original)

Resources