Jenkins pipeline job: Set sleep time from a string parameter? - jenkins

I'm new to Jenkins Pipeline jobs, and I'm facing an issue I cannot solve.
I have a stage with a hardcoded sleep seconds value:
stage ("wait_prior_starting_smoke_testing") {
echo 'Waiting 5 minutes for deployment to complete prior starting smoke testing'
sleep 300 // seconds
}
But I would like to provide the time argument via a job (string) parameter SLEEP_TIME_IN_SECONDS. But whatever I have tried, I am not able to get it to work.
How do you convert a string parameter to the int time argument?

small improve for this page:
You also can use sleep(time:3,unit:"SECONDS") if you are interested in specifying time unit of your sleep
https://jenkins.io/doc/pipeline/steps/workflow-basic-steps/#sleep-sleep

Finally I did found a way to get this work:
stage ("wait_prior_starting_smoke_testing") {
def time = params.SLEEP_TIME_IN_SECONDS
echo "Waiting ${SLEEP_TIME_IN_SECONDS} seconds for deployment to complete prior starting smoke testing"
sleep time.toInteger() // seconds
}

Try this. It work for me.
stage ("wait_for_testing")
{
sh 'sleep 300'
}
With "sh" you start virtual terminal with shell. If you need write other command in one terminal, write ; after command.
For example:
sh 'pwd; sleep 300; echo "Hello World"'

Related

Jenkins timeout not aborting job

