Create a pipeline with Job Dsl and insert it in an existing View without deleting the existing pipelines - jenkins-pipeline

I'm creating pipepiles automatically with Job Dsl and I want to add the pipeline in an already existing View.
I'm using this script
def myJobs = [
'Test1',
'Test2'
]
myJobs.each { mj ->
job(mj) {
steps {
shell('echo ')
}
}
}
listView('TestView') {
filterBuildQueue()
filterExecutors()
jobs {
myJobs.each { mj ->
name(mj)
}
}
columns {
status()
weather()
name()
lastSuccess()
lastFailure()
lastDuration()
buildButton()
}
}
With this script, if I want to add two new Jobs (for example Test3 and Test4), the old pipelines are deleted and in the View there are only the new pipelines.
How can I add new pipelines without deleting old pipelines? Thank you

Related

Jenkins function of shared library executed on wrong node

I have a simple shared library and want to call a function which creates a file.
My pipeline script looks like this:
#Library('jenkins-shared-library')_
pipeline {
agent {
node {
label 'node1'
}
}
stages {
stage('test') {
steps {
script {
def host = sh(script: 'hostname', returnStdout: true).trim()
echo "Hostname is: ${host}"
def testlib = new TestLibrary(script:this)
testlib.createFile("/tmp/file1")
}
}
}
}
}
This pipeline job is triggered by another job which runs on the built-in master node.
The stage 'test' is correctly executed on the 'node1'.
Problem: The created file "/tmp/file1" is created on the jenkins master, instead of "node1"
I also tried it without the shared library and load a groovy script
directly in a step:
pipeline {
agent {
node {
label 'node1'
}
}
stages {
stage('test') {
steps {
script {
def script = load "/path/to/script.groovy"
script.createFile("/tmp/file1")
}
}
}
}
}
This also creates the file on the master node, instead on "node1".
Is there no way of loading external libs or classes and execute them on the node where the stage is running on ? I dont want to place all the code directly into the step.
Ok I found it myself, groovy scripts run by definition always on the master node. No way to run scripts or shared-library code on a node other than master.

I want to enable deployment only from the branch names(starting with hotfix and master). How can I do that?

I am writing a Jenkinsfile and trying to enable deployment from the branch names(starting with master and hotfix). How can I do that? Below is my groovy code. This works if I specify only one branch. How can I do that for multiple branches?
// Create and Deploy to STAGE Environment
stage ('Create and Deploy to k8s stage Environment') {
when {
allOf {
expression {
branch_name.startsWith('master')
}
}
}
options {
skipDefaultCheckout()
}
steps {
withCredentials([string(credentialsId: "$env.K8S_STAGE_NS_TOKEN" , variable: 'STAGE_TOKEN')]) {
kubernetesDeploy(hcEnv: 'stage', hcToken: "${STAGE_TOKEN}")
}
}
}
The below code doesn't work if I specify 2 branch names but the above one works.
// Create and Deploy to PROD Environment
stage ('Create and Deploy to k8s production Environment') {
when {
allOf {
expression {
branch_name.startsWith('hotfix')
branch_name.startsWith('master')
}
}
}
options {
skipDefaultCheckout()
}
steps {
withCredentials([string(credentialsId: "$env.K8S_PROD_NS_TOKEN" , variable: 'PROD_TOKEN')]) {
kubernetesDeploy(hcEnv: 'prod', hcToken: "${PROD_TOKEN}")
}
}
}
You can use this
expression { return (env.GIT_BRANCH.startsWith('origin/master') || env.GIT_BRANCH.startsWith('hotfix'))}
OR
you can also try this
expression { return (env.BRANCH_NAME.startsWith('origin/master') || env.GIT_BRANCH.startsWith('origin/hotfix'))}
I am not sure if your branch name starts with origin or without origin so use it according to you. I would suggest instead of startsWith use contains.
Also instead of allOf i guess you need anyOf because you want to run stage for either if it's master branch or hotfix branch and both at the same time can't be true so

Is there a way to move the entire post {} build section in Jenkinsfile to the global pipeline library?

