I have the following script in a .gsh file:
build = Thread.currentThread().executable
String jobName = build.getEnvVars()["JOB_NAME"]
println "JOBNAME: " + jobName
When I execute this script within a normal freestyle project it does work fine in the step Execute system Groovy script output: JOBNAME: playground/Testing.
However if I execute the same script within a pipeline:
stage('Test') {
steps {
script {
jobName = load 'C:/Tools/getTag.gsh'
}
}
}
I do get an RejectedAccessException.
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: No such field found: field java.lang.Thread executable
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.unclassifiedField(SandboxInterceptor.java:426)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:410)
at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:353)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:357)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:29)
at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
at Script1.run(Script1.groovy:8)
How can I execute this script within the pipeline?
Notes:
I can't approve it like Jenkins RejectedAccessException as it is already approved and works within the freestyle project.
Related
I have groovy postbuild script
def error = manager.getLogMatcher(".*(Error:(.*)))
if(error?.matches()) {
manager. addShortText(matcher.group(1))
}
Now I'm trying to convert this into declarative pipeline syntax
pipeline{
post{
failure{}
}
}
So In failure tab can I add groovy script? or I have to add stage? I see there is jenkins-badge-plugin but not sure how to add regex to find text and then add batch
You just need to add script block inside failure as follows and there you can put your post build groovy script:
pipeline{
post{
failure{
script{
//Add your post build script code in case of failure
}
}
}
}
In one stage of my declarative jenkins pipeline codes, it executes a bash script(sh '''./a.sh''', script "a.sh" is maintained outsides) - in that script, the value of "jarVersion" is injected in ${WORKSPACE}/.jarVersion (echo "jarVersion=${jarVersion}" > ${WORKSPACE}/.jarVersion). At later stage, we need get the value of jarVersion. We use load "${WORKSPACE}/.jarVersion" and ${jarVersion} to get the value. It works when we do so in pipeline script.
However, when we set this pipeline as a shared library (put it in /vars/testSuite.groovy) and call it in another pipeline script. It can not recognize var ${jarVersion}.
Please advise how to solve the issue. A common question is: how to transfer a value in a script from stage A to stage B?
stage('getJarVersion'){
steps{
script{
load "${WORKSPACE}/.jarVersion"
currentBuild.description = "jarVersion:${jarVersion}"
}
}
}
I expected it could work as it is in pipeline scripts.
But it shows:
groovy.lang.MissingPropertyException: No such property: jarVersion for class: testSuite
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:53)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:458)
at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.getProperty(DefaultInvoker.java:34)
at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
at testSuite.call(/jenkins/jobs/TestSuite1/builds/11/libs/pipelineUtilities/vars/testSuite.groovy:84)
With the stages under the same groovy file, you have to declare the object out of the stage blocks and before the node block. So for each stage, you can define the value inside the variable:
Pipeline {
def my_var
stage('stage1'){
---------
}
stage('stage2'){
---------
}
}
If you are defining a stage per file, you have to create the closures with the input object and to pass it in the call from the parent groovy file:
test.groovy:
def call(def my_obj, String my_string) {
stage('my_stage') {
println(my_obj)
}
}
parent_test.groovy
test(obj_value,string_value)
I have been trying to find a solution for changing build parameters programmatically using jenkins pipeline plugin where i have jenkinsfile with following content:
#!/usr/bin/env groovy
import hudson.model.*
properties(
[
parameters(
[
string(defaultValue: 'win64', description: 'PLATFORM', name: 'PLATFORM'),
string(defaultValue: '12.1.0', description: 'PRODUCT_VERSION', name: 'PRODUCT_VERSION')
]
)
]
)
stage('working with parameters'){
node('master'){
def thr = Thread.currentThread()
def build = thr?.executable
def paramsDef = build.getProperty(ParametersDefinitionProperty.class)
if (paramsDef) {
paramsDef.parameterDefinitions.each{ param ->
if (param.name == 'PLATFORM') {
println("Changing parameter ${param.name} default value was '${param.defaultValue}' to 'osx10'")
param.defaultValue = "osx10"
}
}
}
}
}
But it fails everytime with error as :
groovy.lang.MissingPropertyException: No such property: executable for class: java.lang.Thread
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:53)
After searching a lot i could find somewhere that this script needs to run as system groovy script and everywhere they are referring to Groovy plugin but as i am using pipeline project, i am not able to understand how can i force pipeline to execute my scripts as system groovy script.
Please solve my queries as i have left no link on google unopened :(
I am creating a jenkins pipeline job to seed jobs using the jenkins job DSL plugin. How do I get the workspace path inside the DSL file? The jenkins pipeline code is as such:
#!groovy
node{
stage("build jobs"){
ws{
git poll: true, credentialsId: 'xxx', url: 'ssh://git#aaaaa.cc.xxx.com:/xxx/xxx.git'
checkout scm
jobDsl(removedJobAction: 'DISABLE', removedViewAction: 'DELETE', targets: 'jobs/*.groovy', unstableOnDeprecation: true)
}
}
}
The DSL code that is failing is:
hudson.FilePath workspace = hudson.model.Executor.currentExecutor().getCurrentWorkspace()
With the error:
Processing DSL script pipeline.groovy
java.lang.NullPointerException: Cannot invoke method getCurrentWorkspace() on null object
at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:91)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:48)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.java:35)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at pipeline.run(pipeline.groovy:1)
at pipeline$run.call(Unknown Source)
Variables created in the pipeline area are not accessible inside the job DSL step
I stumbled upon this because there seems to be no good way. Here is how I do it:
node {
stage('test') {
sh 'pwd > workspace.txt'
jobDsl scriptText: '''
String workspace = readFileFromWorkspace('workspace.txt').trim()
def file = new File(workspace, 'test.txt')
file.append('It worked!')'''
}
}
So first grab the workspace in the pipeline script and then pass it to the job dsl. If you have more than just the workspace variable, that you need in your scripts I suggest transferring via a properties file:
node {
stage('test') {
sh 'echo "workspace="$(pwd) > build.properties'
jobDsl scriptText: '''
Properties props = new Properties();
props.load(streamFileFromWorkspace('build.properties'))
def file = new File(props.getProperty('workspace'), 'test.txt')
file.append('It worked!')'''
}
}
This can be achieved by using SEED_JOB variable:
String workspacePath = SEED_JOB.lastBuild.checkouts[0].workspace
It is described in project's wiki:
Access to the seed job is available through the SEED_JOB variable. The variable contains a reference to the internal Jenkins object that
represents the seed job. The actual type of the object depends on the
type of job that runs the DSL. For a freestyle project, the object is
an instance of hudson.model.FreeStyleProject. See the Jenkins API
Documentation for details.
The SEED_JOB variable is only available in scripts, not in any classes
used by a script. And it is only available when running in Jenkins,
e.g. in the "Process Job DSLs" build step.
The following example show how to apply the same quiet period for a
generated job as for the seed job.
job('example') {
quietPeriod(SEED_JOB.quietPeriod) }
You can use the __FILE__ variable in a Job DSL script to get the path of the current script. Maybe you can use that to derive the workspace directory. See Script Location for details.
def scriptDir = new File(__FILE__).parent.absolutePath
You can pass the workspace argument to job dsl. for example:
The pipeline code as follow:
node {
step([
$class: 'ExecuteDslScripts',
scriptText: 'job("example-2")'
])
step([
$class: 'ExecuteDslScripts',
targets: ['jobs/projectA/*.groovy', 'jobs/common.groovy'].join('\n'),
removedJobAction: 'DELETE',
removedViewAction: 'DELETE',
lookupStrategy: 'SEED_JOB',
additionalClasspath: ['libA.jar', 'libB.jar'].join('\n'),
additionalParameters: [
message: 'Hello from pipeline',
credentials: 'SECRET'
WORKSPACE: env.WORKSPACE
]
])
}
https://github.com/jenkinsci/job-dsl-plugin/wiki/User-Power-Moves#use-job-dsl-in-pipeline-scripts
I have created a Jenkins Pipeline job. In this job I want to do the build using Ant. I have configured the Ant variable in Manage **Jenkins > Global Tool Configuration** as Ant1.9.1= D:\path_to_hybris\hybris\bin\platform\apache-ant-1.9.1.
In a freestyle jenkins Job, I know that the build.xml location can be specified as in the below screenshot:
but I am unable to understand how to specify the ant groovy script beyond this point, especially where can we mention the path to build.xml file:
def antHome = tool 'Ant1.9.1'
????
????
you can use ant wrapper in Jenkins`s pipeline groovy script.
withAnt(installation: 'LocalAnt') {
// some block
sh "ant build"
//for windows
bat "ant build"
}
Remember to configure the ant tool in the Jenkins "Global Tool Configuration" with the same name "LocalAnt".
You can try this:
def antVersion = 'Ant1.9.1'
withEnv( ["ANT_HOME=${tool antVersion}"] ) {
sh '$ANT_HOME/bin/ant target1 target2'
}
Under Windows this would look like this (I didn't test it though):
def antVersion = 'Ant1.9.1'
withEnv( ["ANT_HOME=${tool antVersion}"] ) {
bat '%ANT_HOME%/bin/ant.bat target1 target2'
}
This assumes that you have Ant configured in Jenkins with name 'Ant1.9.1'.
I needed this multiple times within the same Jenkinsfile that needs to be executed on both linux and windows agents so I created a method for it.
You can call ant like this
callAnt("-v -p")
if you add this method definition to your jenkinsfile
def callAnt(String Parameters) {
if (isUnix()) {
env.PATH = "${tool 'ant'}/bin;${env.PATH}"
sh "ant ${Parameters}"
}
else {
env.PATH = "${tool 'ant'}\\bin;${env.PATH}"
bat "ant ${Parameters}"
}
}