Jenkins convert old format DSL to new version - jenkins

I took the DSL from this https://raw.githubusercontent.com/denschu/job-dsl-examples/master/job-dsl-example.groovy and try to create the job on my Jenkins 2.107 version. But its giving the missing tag error. Any help to convert this DSL to new version?
Processing provided DSL script
ERROR: (script, line 10) No signature of method: javaposse.jobdsl.dsl.helpers.scm.GitContext.createTag() is applicable for argument types: (java.lang.Boolean) values: [false]
DSL I am using.
def projectName = "deploy-application"
freeStyleJob("${projectName}"){
triggers { scm("*/5 * * * *") }
scm {
git {
remote {
url("https://github.com/codecentric/spring-samples")
}
createTag(false)
}
}
rootPOM("${projectName}/pom.xml")
goals("clean package")
wrappers {
preBuildCleanup()
release {
preBuildSteps {
maven {
mavenInstallation("Maven 3.0.4")
rootPOM("${projectName}/pom.xml")
goals("build-helper:parse-version")
goals("versions:set")
property("newVersion", "\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.incrementalVersion}-\${BUILD_NUMBER}")
}
}
postSuccessfulBuildSteps {
maven {
rootPOM("${projectName}/pom.xml")
goals("deploy")
}
maven {
goals("scm:tag")
}
downstreamParameterized {
trigger("deploy-application") {
predefinedProp("STAGE", "development")
}
}
}
}
}
publishers {
groovyPostBuild("manager.addShortText(manager.build.getEnvironment(manager.listener)[\'POM_VERSION\'])")
}
promotions {
promotion("Development") {
icon("star-red")
conditions {
manual('')
}
actions {
downstreamParameterized {
trigger("deploy-application","SUCCESS",false,["buildStepFailure": "FAILURE","failure":"FAILURE","unstable":"UNSTABLE"]) {
predefinedProp("ENVIRONMENT","test-server")
predefinedProp("APPLICATION_NAME", "\${PROMOTED_JOB_FULL_NAME}")
predefinedProp("BUILD_ID","\${PROMOTED_NUMBER}")
}
}
}
}
promotion("QA") {
icon("star-yellow")
conditions {
manual('')
upstream("Development")
}
actions {
downstreamParameterized {
trigger("deploy-application","SUCCESS",false,["buildStepFailure": "FAILURE","failure":"FAILURE","unstable":"UNSTABLE"]) {
predefinedProp("ENVIRONMENT","qa-server")
predefinedProp("APPLICATION_NAME", "\${PROMOTED_JOB_FULL_NAME}")
predefinedProp("BUILD_ID","\${PROMOTED_NUMBER}")
}
}
}
}
promotion("Production") {
icon("star-green")
conditions {
manual('')
upstream("QA")
}
actions {
downstreamParameterized {
trigger("deploy-application","SUCCESS",false,["buildStepFailure": "FAILURE","failure":"FAILURE","unstable":"UNSTABLE"]) {
predefinedProp("ENVIRONMENT","prod-server")
predefinedProp("APPLICATION_NAME", "\${PROMOTED_JOB_FULL_NAME}")
predefinedProp("BUILD_ID","\${PROMOTED_NUMBER}")
}
}
}
}
}
}

The syntax of the createTag method has changed slightly. Take a look here at the latest api docs. https://jenkinsci.github.io/job-dsl-plugin/#method/javaposse.jobdsl.dsl.helpers.publisher.PublisherContext.git
If you don't want to create a tag at all though, I would just delete that line.
The new Syntax is:
git {
tag(String targetRepo, String name) {
// If set, creates a new tag.
create(boolean create = true)
// Sets a message for the tag.
message(String message)
// If set, updates an existing tag.
update(boolean update = true)
}
}

Related

How to reusing duplicate code for Jenkins Parallel includes the Stages section?

