Executing hudson specific function in jenkins pipeline - grails

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

Related

Execute groovy script from pipeline throws RejectedAccessException

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.

Jenkins Publish Over SSh pipeline parameterized

I am using Publish over SSH plugin in Jenkins to deploy the jar file which is created from the build process. I have created a pipeline like this
node {
{
stage('Checkout') {
git([url: '.............', branch: 'myBranch', credentialsId: 'mycredentials'])
}
stage('Build') {
script{
sh 'chmod a+x mvnw'
sh './mvnw clean package'
}
}
stage('Deploy to Server'){
def pom = readMavenPom file: 'pom.xml'
script {
sshPublisher(publishers: [sshPublisherDesc(configName: 'server-instance1',
transfers: [sshTransfer(cleanRemote:true,
sourceFiles: "target/${env.PROJECT_NAME}-${pom.version}.jar",
removePrefix: "target",
remoteDirectory: "${env.PROJECT_NAME}",
execCommand: "mv ${env.PROJECT_NAME}/${env.PROJECT_NAME}-${pom.version}.jar ${env.PROJECT_NAME}/${env.PROJECT_NAME}.jar"),
sshTransfer(
execCommand: "/etc/init.d/${env.PROJECT_NAME} restart -Dspring.profiles.active=${PROFILE}"
)
])
])
}
}
}
}
This works. I have a SSH Server configured under Manage Jenkins >> Configure System >> Publish Over SSH.
Now I want to deploy on multiple servers. Lets say I create multiple ssh configurations by name server-instance1, server-instance2. How do I make this Jenkins job parameterized ? I tried with checking the checkbox and selecting a Choice Parameter. But I am not able to figure out how to make the values for this dropdown come from the SSH server list(instead of hardcoding)
I tried few things as mentioned here(How to Control Parametrized publishing in Jenkins using Publish over SSH plugin's Label field). Unfortunately none of the articles talks about doing this from a pipeline.
Any help is much appreciated.
If you want to select the SSH server name dynamically, you can use the Extended Choice Parameter plugin which allows you to execute groovy code that will create the options for the parameter.
In the plugin you can use the following code to get the values:
import jenkins.model.*
def publish_ssh = Jenkins.instance.getDescriptor("jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin")
configurations = publish_ssh.getHostConfigurations() // get all server configurations
return configurations.collect { it.name } // return the list of all servers
To configure this parameter in you pipeline you can use the following code for scripted pipeline:
properties([
parameters([
extendedChoice(name: 'SERVER', type: 'PT_SINGLE_SELECT', description: 'Server for publishing', visibleItemCount: 10,
groovyScript: '''
import jenkins.model.*
def publish_ssh = Jenkins.instance.getDescriptor("jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin")
return publish_ssh.getHostConfigurations() .collect { it.name }
''')
])
])
Or the following code for declarative pipeline:
pipeline {
agent any
parameters {
extendedChoice(name: 'SERVER', type: 'PT_SINGLE_SELECT', description: 'Server for publishing', visibleItemCount: 10,
groovyScript: '''
import jenkins.model.*
def publish_ssh = Jenkins.instance.getDescriptor("jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin")
return publish_ssh.getHostConfigurations() .collect { it.name }
''')
}
...
}
Once the parameter is defined just use it in your sshPublisher step:
sshPublisher(publishers: [sshPublisherDesc(configName: SERVER, transfers: ...
Another option you can have when using the Extended Choice Parameter is to configure it as Multi-Select instead of Single-Select so a user can then select multiple severs, and you can use the parallel option to publish over all selected servers in parallel.

Create environment variable from parameters in Jenkins

I have a jenkinsfile which is parametrized. Based on the input parameters I want to set certain environment variables. But I m not able to get the syntax right.
parameters {
choice choices: ['insure-base-docker/insure-base', 'insure-ide/insure-sd', 'insure-ide/insure-ansible','insure-ide/ansible-test-vini'], description: 'Auf welche repository sollte die Tag erstellt?', name: 'repository'
choice choices: ['tag', 'branch'], description: 'Tag oder branch erstellen', name: 'git_entity'
string defaultValue: '21.x.x', description: 'Version die als branch oder Tag ersellt werden muss', name: 'version', trim: false
}
environment {
GIT_URL = "${'https://my_repo/scm/'+param.repository+'.git'}"
GIT_BRANCH = "${'Release/'+param.version}"
CHECKOUT_BRANCH = '${${git_entity} == "tag" ? "master" : "develop"}'
}
the env vars are always wrong. How do I set the env vars correctly?
Nowadays, there aren't many differences between parameters and environment variables in Jenkins. Even the way you use them, preceded by the env. keyword, is the same.
Try something like this.
pipeline {
parameters {
choice choices: ['insure-base-docker/insure-base', 'insure-ide/insure-sd', 'insure-ide/insure-ansible','insure-ide/ansible-test-vini'], description: 'Auf welche repository sollte die Tag erstellt?', name: 'GIT_PROJECT'
string defaultValue: '21.x.x', description: 'Version die als branch oder Tag ersellt werden muss', name: 'GIT_BRANCH', trim: false
}
agent any
stages {
stage('Cloning Git repository') {
steps {
script {
git branch: "${env.GIT_BRANCH}", credentialsId: 'MY_GIT_CREDENTIALS_PREVIOUSLY_ADDED_TO_JENKINS', url: "http://github.com/user/${env.GIT_PROJECT}.git"
}
}
}
}
}
You can use as GIT_BRANCH not just branches, but also tags.
Best regards.
I am assuming you are using a freestyle project
here are the steps
Go to Build Environment part and check the option Inject environment variables to the build process
it will open a new set of input boxes.
enter your code in Groovy script
Here am just trying to update the Version and Full version to include the passing parameter say TestParam
here is a sample:
import hudson.model.*
import groovy.io.FileType
def build = Thread.currentThread().executable
def buildNumber = build.number
def workspace = build.getEnvVars()["WORKSPACE"]
def defaultBuildNo = build.getEnvVars()["BUILD_NUMBER"]
println "Hi from Groovy script "
println workspace
println defaultBuildNo
def map = [
"BUILD_NUMBER": defaultBuildNo,
"VERSION" : defaultBuildNo + build.getEnvVars()["TestParam"],
"FULL_VERSION": +defaultBuildNo + "." + build.getEnvVars(["TestParam"]
]
return map
Now in the execute shell part type these and see all will resolve successfully.
Execute shell
echo $TestParam
echo $BUILD_NUMBER
echo $VERSION
echo $FULL_VERSION
Now all these env variables are accessible throughout the Job.

groovy.lang.MissingPropertyException: No such property: Jenkins for class: hudson

I am trying to run a groovy script in Jenkins slave node to retrieve child jobs from a folder in Jenkins slave node. Here is the groovy script I tried:
I tried some SO answers and found groovy.lang.MissingPropertyException: No such property: jenkins for class: groovy.lang.Binding
But this doesn't solve my problem.
Please find the code that I tried:
import groovy.json.JsonSlurper
import groovy.json.JsonBuilder
import jenkins.model.*
static main(args){
def childJobFolder = "childJob"
def childJobNameList = []
def env = System.getenv()
// Setting the environment properties to variables.
def jenkinsUsername = env.UAT_JENKINS_MY_USER
def jenkinsPassword = env.UAT_JENKINS_MY_PASS
def jsonSlurper = new JsonSlurper()
// Getting the child job names from "childJob" folder
Jenkins.instance.getItemByFullName(childJobFolder).allJobs.each{
def childJobName = it.name.toString()
if(childJobName.startsWith("job-")){
childJobNameList.add(childJobName)
}
}
println "\n" + "Child Jobs Available: " + childJobNameList + "\n"
}
Here is what I got in the console:
Caught: groovy.lang.MissingPropertyException: No such property: Jenkins for class: hudson3067346520259876246
groovy.lang.MissingPropertyException: No such property: Jenkins for class: hudson3067346520259876246
at hudson3067346520259876246.run(hudson3067346520259876246.groovy:17)
Build step 'Execute Groovy script' marked build as failure
Can someone help me to fix this error? Thanks in advance!
Finally, I found out the solution for this error. This is caused by running on plain groovy script instead of system groovy script. As Jayan said the Jenkins variables only available for System groovy scripts and not for plain groovy script. For that reason I could not load Jenkins instances from plain groovy script.

How can I pass parameters from parallel builds downstream in a jenkins pipeline

I have been trying to set up a pipeline in jenkins which runs all my robot test builds in parallel and then, after they all finish, runs another build which includes sending 1 email with results for all the tests (rather than spamming with 1 per build).
I know that the robot plugin returns the variables $(ROBOT_PASSPERCENTAGE) and $(ROBOT_PASSRATIO) which we currently use. I was hoping there was a way of extracting them and using as a parameter for the downstream pipline build.
Just as a test I was trying groovy of the form below, but can't figure out how you get the variables and pass into the downstream build.
Any help appreciated.
stage('set up') {
node {
build job: 'setup', propagate: false
}
}
stage('run suites') {
parallel 'test set 1':{
node {
build job: 'test set 1', propagate: false
def 1_PASSPERCENTAGE = build.buildVariableResolver.resolve("ROBOT_PASSPERCENTAGE")
def 1_PASSRATIO = build.buildVariableResolver.resolve("ROBOT_PASSRATIO")
println "FOO=$CRM_PASSPERCENTAGE"
println "FOO=$CRM_PASSRATIO"
}
}, 'test set 2':{
node {
build job: 'thankQ Robot Mission Personnel Tests', propagate: false
def 2_PASSPERCENTAGE = build.buildVariableResolver.resolve("ROBOT_PASSPERCENTAGE")
def 2_PASSRATIO = build.buildVariableResolver.resolve("ROBOT_PASSRATIO")
println "FOO=$MP_PASSPERCENTAGE"
println "FOO=$MP_PASSRATIO"
}
}
}
stage('results') {
node {
println "FOO=$2_PASSPERCENTAGE"
println "FOO=$2_PASSRATIO"
println "FOO=$1_PASSPERCENTAGE"
println "FOO=$1_PASSRATIO"
}
}
From Jenkins pipeline steps reference, you can call a downstream job with parameters like this :
build job: downstreamJob, parameters: [
[$class: 'StringParameterValue', name: 'passPercentage', value: "${1_PASSPERCENTAGE}"],
[$class: 'StringParameterValue', name: 'passRatio', value: "${1_PASSRATIO}"]
]
As for how to get your Robot variables I have never used it but I guess you could always use the URL of the test build (e.g. your test set 1 job) and parse the log file or the build page for the variables you are looking for. Something like this :
def robotLog = script: 'curl http://your-jenkins/job/test-set-1/lastBuild/robot.log', returnStdout: true // First determine which URL corresponds to the robot.log file, or use the main page of your build.
def percentageMatcher = robotLog.trim() =~ 'Pass percentage.*(\\d+)%' // Again, find the exact regex here
def 1_PASSPERCENTAGE = percentageMatcher[0][1]
... // Same thing with pass ratio...

Resources