Jenkins run a failing test n times - bash

I'm trying rerun a test n times on failure in Jenkins. I've seen Naginator, but my team would prefer not to add additional plugins.
(Note: we use EnvInject to inject environmental variables into the build process)
The next idea was to keep a variable with the number of times to retry, and decrement it on each new build. There was a stack overflow link (that I'm struggling to find at the moment) suggesting a groovy script that looks like this
def map = [:]
Int newRetries = RETRIES.toInteger() - 1
map.put(“RETRIES”, newRetries)
return map
However, groovy scripts in the "prepare an environment to run" section need admin privilages (which again my team would prefer to avoid).
The next idea was to use a property file and just do something along the lines of echo "RETRIES=$((RETRIES-1))" > env.properties and add an Inject Environmental variable step that reads in env.properties.
The problem is that within our Jenkins bash script echo "RETRIES=$((RETRIES-1))" prints "RETRIES=$((RETRIES-1))"
In a local terminal I can run
RETRIES=5
echo "RETRIES=$((RETRIES-1))"
> RETRIES=4
, but in Jenkins, RETRIES-1 doesn't get evaluated. Do any of you have an idea of why?

So I found 3 mistakes that I was making.
Jenkins pipelines execute a single step in parallel. This means you can't write to and read from a file in different portions of the same step without reading from the unupdated file (in practice) (From this stackoverflow Override environment variable created locally in Jenkins)
The default shell on Jenkins is /usr/bin/sh which isn't necessarily bash. I explicitly ran my script with bash -c "echo $Var" (the real issue here was that the remote machines were windows, oops)
My pipeline was failing before reading in the updated variable value from the file. I've moved the reading step earlier in the pipeline.

Related

Jenkins "forgets" parameters when executing a shell script in Build section

I encounter the issue that I have a parameterized project with several string parameters, e.g., "VARIABLE_A", and that Jenkins doesn't know them anymore when executing a shell script in the Build section, i.e., there is simply no value.
This is very bizarre and I am convinced this should work using a string parameter (variable) in these ways:
"echo $VARIABLE_A"
"python3 $PATH/abc.py $VARIABLE_A"
...
but there is no values anymore.
echo-command does not print anything and the Python script misses the value as VARIABLE_A is apparently empty.
Perhaps someone has an idea ?
Thanks
Rainer
PS
Jenkins version is "2.277.2".

Choice paramter in jenkins as an output from shell script (pipeline)

I'm looking for a way to use an output from shell as a jenkins parameter but in pipeline, don't want to use any of UI plugins.
For example I want to use output from command
ls /home
as a choice parameter (so I would be able to choose users from the list), is it possible to do something like that?
It must be done in pipeline, I'm not looking for some plugins which allow you to do something like that, but you need to do all in UI, if plugin support pipelines then it's also ok.
For a pipeline to run, its parameters need to be completely defined before the pipeline is started.
For the pipeline to parse the output of ls /home, it needs to run and allocate a node and a workspace, which can only happen after the pipeline is started.
So you are in a kind of a chicken-and-egg problem, where you need to run some code before you start a pipeline, but you can't run pipeline before you run that code.
So your issue boils down to "How can I run some arbitrary Groovy script before I start my pipeline?"
There are two options for this:
ActiveChoice plugin allows you to define a parameter that returns a script. Jenkins will then run the script (don't forget to approve it) in order to show you your "Build with parameters" page. Debugging this is notoriously hard, but this can go to great lengths.
Alternatively, you may want to run a scripted pipeline before you run the Declarative (main) one, as outlined e.g. in this answer. This may look a bit like this:
def my_choices_list = []
node('master') {
stage('prepare choices') {
// read the folder contents
def my_choices = sh script: "ls -l /home", returnStdout:true
// make a list out of it - I haven't tested this!
my_choices_list = my_choices.trim().split("\n")
}
}
pipeline {
parameters {
choiceParam('OPTION', my_choices_list)

Put output of a command in a variable GoCD

I try to create a variable with the version of a project in a GoCD job.
My project is built with maven. The version of the project is set on the pom.xml file (present on the git repository).
Maven allow to retrieve the version of the project with command :
mvn help:evaluate -Dexpression=project.version
So I tried to put the output of this command in a linux variable :
my_version=${mvn help:evaluate -Dexpression=project.version}
And then use it to push the project on a docker repository :
docker push my_project:$my_version
The problem is that GoCD seems to have his own interpreter (see https://docs.gocd.org/current/faq/dev_use_current_revision_in_build.html ).To use a variable, I must do something like this :
sh -c docker push my_project:$my_version
But I can't find a way to set a linux variable.
Is it something that is ok to do with GoCD ? What is the right way to do this ?
GoCD doesn't maintain a single shell session for the entire job. So even if you use sh export MY_VERSION=... and try to use that in the next task within the same job it will not work as expected.
To solve this problem the best way is to wrap the entire set of commands you want to perform within a shell script and execute that shell script as a task. Given the entire shell script would be executed within a single shell instance anything variable you define can be used.

How/When does Execute Shell mark a build as failure in Jenkins?

The horror stories I found while searching for an answer for this one...
OK, I have a .sh script which pretty much does everything Jenkins supposed to do:
checks out sources from SVN
build the project
deploys the project
cleans after itself
So in Jenkins I only have to 'build' the project by running the script in an Execute Shell command.
The script is ran (the sources are downloaded, the project is build/deploy) but then it marks the build as a failure:
Build step 'Execute shell' marked build as failure
Even if the script was successfully ran! I tried closing the script with:
exit 0 (still marks it as failure)
exit 1 (marks it as failure, as expected)
no exit command at all (marks it as failure)
When, how and why does Execute Shell mark my build as a failure?
First things first, hover the mouse over the grey area below. Not part of the answer, but absolutely has to be said:
If you have a shell script that does "checkout, build, deploy" all by itself, then why are you using Jenkins? You are foregoing all the features of Jenkins that make it what it is. You might as well have a cron or an SVN post-commit hook call the script directly. Jenkins performing the SVN checkout itself is crucial. It allows the builds to be triggered only when there are changes (or on timer, or manual, if you prefer). It keeps track of changes between builds. It shows those changes, so you can see which build was for which set of changes. It emails committers when their changes caused successful or failed build (again, as configured as you prefer). It will email committers when their fixes fixed the failing build. And more and more. Jenkins archiving the artifacts also makes them available, per build, straight off Jenkins. While not as crucial as the SVN checkout, this is once again an integral part of what makes it Jenkins. Same with deploying. Unless you have a single environment, deployment usually happens to multiple environments. Jenkins can keep track of which environment a specific build (with specific set of SVN changes) is deployed it, through the use of Promotions. You are foregoing all of this. It sounds like you are told "you have to use Jenkins" but you don't really want to, and you are doing it just to get your bosses off your back, just to put a checkmark "yes, I've used Jenkins"
The short answer is: the exit code of last command of the Jenkin's Execute Shell build step is what determines the success/failure of the Build Step. 0 - success, anything else - failure.
Note, this is determining the success/failure of the build step, not the whole job run. The success/failure of the whole job run can further be affected by multiple build steps, and post-build actions and plugins.
You've mentioned Build step 'Execute shell' marked build as failure, so we will focus just on a single build step. If your Execute shell build step only has a single line that calls your shell script, then the exit code of your shell script will determine the success/failure of the build step. If you have more lines, after your shell script execution, then carefully review them, as they are the ones that could be causing failure.
Finally, have a read here Jenkins Build Script exits after Google Test execution. It is not directly related to your question, but note that part about Jenkins launching the Execute Shell build step, as a shell script with /bin/sh -xe
The -e means that the shell script will exit with failure, even if just 1 command fails, even if you do error checking for that command (because the script exits before it gets to your error checking). This is contrary to normal execution of shell scripts, which usually print the error message for the failed command (or redirect it to null and handle it by other means), and continue.
To circumvent this, add set +e to the top of your shell script.
Since you say your script does all it is supposed to do, chances are the failing command is somewhere at the end of the script. Maybe a final echo? Or copy of artifacts somewhere? Without seeing the full console output, we are just guessing.
Please post the job run's console output, and preferably the shell script itself too, and then we could tell you exactly which line is failing.
Simple and short answer to your question is
Please add following line into your "Execute shell" Build step.
#!/bin/sh
Now let me explain you the reason why we require this line for "Execute Shell" build job.
By default Jenkins take /bin/sh -xe and this means -x will print each and every command.And the other option -e, which causes shell to stop running a script immediately when any command exits with non-zero (when any command fails) exit code.
So by adding the #!/bin/sh will allow you to execute with no option.
In my opinion, turning off the -e option to your shell is a really bad idea. Eventually one of the commands in your script will fail due to transient conditions like out of disk space or network errors. Without -e Jenkins won't notice and will continue along happily. If you've got Jenkins set up to do deployment, that may result in bad code getting pushed and bringing down your site.
If you have a line in your script where failure is expected, like a grep or a find, then just add || true to the end of that line. That ensures that line will always return success.
If you need to use that exit code, you can either hoist the command into your if statement:
grep foo bar; if [ $? == 0 ]; then ... --> if grep foo bar; then ...
Or you can capture the return code in your || clause:
grep foo bar || ret=$?
I 've tried all mentioned options (even changing sh to bash without -xe params), the only one option worked for me is:
<command-which-returns-not-zero> || exit 0
Plain and simple:
If Jenkins sees the build step (which is a script too) exits with non-zero code, the build is marked with a red ball (= failed).
Why exactly that happens depends on your build script.
I wrote something similar from another point-of-view but maybe it will help to read it anyway:
Why does Jenkins think my build succeeded?
So by adding the #!/bin/sh will allow you to execute with no option.
It also helped me in fixing an issue where I was executing bash script from Jenkins master on my Linux slave. By just adding #!/bin/bash above my actual script in "Execute Shell" block it fixed my issue as otherwise it was executing windows git provided version of bash shell that was giving an error.
Try and always find where exactly its failing by adding the following line into your "Execute shell" Build step.
#!/bin/sh -xe
By adding the -x you will print each and every command that ran (including the lines from embedded scripts) and that will help in spotting the root cause.
Removing the -e option i.e. running #!/bin/sh will allow you to execute with no option, which is really a bad idea as Bryan explained well in one of the answers.
The problem is with no option Jenkins will ignore errors and continue execution of subsequent steps (if there are any) which will leave your process in an consistent state. If this is for a production build or deployment, that may have a bad impact.
Once you find the problem area, run the same failing command from the directory as jenkins-user manually, to get to the exact error/rootcause.
In Jenkins ver. 1.635, it is impossible to show a native environment variable like this:
$BUILD_NUMBER or ${BUILD_NUMBER}
In this case, you have to set it in an other variable.
set BUILDNO = $BUILD_NUMBER
$BUILDNO

Pass variable from Jenkins to Ruby script (Jenkins newbie)

I've pulled a few scripts into Jenkins for a proof of concept and think I'd like to move that direction for all of our scripts. Right now I keep an environment.rb file with my code (watir-webdriver, cucumber) which tells the script which environment we're testing and which browser to use (global variables). Jenkins fires off the script using rake.
I'd love to let the user choose the environment and browser through Jenkins 'choice' variable or similar, and then pass that to the script. While I see the framework in that for Jenkins and set up a choice list for environment, I'm having trouble determining what the next step is.
I could write to environment.rb, I could pass a variable to rake - I have many options for how to pass the information, I just need some assistance finding the first step to find the Jenkins way of accomplishing them. Google results and previous Stack questions weren't what I was looking for.
Thanks
Sure. Give the user either a text entry field a dropdown after telling Jenkins that this is a parameterized build. You'll give them a name, something like BuildEnvironment. Then when you call the build, you can pass these from the environment variables. For example, if you were using ANT, you'd add a line to the parameters that said environment = ${MyEnvironment} Jenkins will then pass the value along for your build tool to use.
There is a way to pass Jenkins Environment Variable to Ruby script. Please see the following example:
workspace_path = `echo $WORKSPACE`.strip # note the use of backticks
puts workspace_path
In the "echo $WORKSPACE".strip # the code work only if you replace quotes with backticks
This code example works in Jenkins on a Linux system.

Resources