1.The following code can be replicated locally
how do i reuse the redundant code above, The code here may be a bit special. The code that needs to be reused includes stages. This is because an upstream build issues testing tasks to a downstream job(the code here), which is partially serialized in a producer-consumer model to control the degree of parallelism
def fill_list() {
def test_list = [] // or [].asSynchronized()
for ( int i = 0; i < 2; i++ ) {
test_list.add(i.toString())
}
return test_list
}
pipeline {
agent any
stages {
stage('Assign Tests') {
steps {
script {
test_list = fill_list()
}
}
}
stage('CTest Stage') {
parallel {
stage('stream_1') {
agent any
stages {
stage('installation') {
steps {
script {
while (test_list.size() > 0) {
def current_task = 0
try {
current_task = test_list.pop()
} catch (err) {
println('current stream ends')
break
}
stage("stream_1_${current_task}") {
script {
sleep(0.5)
println("ctest -R ${current_task} -N") // do test
println("node executor num: ${env.EXECUTOR_NUMBER}")
}
}
}
}
}
}
stage('clean') {
steps {
script {
println('stream_1_workspace clean')
}
}
}
}
}
stage('stream_2') {
agent any
stages {
stage('installation') {
steps {
script {
while (test_list.size() > 0) {
def current_task = 0
try {
current_task = test_list.pop()
} catch (err) {
println('current stream ends')
break
}
stage("stream_2_${current_task}") {
script {
sleep(0.5)
println("ctest -R ${current_task} -N") // do test
println("node executor num: ${env.EXECUTOR_NUMBER}")
}
}
}
}
}
}
stage('clean') {
steps {
script {
println('stream_1_workspace clean')
}
}
}
}
}
}
}
}
}
You could write a function that would provide a map containing reusable code and execute it in parallel. See also this answer https://stackoverflow.com/a/53237378/10721630
def parallelExecution() {
streams = [:]
for (int count = 1; count <= 2; count++) {
def temp = count
streams["stream_${temp}"] = {
node {
stage('installation') {
while (test_list.size() > 0) {
def current_task = 0
try {
current_task = test_list.pop()
} catch (err) {
println('current stream ends')
break
}
stage("stream_${temp}_${current_task}") {
println("ctest -R ${current_task} -N") // do test
println("node executor num: ${env.EXECUTOR_NUMBER}")
}
}
}
stage('clean') {
println("stream_${temp}_workspace clean")
}
}
}
}
parallel streams
}
In the pipeline script call the new function.
...
stage('CTest Stage') {
steps {
script {
parallelExecution()
}
}
}
...

jenkins pipeline : How to execute a function on a list of agents in parallel?

