EnvInject Error using Jenkins evaluated Groovy script - jenkins

We have a evaluated Groovy script in Jenkins below:-
;
But the build is failing with error [EnvInject] - [ERROR] - [EnvInject] - [ERROR] - Problems occurs on injecting env vars as a build wrap: null
17:04:06 Finished: FAILURE.
Also how can I call the variable from Jenkins shell script to get last successful build date. -Thanks
def env = System.getenv()
def item = Jenkins.instance.getItem("")
def f=item.getLastFailedBuild()
println f.getTime()
def ff=env['item.getLastSuccessfulBuild()]
println ff.getTime().format("YYYY-MMM-dd HH:MM:SS")
println ff.getTime().format("dd-MM-yyyy")
def pa = new ParametersAction([new StringParameterValue('PARAMETER_NAME', ff)]);
Thread.currentThread().executable.addAction(pa)
println 'Script finished! \nenv variable

The easy answer is that on line 7 you have no closing quote here:
def ff=env['item.getLastSuccessfulBuild()]
However, that is not the last of your issues:
I don't think you want to use ff = env['item.getLastSuccessfulBuild()]'] but rather just a simple ff = item.getLastSuccessfulBuild()
You need to include the following import lines to be able to use the associated classes:
import jenkins.model.Jenkins
import hudson.model.ParametersAction
import hudson.model.StringParameterValue
The line item = Jenkins.instance.getItem("Fastlane_Test") doesn't work in my environment, even replacing "Fastlane_Test" with a job that exists.I've replaced it with item = Jenkins.instance.getItemByFullName("Fastlane_Test").
Also, for safety, you should test to ensure item isn't null
Finally, have you missed the Thread.currentThread().executable.addAction(pa) line out for a reason? You need to use it to add the new parameter to the running environment.
The following code should hopefully be a reasonable starting point, however please note that I've removed the line def env = System.getenv() since env isn't used anywhere else in the code later:
import jenkins.model.Jenkins
import hudson.model.ParametersAction
import hudson.model.StringParameterValue
def item = Jenkins.instance.getItemByFullName("Fastlane_Test")
if (item) {
def f=item.getLastFailedBuild()
println f.getTime()
def ff=item.getLastSuccessfulBuild()
println ff.getTime().format("YYYY-MMM-dd HH:MM:SS")
println ff.getTime().format("dd-MM-yyyy")
def pa = new ParametersAction([new StringParameterValue("LAST_GOOD", ff.getTime().toString())])
Thread.currentThread().executable.addAction(pa)
}
Hope you find this of assistance, although I see it's been a while since you posted the question.
Kind Regards

Thanks Nick!!
I added the below "execute system groovyscript" as part of Jenkins job and it worked:
import jenkins.model.Jenkins
`. def item = Jenkins.instance.getItem("Job")
def ff=item.getLastSuccessfulBuild()
println ff.getTime().format("yyyy-MM-dd")
def temp = ff.getTime().format("yyyy-MM-dd")
import hudson.model.*
def build = Thread.currentThread().executable
def pa = new ParametersAction([
new StringParameterValue("LAST_BUILD_DATE",temp)
])
build.addAction(pa)`

Related

Trigger Jenkins job on same node than parent with Groovy

In a Jenkins job, I want to trigger another Jenkins job from a Groovy script :
other_job.scheduleBuild();
But other_job is not launched on the same node than the parent job. How can I modify my script to launch other_job on the same node than the parent job ?
I used to do that with the "Trigger/call builds on other project" and "NodeLabel Parameter" plugins but I would like now to do that inside a script.
Firstly, check Restrict where this project can be run option in 'other_job' configuration - you must specify the same node name there.
Then, this should work:
import hudson.model.*
def job = Hudson.instance.getJob('other_job')
job.scheduleBuild();
If you don't want to use this option in your 'other_job', then you can use NodeLabel Parameter Plugin (which you already used) and pass the NodeLabel parameter to downstream job.
In this case, see example from Groovy plugin page how to start another job with parameters (you need to use NodeParameterValue instead of StringParameterValue):
def job = Hudson.instance.getJob('MyJobName')
def anotherBuild
try {
def params = [
new StringParameterValue('FOO', foo),
]
def future = job.scheduleBuild2(0, new Cause.UpstreamCause(build), new ParametersAction(params))
println "Waiting for the completion of " + HyperlinkNote.encodeTo('/' + job.url, job.fullDisplayName)
anotherBuild = future.get()
} catch (CancellationException x) {
throw new AbortException("${job.fullDisplayName} aborted.")
}
println HyperlinkNote.encodeTo('/' + anotherBuild.url, anotherBuild.fullDisplayName) + " completed. Result was " + anotherBuild.result
If it's not working, probably the issue is with node restrictions (e.g., there is only one executor for the node).
NOTE: I prefer to use Jenkins pipelines for job configurations. It allows you to store your build configs in Jenkinsfiles which can be loaded from repository (e.g., from GitLab). See example of triggering job with NodeParameterValue.
Based on the answer of biruk1230, here is a full solution :
import hudson.model.*;
import jenkins.model.Jenkins
import java.util.concurrent.*
import hudson.AbortException
import org.jvnet.jenkins.plugins.nodelabelparameter.*
def currentBuild = Thread.currentThread().executable
current_node = currentBuild.getBuiltOn().getNodeName()
def j = Hudson.instance.getJob('MyJobName')
try {
def params = [
new NodeParameterValue('node', current_node, current_node),
]
def future = j.scheduleBuild2(0, new Cause.UpstreamCause(build), new ParametersAction(params))
println "Waiting for the completion of " + j.getName()
anotherBuild = future.get()
} catch (CancellationException x) {
throw new AbortException("aborted.")
}

Groovy Missing Property Exception

I have a jenkins build that needs to get the filenames for all files checked in within a changeset.
I have installed groovy on the slave computer and configured Jenkins to use it. I am running the below script that should return the names (or so I assume as this may be wrong as well) and print to the console screen however I am getting this error:
groovy.lang.MissingPropertyException: No such property: paths for class: hudson.plugins.tfs.model.ChangeSet
Here is the Groovy System Script:
import hudson.plugins.tfs.model.ChangeSet
// work with current build
def build = Thread.currentThread()?.executable
// get ChangesSets with all changed items
def changeSet= build.getChangeSet()
def items = changeSet.getItems()
def affectedFiles = items.collect { it.paths }
// get file names
def fileNames = affectedFiles.flatten().findResults
fileNames.each {
println "Item: $it" // `it` is an implicit parameter corresponding to the current element
}
I am very new to Groovy and Jenkins so if its syntax issue or if I'm missing a step please let me know.
I don't know the version of jenkins you are using but according to the sourcecode of ChangeSet that you can find here I suggest you to replace line 9 with:
def affectedFiles = items.collect { it.getAffectedPaths() }
// or with the equivalent more groovy-idiomatic version
def affectedFiles = items.collect { it.affectedPaths }
Feel free to comment the answer if there will be more issues.

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()

Jenkins 2.0 Pipeline and Job DSL

I have a Jenkins Pipeline Job which has this code :
import hudson.model.*
import hudson.util.*
import hudson.scm.*
import hudson.scm.SubversionChangeLogSet.LogEntry
stage 'Build'
node('master'){
svn 'http://mysvn/url'
def build = Thread.currentThread()?.executable
def changeSet= build.getChangeSet()
.
.
}
The code is with unchecked 'sandbox' (as it presented on the picture).
and I get this error :
groovy.lang.MissingPropertyException: No such property: executable for class: java.lang.Thread
I am not familiar with the syntax for Thread.currentThread()?.executable
what does the '?' operator means.
I google it and found out about jenkins job-dsl plugin and didn't find anything about this operator.
I also tried the Script Console Plugin at : http://localhost:8080/script
and I fail for the same reason.
Does Pipeline Plugin support the Jenkins DSL-JOB ? should I import something in order to make it work ?
Here is the related ticket and the answer from cloudbees.. Ping back from there:
def changeLogSets = currentBuild.rawBuild.changeSets
for (int i = 0; i < changeLogSets.size(); i++) {
def entries = changeLogSets[i].items
for (int j = 0; j < entries.length; j++) {
def entry = entries[j]
echo "${entry.commitId} by ${entry.author} on ${new Date(entry.timestamp)}: ${entry.msg}"
def files = new ArrayList(entry.affectedFiles)
for (int k = 0; k < files.size(); k++) {
def file = files[k]
echo " ${file.editType.name} ${file.path}"
}
}
}
It's a groovy operator, '?' is to prevent NullpointerExceptions. It does the following only if the first is not null.
The Sandbox feature is to prevent certain calls so anybody can add scripts without admin approval, but very limited...
def build = Thread.currentThread()?.executable
Firstly, the above sentence can be explained like this,
Thread.currentThread() will get the current running thread, in normal case, it will be a instance of Jenkins Executor class, there is a attribute inside this class,
/**
* {#link hudson.model.Queue.Executable} being executed right now, or null if the executor is idle.
*/
#GuardedBy("lock")
private Queue.Executable executable;
Jenkins AbstractBuild implement this interface, so it means you will actually get AbstractBuild instance back.
However, this sentence is not work for pipeline related jobs since pipe line project have different structure compared with old Jenkins jobs. It don't extend AbstractBuild class.
This is why your script is not working.
About your requirement, since there is no AbstrctBuild class, so a lot of methods are actually cannot be used, like the one you used.
No idea if there is a smart way to get the changset inside pipeline job, or maybe you need restructure your job to adapt pipeline plugin.
Br,
Tim

Call a jenkins job by using a variable for build the name

I try to launch a job from a parametrized trigger and I would compute the name from a given variable.
Is it possible to set in field :
Build Triggers Projects to build
a value like this
${RELEASE}-MAIN-${PROJECT}-LOAD_START
?
Unfortunately, this isn't possible with the Build Triggers. I looked for a solution for this "higher order build job" that would allow you to create a dynamic build name with a one of the parameterized build plugins, but I couldn't find one.
However, using the Groovy Postbuild Plugin, you can do a lot of powerful things. Below is a script that can be modified to do what you want. In particular, notice that it gets environmental variables using build.buildVariables.get("MY_ENV_VAR"). The environmental variable TARGET_BUILD_JOB specifies the name of the build job to build. In your case, you would want to build TARGET_BUILD_JOB using these two environmental variables:
build.buildVariables.get("RELEASE")
build.buildVariables.get("PROJECT")
The script is commented so that if you're not familiar with Groovy, which is based off Java, it should hopefully make sense!
import hudson.model.*
import hudson.model.queue.*
import hudson.model.labels.*
import org.jvnet.jenkins.plugins.nodelabelparameter.*
def failBuild(msg)
{
throw new RuntimeException("[GROOVY] User message, exiting with error: " + msg)
}
// Get the current build job
def thr = Thread.currentThread()
def build = thr?.executable
// Get the parameters for the current build job
// For ?:, see "Elvis Operator" (http://groovy.codehaus.org/Operators#Operators-ElvisOperator)
def currentParameters = build.getAction(ParametersAction.class)?.getParameters() ?:
failBuild("There are no parameters to pass down.")
def nodeName = build.getBuiltOnStr()
def newParameters = new ArrayList(currentParameters); newParameters << new NodeParameterValue("param_NODE",
"Target node -- the node of the previous job", nodeName)
// Retrieve information about the target build job
def targetJobName = build.buildVariables.get("TARGET_BUILD_JOB")
def targetJobObject = Hudson.instance.getItem(targetJobName) ?:
failBuild("Could not find a build job with the name $targetJobName. (Are you sure the spelling is correct?)")
println("$targetJobObject, $targetJobName")
def buildNumber = targetJobObject.getNextBuildNumber()
// Add information about downstream job to log
def jobUrl = targetJobObject.getAbsoluteUrl()
println("Starting downstream job $targetJobName ($jobUrl)" + "\n")
println("======= DOWNSTREAM PARAMETERS =======")
println("$newParameters")
// Start the downstream build job if this build job was successful
boolean targetBuildQueued = targetJobObject.scheduleBuild(5,
new Cause.UpstreamCause(build),
new ParametersAction(newParameters)
);
if (targetBuildQueued)
{
println("Build started successfully")
println("Console (wait a few seconds before clicking): $jobUrl/$buildNumber/console")
}
else
failBuild("Could not start target build job")

Resources