In a Jenkins freestyle job (on an older 1.6x version, no support for 2.x pipeline jobs) I would like to run a shell command (curl -XPOST ...) as a post build step if the build status recovered(!) from FAILED to SUCCESS.
However, all plugins for determining the build status I am aware of can only do something if the current build status IS FAILED or SUCCESS but don't take into account whether it recovered in comparison to the last build.
Is there any way how to achieve this, e.g. using the Groovy Post build plugin and some lines of scripting?
I found that something like this is a good way to go.
You can build up some interesting logic, and the "currentBuild" variable has some decent documentation here: currentBuild variable doc
script {
if ( ( currentBuild.resultIsBetterOrEqualTo("SUCCESS") && currentBuild.previousBuild.resultIsWorseOrEqualTo("UNSTABLE") ) || currentBuild.resultIsWorseOrEqualTo("UNSTABLE")) {
echo "If current build is good, and last build is bad, or current build is bad"
}
}
Meanwhile I found a way to achieve this. It is not necessarily pretty and I still appreciate alternative solutions :)
First of all, a plugin is needed which lets you execute shell commands in a Post Build step. There might be different ones, I am using the PostBuildScript plugin for that.
Then, create a "Execute a set of scripts" post build step, set the step to execute to Build step and select Execute shell, for me this looks like this:
In there, I run the following shell script lines which use my Jenkins server's REST API in combination with a Python one-liner (you could also use jq or something else for this) to determine the status of the current build as well as of the last completed build:
statusOfCurrentBuild=$(curl --silent "${BUILD_URL}api/json" | python -c "import sys, json; print json.load(sys.stdin)['result']")
statusOfLastBuild=$(curl --silent "${JOB_URL}/lastCompletedBuild/api/json" | python -c "import sys, json; print json.load(sys.stdin)['result']")
if [ "${statusOfCurrentBuild}" == "SUCCESS" ] && [ "${statusOfLastBuild}" == "FAILURE" ]
then
echo "Build was fixed"
# do something interesting here
fi
Depending on your Jenkins settings, using the REST API might require authentication.
Related
I am trying to use Jenkins' Build Number in the naming of a Log that I would want to be saved as a post build action
Will the below format work
C:\Jenkins\workspace\Jmeter_Jenkins_Test_Job\Jenkins_Results\"${env.BUILD_NUMBER}"results.jtl
As per Building a software project wiki article the environment variable you're looking for is BUILD_NUMBER and in case of Windows operating system you can access it as:
%BUILD_NUMBER%
so if you want to amend JMeter result file name to include build number you can do something like:
jmeter -n -t /path/to/test.jmx -l /path/to/result-%BUILD_NUMBER%-.jtl
and in the runtime the variable will be evaluated to the current Jenkins build number:
More information just in case: Continuous Integration 101: How to Run JMeter With Jenkins
Without having laid my hands on a Jenkins installation for quite some time:
Yes, you can do that and it has been done before!
You could do something like:
pipeline {
agent any
stages {
stage('test') {
sh 'path/to/jmeter.bat -n -t ${env.WORKSPACE}my_test.jmx -l my_test${env.BUILD_ID}_${env.BUILD_NUMBER}.jtl'
}
}
}
I would propose to create the HTML dashboard report first though and then publish that in Jenkins - you could use https://jenkins.io/doc/pipeline/steps/htmlpublisher/ to do that. Further you should avoid absolute paths in favor of using the WORKSPACE environment variable (see https://jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables for reference).
If you need some general idea of how to run the test via Jenkins you could have a look at https://code-maven.com/jenkins-pipeline-running-external-programs and https://jmeter.apache.org/usermanual/get-started.html#non_gui
If you already tried to achieve something and need more specific help, please come forward with some more detail.
Is there a way to have a script being run from an execute shell step access the build status as well as other information about the build? (e.g. build number, start/end time, etc)
I need to update a wiki page with a script with the information about the build.
Thanks in advance!
Build status information gets saved into simple XML files. Take a look at
{jenkins-directory}/jobs/{job-name}/builds/{build-number}/build.xml. You can use symbolic links like lastSuccessfulBuild instead of specifying a build number if you want.
You'll find all information about the build there: build status, start time, duration, etc. Parse the XML file or just use grep in a bash script.
If you don't want to use the filesystem you can use Jenkins API.
But in any case, once you got a script that can determine build parameters and update your wiki page, you can put it into another Jenkins job and trigger it automatically (for example, with the BuildResultTrigger Plugin).
I'm using jenkins own API to get the build status while the job is running, which works like a charm. Be aware that i'm using JQ To parse the json response.
To get this to work simply add a shell script and execute the following command: BUILD_STATUS=$(curl --silent ${BUILD_URL}api/json | jq -r '.result')
Which results in the following:
While executing a build, Jenkins set environment variables you can use in your script.
also refer to the detailes on how to use it -
%VAR% in batch files and $VAR from inside the Jenkins job configuration page
Just wanted to explore pytest and integrating it into Jenkins. My sample pytest test cases are
def a(x):
return x+1
def test_answer():
assert a(2) == 3
def test_answer2():
assert a(0) == 2
I then generated a standalone pytest script which I run in Jenkins, generating an xml to be parsed for results.
As test_answer2 fails, the Jenkins job also fails. I'm assuming this is because the exit code returned is non-zero. How would I go around this, i.e the Jenkins job doesn't even if 1 or more tests do indeed fail. Thanks
If you are calling this test execution in a batch file or shell script or directly using the command execution in Jenkins. You can follow the below way:
Windows:
<your test execution calls>
exit 0
Linux:
set +e
<your test execution calls>
set -e
This will ignore the error if at all it is called with in the batch scripts and the Jenkins will show status as successful.
In addition to already posted answers:
You also can mark your test as xfail, what means you know it will fail, just like skipping:
#pytest.mark.skip(reason="no way of currently testing this")
def test_the_unknown():
...
more about skipping you can find in pytest documentation
and on Jenkins side you also can manipulate of state of your build via simply try/catch statement:
try {
bat "python -m pytest ..."
} catch (pytestError) {
// rewrite state of you build as you want, Success or Failed
// currentBuild.result = "FAILED"
currentBuild.result = "SUCCESS" // your case
println pytestError
}
But be aware, it will mark whole build each time as success for that step of pytest run. Best practice just to skip tests via #pytest.mark.skip as described above.
If you are calling this test execution in a batch file or shell script or directly using the command execution in Jenkins. You can follow the below way:
Below code is NOT Working
Linux:
set +e
set -e
We use Jenkins running on a Windows system so our tests are listed in the Jenkins "Execute Windows Batch command" section.
I was able to solve this by separating the tests that might have failures with a single & (rather than &&). For example:
"C:\Program Files\Git\bin\sh.exe" -c python -m venv env && pip3 install -r requirements.txt && py.test --tap-files test_that_may_fail.py & py.test --tap-files next_test.py & py.test
Since we use pytest, any failures are flagged in python with an assert. If you use the &&, this will cause Jenkins job to abort and not run the other tests.
I'm planning to write a script that would choose a set of Jenkins jobs with a regexp, start their builds and wait until they finish. If most of them fail, I want to change some global env vars (I already know how to do this) and build them again. Then I want to collect the test results and format it into a nice report.
I can't put this into the individual jobs' post-build actions, I need info about all of them to write the report and to do the rebuilding.
My current idea is to use the Jenkins REST API, but before I do so: is this already implemented somewhere?
Give a look at Multi-Job plugin and see if it fits your requirement.
Else go with REST API.
Because unique requirement of our build process I had to use jenkins cli :
java -jar jenkins-cli.jar -s http://<jenkinsURL> build <job-name> -s <parameters if any>
The trailing -s makes it wait till the job is complete.
I have a bash script that looks like this:
#!/bin/sh
previousRelease=`git describe --tags --match "release*" origin/release`
git diff --name-status $previousRelease..origin/release
Is there a way of having Jenkins execute it as part of a build process? The intention is to see a list of files that have changed since the last release, as a manual step to confirm that the release should go up. The user who has triggered the build needs to read the output and then confirm the release should go ahead.
Most things are possible to do in Jenkins but if it is the best way of doing it is another question.
To solve this I would use an approach with two jobs one for checking the diff (hock that one on to the git repository) The other job for doing the actual release.
The check diff job
1 Create a job of the type freestyle project with build type "execute shell" and run your script above. Add some prints at the end of the log to create a clickable link to manually start the release job with current git-id as argument.
Just printing an URL in console output will make it clickable so:
export GITID=`git log -n| grep and sed or awk something`
echo http://jenkins.example.com:8888/job/releaseme/buildWithParameters?label=$GITID¶meters=build
will create the accept changes user interface you requested.
The release job
2 Create another job(above I assumed you named it releaseme) let the job have one parameter as argument (tick "This build is parameterized") make let the argument be the git-id you would like to release. Create your release script in this job.