I have a Jenkins pipeline where I have the following code (jenkinsfile):
stage('My stage') {
options {
timeout(time: 5, unit: "MINUTES")
}
steps {
script {
./run_script.sh
}
}
}
}
With this code I was expecting that If the run_script.sh would take more than 5 minutes, the job would abort.
But this is not the case (even with jenkins telling me "Sending interrupt signal to process").. After running the job I get this:
...
17:09:40 Timeout set to expire in 5 min 0 sec
[Pipeline] {
[Pipeline] script
[Pipeline] {
17:09:40 ./run_script.sh '
17:14:40 Cancelling nested steps due to timeout
17:14:40 Sending interrupt signal to process
17:14:48 ...
17:14:48 + JOB_NAME=...
17:14:48 + BUILD_URL=...
17:14:48 + BUILD_ID=777
17:14:48 + BUILD_RESULT=SUCCESS
The job gets executed and I can see the green success status in jenkins.
Why is this happening and how can I make it so when a timeout occurs the job gets aborted?
EDIT:
Not sure if this is relevant or not but the run_script.sh is a script which connects to a remote server using ssh and runs some docker commands (docker run...). Running this script using timeout gives me the following msgs:
...
12:07:22 Cancelling nested steps due to timeout
12:07:22 Sending interrupt signal to process........
.........
Finished: SUCCESS
As you can see the status stays success instead of aborted!!!
I need to capture this "timeout" so I can send notifications to users. One way would be to capture the aborted status but if the status is success how can i do it?
The run_script.sh looks like this:
#!/bin/bash
ssh user#server.com "
ssh -p 30 xdy#localhost ' docker run --rm --name cont1 -e FTP_USER=$User -e FTP_PASSWD=$Pass -v /home/logs:/usr/myapp -w /usr/myapp server2.com:3000/mylog:1.1 python script.py' "
script.py is a simple script to copy some files from a server to another.

How to run a task if tests fail in Jenkins

I have a site in production. And I have a simple playwright test that browses to the site and does some basic checks to make sure that it's up.
I'd like to have this job running in Jenkins every 5 minutes, and if the tests fail I want to run a script that will restart the production server. If the tests pass, I don't want to do anything.
What's the easiest way of doing this?
I have the MultiJob plugin that I thought I could use, and have the restart triggered on the failed test step, but it doesn't seem to have the ability to trigger specifically on fail.
Something like the following will do the Job for you. I'm assuming you have a second Job that will take care of the restart.
pipeline {
agent any
triggers{
cron('*/5 * * * *')
}
stages {
stage("Run the Test") {
steps{
echo "Running the Test"
// I'm returning exit code 1 so jenkins will think this failed
sh '''
echo "RUN SOMETHING"
exit 1
'''
}
}
}
post {
success {
echo "Success: Do nothing"
}
failure {
echo 'I failed :(, Execute restart Job'
// Executing the restart Job.
build job: 'RestartJob'
}
}
}

Jenkinsfile pipeline, return warning but do not fail

Is there a way to not fail with a declarative pipeline step but display a warning instead? At the moment I am circumventing it by adding || exit 0 to the end of the sh command lines so it always exits ok.
Example currently:
sh 'vendor/bin/phpcs --report=checkstyle --report-file=build/checkstyle.xml --standard=phpcs.xml . || exit 0'
I feel there should be a better way of doing this? How can you control the result returned so the user knows with out digging through result logs but with out blocking/failing too?
Thank you
Edit:
So I have got this far to be able to mark it as unstable. In Blue Ocean it just marks every stage as unstable though and you have to go digging through to find it. Am I trying to do the impossible (but feels like I should be able to do it)?
Also it just displays it as 'Shell script' in the heading on Blue Sky now instead of showing the command being run so you don't even know what it's doing with out expanding each of them.
script {
def RESULT = sh returnStatus: true, script: 'vendor/bin/phpcs --report=checkstyle --report-file=build/checkstyle.xml --standard=phpcs.xml .'
if ( RESULT != 0 ) {
currentBuild.result = 'UNSTABLE'
}
}
Re marking it all yellow/unstable: Just found this which explains that I am not going mad. Several years of discussion and no progress :( https://issues.jenkins-ci.org/browse/JENKINS-39203
Re it just showing 'Shell script' now on Blue Ocean view: I'll go and play some more and see if I'm better with || exit 0 or a script block and using echo to display some useful info.
FYI: JENKINS-39203 has been resolved in the meantime.
Instead of setting currentBuild.result = 'UNSTABLE' we use the corresponding basic pipeline step unstable, which also takes a message:
unstable("There are Checkstyle issues")
You can find options for any steps in your jenkins itself under http://jenkins-url/pipeline-syntax/. sh with returnStatus: true can be used to achieve your goal.
sh returnStatus: true, script: 'ls -2' # returnStatus: true, just set $? but not fail the execution
Below pasted the screenshot from pipeline-syntax page:

jenkins complicated buildflow, is it possible?

I would like to have a Jenkins build flow that looks like this.
After the build is triggered all slaves run the same job in parallel (a setup job).
If any slaves fail this job they should not continue on.
For the all the slaves that to pass that job, they should grab a job out of a pool of jobs that need to be completed. And once a slave completes a job they should go back to complete another job in the pool.
I have only started working with Jenkins a few weeks ago and they way I have it setup now is as each job is picked up by a slave they have to run the setup job first. This really slows down build times because I have about 30 jobs and the setup takes ~2 minutes.
I am using Jenkins as an automated testing platform and all the jobs in the job pool can run independently of each other. I have 5 slaves currently and ~30 jobs.
The following should do the trick:
def jobPool = new ArrayDeque()
jobPool.add({
echo "Doing stuff on ${env.NODE_NAME}"
});
jobPool.add({
echo "Doing other stuff on ${env.NODE_NAME}, a little slower"
sleep 4
});
jobPool.add({
echo "Doing more stuff on ${env.NODE_NAME}, even slower"
sleep 10
});
jobPool.add({
echo "Doing stuff quick on ${env.NODE_NAME}"
});
jobPool.add({
echo "Doing stuff quicker on ${env.NODE_NAME}"
});
def par = [:]
for (x in ["master", "urban"]) {
def nodeName = x; // needed due to variable scoping
par[nodeName] = {
node (nodeName) {
try {
echo "Doing setup on ${env.NODE_NAME}!"
// Do you're setup
echo "Done with setup"
} catch (Exception e) {
echo "Will not use this node as it failed setup!"
return;
}
while (true) {
// echo "${jobPool.size()}"
def subTask = jobPool.poll()
//echo "${jobPool.size()} ${subTask}"
if (subTask == null) {
break;
}
// Might wan't try catch around the next line if you wan't to continue if a job fails
subTask()
}
}
}
}
parallel par
if (!jobPool.isEmpty()) {
error "Not all tasks was done!"
}
Simply add your "job pool jobs" to the jobPool variable and modify the setup part.
It seems like you want separate stages in the same job. This is made much easier in jenkins 2's pipelines. There are some pictures here:
https://wiki.jenkins-ci.org/display/JENKINS/Pipeline+Stage+View+Plugin
the [groovy] code ends up looking like this:
node {
stage 'Checkout'
svn 'https://svn.mycorp/trunk/'
stage 'Build'
sh 'make all'
stage 'Test'
sh 'make test'
}

Jenkins exclude days from scheduled

How can I exclude specific days from a Jenkins scheduld?
For example: every 5 minutes from 7 to 17 and from monday to friday.
H/05 7-17 * * 1-5
But, if the day of the week is a public holiday, it should not run. How can I configure this?
Thx
Currently Jenkins crontab does not support a complicate logic such public holidays exclusion. However, there are some options out there you can use to accomplish that:
First
For my project I create my own holiday database, which it is a file containing the days I want to exclude eg.:
# /path/to/holidays
# New Year's Day
01-01-2017
# Christmas
12-25-2017
and I check it using a Jenkins shell script, as it was proposed here.
For example for the above file format:
#!/bin/bash
TODAY="`date +%m-%d-%Y`"
if grep -q $TODAY /path/to/holidays; then
echo Skipping holiday for $*
exit 0
fi
$*
Second
A more robust solution but more complicate is to create your own plugin based on the
Run Condition Example Plugin in which you exclude the public holidays of your Country such as this plugin.
There is another option now, with the Jenkins Working Hours Plugin.
Using the plugin, you can configure both working hours:
Or Holidays as 'Excluded Days':
The working hours plugin allows you to set up a schedule of allowable build times; projects can opt in to use the schedule to prevent them from running outside of configured allowable build times. If a build is scheduled during non-working hours then it is kept in the build queue until the next allowable time.
Jobs opt in via the enforceBuildSchedule job parameter, which is provided by this plugin. It can optionally take in a branches parameter to limit it's usage to only those branches. This only works in MultiBranchPipelines.
Usage
Sample job (scripted pipeline):
node {
properties([enforceBuildSchedule()])
stage('Do some stuff') {
echo 'this can wait til morning'
}
}
Sample job (declarative pipeline):
pipeline {
agent any
options {
enforceBuildSchedule()
}
stages {
stage('Do some stuff') {
steps {
echo 'this can wait til morning'
}
}
}
}
Sample job with branches parameter (works in both declarative and scripted):
node {
properties([enforceBuildSchedule(branches: ['dev', 'qa', 'prod')])
stage('Do some stuff') {
echo 'this can wait til morning'
}
}
Using the idea of one of the answers and using Declarative + Script block I created this:
stage('Check if Today is Holiday') {
steps {
// Based on idea from https://stackoverflow.com/a/41219757/7820857
script {
IS_HOLIDAY = sh(script: 'grep -q $(date +%Y-%m-%d) /etc/holidays', returnStatus: true)
if (IS_HOLIDAY == 0) {
currentBuild.result = 'ABORTED'
error ('Today is Holiday according to the file /etc/holidays inside the Jenkins server')
}
}
}
}
This will depend on the file /etc/holidays inside the Jenkins server. Adding this additional Stage before will help you to identify if the day mentioned is holiday and exit with error message, or not and continue with the rest of the stages.
I will like that the Working Hours Plugin worked for this but they queue the jobs in case that the day is inside the Excluded days, but I need to cancel the job execution. A feature request exist for that user case.

Resources