I'm relatively new to Jenkins pipelines, but having implemented already a few, I've realised I need to start using jenkins shared library before I go mad.
Have already figured out how to define some repetitive steps in the library and call them with less clutter from Jenkinsfile, but not sure if the same thing can be done for the entire post build section (thought I've read about to how to define the entire pipeline in the lib and similar), as this is pretty much static end of every single pipeline code:
#Library('jenkins-shared-library')_
pipeline {
agent none
stages {
stage ('System Info') { agent any
steps { printSysInfo() }
}
stage ('Init'){ agent {label 'WinZipSE'}
steps { init('SCMroot') }
}
stage('Build') { agent any
steps { doMagic() }
}
}
// This entire 'post {}' section needs to go to a shared lib
// and be called just with a simple methed call, e.g.
// doPostBuild()
post {
always {
node ('master') {
googlechatnotification (
message: '[$BUILD_STATUS] Build $JOB_NAME $BUILD_NUMBER has finished',
url: 'id:credential_id_for_Ubuntu')
step (
[$class: 'Mailer',
recipients: 'sysadmins#example.com me#example.com',
notifyEveryUnstableBuild: true,
sendToIndividuals: true]
)
}
}
success {
node ('master') {
echo 'This will run only if successful'
}
}
failure {
node ('master') {
echo 'This will run only if failed'
}
}
// and so on
}
}
I just dunno how to syntactically achieve that. For sure, I can define the entire post build section an a lib/var like: doPotBuild.groovy
def call () {
post {...}
}
but how I will eventually call it from within my Jenkinsfile outside of that defined post {} build block section (AKA stages).
I can call it within some stage('post build){doPostBuild()}, but it won't serve the way how the true post {} section is supposed to work, e.g. it won't get executed it there was failure in one of the previous stages.
Any thoughts on that and mainly working examples?
I am not entirely if this will work as I don't use declarative pipelines, so am unsure how rigid the top level structure is. But I would revert to a script block.
#Library('jenkins-shared-library')_
pipeline {
agent none
stages {
stage ('System Info') { agent any
steps { printSysInfo() }
}
stage ('Init'){ agent {label 'WinZipSE'}
steps { init('SCMroot') }
}
stage('Build') { agent any
steps { doMagic() }
}
}
// This entire 'post {}' section needs to go to a shared lib
// and be called just with a simple methed call, e.g.
// doPostBuild()
script {
doPostBuild()
}
}

How can I define multiple agents in declarative jenkinsfile?

In my Jenkinsfile I want a particular stage to run on both the agents in parallel.for example:
stage('abc'){
agent {
label "dev6" && "dev7"
}
steps {
xyz()
}
}
I have two slaves with label dev6 and dev7. I want xyz() to start on both the agents dev6 and dev7 at same time parallely. What is the correct way to do it? Do i need parallel block ? from the above code it just starts the functions on one of dev6 or dev7. I tried with
label "dev6 || dev7"
label "dev6 && dev7"
but it doenst work. Can someone help??
Thanks
You need parallel on level of stages, the reason for that is actually you want this to run twice on separate agents. Unless I misunderstood you.
pipeline {
agent none
stages {
stage('Test') {
parallel {
stage('Test On dev6') {
agent {
label "dev6"
}
steps {
xyz()
}
}
stage('Test On dev7') {
agent {
label "dev7"
}
steps {
xyz()
}
}
}
}
}

exit declarative pipeline prematurely based on script output

While I am aware of this question clean way to exit declarative Jenkins pipeline as success I am to green to understand how to put it to use (from where does the skipBuild variable come?).
I have a script that determines whether the pipeline should continue or not but I am unsure how to piece it together (I am free to construct the script as needed).
pipeline {
agent {
docker { image 'python:3-alpine' }
}
stage('Should I continue') {
steps {
python should_i_continue.py
}
when { ? == true }
stages {
...
}
}
}
I am aware that the capabilities increase tenfold if I use a scripted pipeline but I wonder if it is possible to do what I want with a declarative one?
You can use any custom variable, which you will set as true|false based on some condition in the steps of your pipeline and all stages that need to be executed based on that condition have to have following format:
stage('Should Continue?') {
setBuildStatus("Build complete", "SUCCESS");
when {
expression {skipBuild == true }
}
}
In other words to provide you a bit clean picture, check this abstract example:
node {
skipBuild = false
stage('Checkout') {
...
your checkout code here
...
}
stage('Build something') {
...
some code goes here
skipBuild = true
...
}
stage('Should Continue?') {
setBuildStatus("Build complete", "SUCCESS");
when {
expression {skipBuild == true }
}
}
}

Resources