I have a bunch of nodes serving labels rhel6, rhel7.
How do I execute myFunc() on any 2 nodes of rhel6 and any 3 nodes rhel7 - in parallel?
def slaveList = ['rhel6', 'rhel6', 'rhel7', 'rhel7', 'rhel7']
def stageFunc (String slaveLabel) {
return {
// Run this stage on any available node serving slaveLabel
agent { label "${slaveLabel}" } // Error shown here.
stage {
myFunc()
}
}
}
pipeline {
agent any
stages {
stage('Start') {
steps {
script {
def stageMap = [:]
def i = 0
slaveList.each { s ->
stageMap[i] = stageFunc(s)
i++
}
parallel stageMap
}
}
}
}
}
Error shown:
java.lang.NoSuchMethodError: No such DSL method 'agent' found among steps [archive, ...
I haven't tested this yet, but it should work.
def slaveList = ['rhel6', 'rhel6', 'rhel7', 'rhel7', 'rhel7']
def stageFunc (stage_name, slaveLabel) {
return {
// Run this stage on any available node serving slaveLabel
stage(stage_name){
node(slaveLabel) {
myFunc()
}
}
}
}
pipeline {
agent any
stages {
stage('Start') {
steps {
script {
def stageMap = [:]
def i = 0
slaveList.each { s ->
stageMap[i] = stageFunc("Stage-${i}", s)
i++
}
parallel stageMap
}
}
}
}
}

No such DSL method 'when' found among steps in Jenkinsfile

I want to execute some stage in loop. I have Jenkinsfile
pipeline {
agent any
tools {}
parameters {}
environment {}
stages {
stage('Execute') {
steps {
script {
for (int i = 0; i < hostnameMap.size; i++) {
hostname = hostnameMap[i]
echo 'Executing ' + hostname
stage('Backup previous build ' + hostname) {
backup(hostname, env.appHome)
}
stage('Deploy ' + hostname) {
when {
expression { env.BRANCH_NAME ==~ /(dev|master)/ }
}
steps {
script {
deploy(hostname , env.appHome, env.appName)
}
}
}
stage('Restart ' + hostname) {
when {
expression { env.BRANCH_NAME ==~ /(dev|master)/ }
}
steps {
script {
restart(hostname , env.appName, env.port)
}
}
}
}
}
}
}
}
}
But got error
java.lang.NoSuchMethodError: No such DSL method 'when' found among
steps
Separately all of this stage works fine. Why I got this error?
stage('Execute') {
steps {
script {
for (int i = 0; i < hostnameMap.size; i++) {
hostname = hostnameMap[i]
echo 'Executing ' + hostname
stage('Backup previous build ' + hostname) {
backup(hostname, env.appHome)
}
stage('Deploy ' + hostname) {
if (env.BRANCH_NAME ==~ /(dev|master)/) {
deploy(hostname, env.appHome, env.appName)
}
}
stage('Restart ' + hostname) {
if (env.BRANCH_NAME ==~ /(dev|master)/) {
restart(hostname, env.appName, env.port)
}
}
}
}
}
}
when is a directive used in the declarative pipeline definition - it won't work inside script {} block. Instead use if.

Disable Jenkins Build button based on Parameters

I have Jenkins jobs with parameters. I would like to disable the build button and enable only user enters valid value in string parameter. How can i do that ?
There is one more extension to the above shown method - Above method checks for BUILD button on every Jenkins page as Simple Theme Plugin will be used.
In order to make the change at Job level - we can use Active Choices (https://plugins.jenkins.io/uno-choice/)
Go to configure section of the respective job
Select This project is parameterized option in General Tab
Add a new String Parameter named "Validating_Parameter"
Add another parameter of type Active Choice Reactive Reference Parameter
In Active Choice Reactive Reference Parameter - name can be empty and Choice Type should be of Formatted Hidden HTML
Add below groovy script by selecting Groovy:
return '''
<script>
function custom() {
if (!document.querySelector("td.setting-main>div>input[value='Validating_Parameter']")) {
return;
} else {
var inputElement = "";
if (document.querySelector("td.setting-main>div>input[value='Validating_Parameter']").parentNode) {
var childNodes = document.querySelector("td.setting-main>div>input[value='Validating_Parameter']").parentNode.childNodes;
if (Object.keys(childNodes).length) {
for (var key in childNodes) {
if ((Object.prototype.toString.call(childNodes[key]) == "[object HTMLInputElement]") && (childNodes[key].name == "value")) {
inputElement = childNodes[key];
}
}
}
}
}
/* init */
if (inputElement) {
var buildNumber = inputElement.value;
setTimeout(function () {
if (document.getElementsByName("parameters")[0].getElementsByTagName("button")[0]) {
document.getElementsByName("parameters")[0].getElementsByTagName("button")[0].disabled = buildNumber.match(/^[a-zA-Z0-9\\s,\\!.-]{15,}$/) ? false : true;
}
}, 100);
}
/* Register keyup event */
if (inputElement) {
inputElement.onkeyup = function () {
var buildNumber = inputElement.value;
if (document.getElementsByName("parameters")[0].getElementsByTagName("button")[0]) {
document.getElementsByName("parameters")[0].getElementsByTagName("button")[0].disabled = buildNumber.match(/^[a-zA-Z0-9\\s,\\!.-]{15,}$/) ? false : true;
}
}
}
}
document.addEventListener('DOMContentLoaded', custom, false);
</script>
'''
Updated code so it doesnt fail on yui-gen3-button not found element. you can reference answer by #Mayur
Code referenced from above code by #Renjith
You could use the validating string parameter plugin.
Or if you wanted to roll one yourself check out the documentation.
From the docs: "This is called "form validation", and Jenkins performs this on the server side." Meaning you wouldn't want to disable the build button if you use this method of validation.
Install Simple Theme plugin. This will help you to load your own JavaScript
(https://wiki.jenkins.io/display/JENKINS/Simple+Theme+Plugin )
Once its installed copy and paste following script to "/var/lib/jenkins/userContent" as custom.js
Replace "X_BUILD_NUMBER" with your string parameter which you wanted to validate.
function custom()
if (!document.querySelector("td.setting-main>div>input[value='X_BUILD_NUMBER']")) {
return;
} else{
var inputElement = "";
if(document.querySelector("td.setting-main>div>input[value='X_BUILD_NUMBER']").parentNode){
var childNodes = document.querySelector("td.setting-main>div>input[value='X_BUILD_NUMBER']").parentNode.childNodes;
if(Object.keys(childNodes).length){
for (var key in childNodes) {
if((Object.prototype.toString.call(childNodes[key]) == "[object HTMLInputElement]") && (childNodes[key].name == "value")){
inputElement = childNodes[key];
}
}
}
}
}
/* init */
if (inputElement) {
var buildNumber = inputElement.value;
setTimeout(function() {
if (document.getElementById("yui-gen1-button")) {
document.getElementById("yui-gen1-button").disabled = buildNumber ? false : true;
}
}, 100);
}
/* Register keyup event */
if (inputElement) {
inputElement.onkeyup = function() {
var buildNumber = inputElement.value;
if (document.getElementById("yui-gen1-button")) {
document.getElementById("yui-gen1-button").disabled = buildNumber ? false : true;
}
}
}
}
document.addEventListener('DOMContentLoaded', custom, false);
Thanks #Simeen Khan. I was actively searching for this. I found your post helpful but there is one thing to change based on plugins used by jenkins.
For newer jenkins and newer "Build With Parameters" plugin the documentElementID will be changed to gen4 or higher.
We can find these details using inspecting build button on build with parameter page of jenkins.
for example on my jenkins it is <button type="button" tabindex="0" id="yui-gen4-button">Build</button>.
for this Simeen's script will be like below:
return '''
<script>
function custom() {
if (!document.querySelector("td.setting-main>div>input[value='Validating_Parameter']")) {
return;
} else {
var inputElement = "";
if (document.querySelector("td.setting-main>div>input[value='Validating_Parameter']").parentNode) {
var childNodes = document.querySelector("td.setting-main>div>input[value='Validating_Parameter']").parentNode.childNodes;
if (Object.keys(childNodes).length) {
for (var key in childNodes) {
if ((Object.prototype.toString.call(childNodes[key]) == "[object HTMLInputElement]") && (childNodes[key].name == "value")) {
inputElement = childNodes[key];
}
}
}
}
}
/* init */
if (inputElement) {
var buildNumber = inputElement.value;
setTimeout(function () {
if (document.getElementById("yui-gen4-button")) {
document.getElementById("yui-gen4-button").disabled = buildNumber.match(/^[a-zA-Z0-9\\s,\\!.-]{15,}$/) ? false : true;
}
}, 100);
}
/* Register keyup event */
if (inputElement) {
inputElement.onkeyup = function () {
var buildNumber = inputElement.value;
if (document.getElementById("yui-gen4-button")) {
document.getElementById("yui-gen4-button").disabled = buildNumber.match(/^[a-zA-Z0-9\\s,\\!.-]{15,}$/) ? false : true;
}
}
}
}
document.addEventListener('DOMContentLoaded', custom, false);
</script>
'''

Criteria building in GORM

if (params.filters) {
def o = JSON.parse(params.filters);
def groupOp = o.groupOp
def fields = o.rules.field
def values = o.rules.data
def op = o.rules.op
println fields
println values
if(groupOp == "AND") {
fields.eachWithIndex {a, i ->
println op[i]
if(op[i].equals( "eq")) {
and{ eq(fields[i], values[i])}
}
if(op[i].equals("ne")) {
and{ ne(fields[i], values[i])}
}
if(op[i].equals("ge")) {
def valu = Double.valueOf( values[i]);
and{ ge(fields[i], valu)}
}
}
}
if(groupOp == "OR") {
fields.eachWithIndex {a, i ->
println op[i]
if(op[i].equals( "eq")) {
println 'eq';
or{ eq(fields[i], values[i])}
}
if(op[i].equals("ne")) {
println 'ne';
or{ ne(fields[i], values[i])}
}
if(op[i].equals("ge")) {
def valu = Double.valueOf( values[i]);
or{ ge(fields[i], valu)}
}
}
}
}
where params.filters is following JSON text.
{
"groupOp":"OR",
"rules":[
{
"field":"foo1",
"op":"le",
"data":"9.5"
},
{
"field":"foo2",
"op":"eq",
"data":"12345-123"
},
{
"field":"foo3",
"op":"cn",
"data":"IDM"
}
]
}
This data is coming from JQuery data grid.
Is there a better way of doing this?
In the code I have just listed only 3 operators, but in real I have 14 operations.
You can use String as Criteria operation, like:
A.withCriteria {
'eq' (id, 1)
}
so you might come to something like
A.withCriteria {
(groupOp) {
for (???) {
(op[i]) (fields[i], parsedVals[i])
}
}
}
Anyway you'll need to sanitize the web-submitted query for only allowed subset of operations. You don't want to receive end execute arbitrary sqlRestriction, right? :D So the code is going to be more complex then this anyway.
Note: wrapping and{} or or {} around single statement has no point, you need to put it around whole block of if-s.
I suggest that you have a look at the source code of the FilterPane plugin. Its service does essentially what you are doing and may give you some ideas for enhancements.

Resources