How to continue a Jenkins build even though a build step failed? - continuous-integration

I am using a Phing build script with Jenkins and would like to run it end to end on a job and capture all the reports. The problem is it stop building on a failed build step. Is there a way or a plugin that would continue the job even on failures?
Thanks

I don't know a lot about Phing but, since it's based on Ant, if the build step you are executing has a "failonerror" attribute you should be able to set it to false so that the entire build doesn't fail if the step returns an error.

Yes, use try, catch block in you pipeline scripts
example:
try {
// do some stuff that potentially fails
} catch (error) {
// do stuff if try fails
} finally {
// when you need some clean up to do
}
Or alternatively if you use sh commands to run these tests, consider running your sh scripts with the "|| true" suffix, this tells the linux sh script to exit with a result code of 0, even if your real command exited with an exit code.
example:
stage('Test') {
def testScript = ""
def testProjects = findFiles(glob: 'test/**/project.json')
if (!fileExists('reports/xml')) {
if (!fileExists('reports')) {
sh "mkdir reports"
}
sh "mkdir reports/xml"
}
for(prj in testProjects) {
println "Test project located, running tests: " + prj.path
def matcher = prj.path =~ 'test\\/(.+)\\/project.json'
testScript += "dotnet test --no-build '${prj.path}' -xml 'reports/xml/${matcher[0][1]}.Results.xml' || true\n"
}
sh testScript

Related

how to play audio in gradle.kts? [duplicate]

I have a gradle build setup at the beginning of which I want to execute a shellscript in a subdirectory that prepares my environment.
task build << {
}
task preBuild << {
println 'do prebuild stuff:'
}
task myPrebuildTask(type: Exec) {
workingDir "$projectDir/mySubDir"
commandLine './myScript.sh'
}
build.dependsOn preBuild
preBuild.dependsOn myPrebuildTask
However, when I execute the task either by calling gradle myPrebuildTask or by simply building the project, the following error occurs:
> A problem occurred starting process 'command './myScript.sh''
Unfortunately, thats all I get.
I have also tried the following - same error.
commandLine 'sh mySubDir/myScript.sh'
I use Gradle 1.10 (needed by Android) on Windows, inside a Cygwin shell. Any ideas?
use
commandLine 'sh', './myScript.sh'
your script itself is not a program itself, that's why you have to declare 'sh' as the program and the path to your script as an argument.
A more generic way of writing the exec task, but portable for Windows/Linux, if you are invoking a command file on the PATH:
task myPrebuildTask(type: Exec) {
workingDir "$projectDir/mySubDir"
if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
commandLine 'cmd', '/c', 'mycommand'
} else {
commandLine 'sh', '-c', 'mycommand'
}
}
This doesn't directly address the use case for the OP (since there is script file in the working directory), but the title of the question is more generic (and drew me here), so it could help someone maybe.
unfortunately options with commandLine not worked for me in any way and my friend find other way with executable
executable "./myScript.sh"
and full task would be
task startScript() {
doLast {
exec {
executable "./myScript.sh"
}
}
}
This works for me in my Android project
preBuild.doFirst {
println("Executing myScript")
def proc = "mySubDir/myScript.sh".execute()
proc.waitForProcessOutput(System.out, System.err)
}
See here for explanation:
How to make System command calls in Java/Groovy?
This is a solution for Kotlin DSL (build.gradle.kts) derived from Charlie Lee's answer:
task<Exec>("MyTask") {
doLast {
commandLine("git")
.args("rev-parse", "--verify", "--short", "HEAD")
.workingDir(rootProject.projectDir)
}
}
Another approach using the Java standard ProcessBuilder API:
tasks.create("MyTask") {
val command = "git rev-parse --verify --short HEAD"
doLast {
val process = ProcessBuilder()
.command(command.split(" "))
.directory(rootProject.projectDir)
.redirectOutput(Redirect.INHERIT)
.redirectError(Redirect.INHERIT)
.start()
process.waitFor(60, TimeUnit.SECONDS)
val result = process.inputStream.bufferedReader().readText()
println(result)
}
}
For more information see:
How to run a command line command with Kotlin DSL in Gradle 6.1.1?
How to invoke external command from within Kotlin code?
for kotlin gradle you can use
Runtime.getRuntime().exec("./my_script.sh")
I copied my shell scipt to /usr/local/bin with +x permission and used it as just another command:
commandLine 'my_script.sh'

Keep workspace when switching stages in combination with agent none

I have a Jenkins pipeline where I want to first build my project (Stage A) and trigger an asynchronous long running external test process with the built artifacts. The external test process then resumes the Job using a callback. Afterwards (Stage B) performs some validations of the test results and attaches them to the job. I don't want to block an executor while the external test process is running so I came up with the following Jenkinsfile which mostly suites my needs:
#!/usr/bin/env groovy
pipeline {
agent none
stages {
stage('Stage A') {
agent { docker { image 'my-maven:0.0.17' } }
steps {
script {
sh "rm testfile.txt"
sh "echo ABCD > testfile.txt"
sh "cat testfile.txt"
}
}
}
stage('ContinueJob') {
agent none
input { message "The job will continue once the asynchronous operation has finished" }
steps { echo "Job has been continued" }
}
stage('Stage B') {
agent { docker { image 'my-maven:0.0.17' } }
steps {
script {
sh "cat testfile.txt"
def data = readFile(file: 'testfile.txt')
if (!data.contains("ABCD")) {
error("ABCD not found in testfile.txt")
}
}
}
}
}
}
However, depending on the load of the Jenkins or the time passed or some unknown other conditions, sometimes the files that I create in "Stage A" are no longer available in "Stage B". It seems that Jenkins switches to a different Docker node which causes the loss of workspace data, e.g. in the logs I can see:
[Pipeline] { (Stage A)
[Pipeline] node
Running on Docker3 in /var/opt/jenkins/workspace/TestJob
.....
[Pipeline] stage
[Pipeline] { (Stage B)
[Pipeline] node
Running on Docker2 in /var/opt/jenkins/workspace/TestJob
Whereas with a successful run, it keeps using e.g. node "Docker2" for both stages.
Note that I have also tried reuseNode true within the two docker sections but that didn't help either.
How can I tell Jenkins to keep my workspace files available?
As pointed out by the comment from #Patrice M. if the files are not that big (which is the case for me) stash/unstash are very useful to solve this problem. I have used this combination now since a couple of months and it has solved my issue.

Parallel execution 'mvn test' in Jenkins

I try to create jenkinsfile for parallel execution command mvn test with different arguments. On the first stage of jenkinsfile I create *.csv file where are will be future arguments for mvn test command. Also I don't know the quantity of parallel stages (it depends on first stage where I get data from DB). So, summarize it again. Logic:
First stage for getting data from DB over command mvn test (with args). On this test I save data into csv file.
In loop of jenkinsfile I read every string, parse it and get args for arallel execution mvn test (with args based on the parsed data).
Now it looks like this (only necessary fragments of jenkinsfile):
def buildProject = { a, b, c ->
node {
stage(a) {
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
sh "mvn -Dtest=test2 test -Darg1=${b} -Darg2=${c}"
}
}
}
}
stages {
stage('Preparation of file.csv') {
steps {
sh 'mvn -Dtest=test1 test'
}
}
stage('Parallel stage') {
steps {
script {
file = readFile "file.csv"
lines = file.readLines()
def branches = [:]
for(i = 0; i < lines.size(); i++) {
values = lines[i].split(';')
branches["${values[0]}"] = { buildProject(values[0], values[1], values[2]) }
}
parallel branches
}
}
}
}
So, which problems do I face now with?
I see in log following error:
[ERROR] The goal you specified requires a project to execute but there is no POM in this directory (/Data/jenkins/workspace//#2)
I look at workspaces of Jenkins and see that there were created several empty(!!!) directories (quantity equals to quantity of parallel stages). And therefore mvn command could be executed because of absence of pom.xml and other files.
In branches the same data are saved on every iteration of loop and in 'stage(a)' I see the same title (but every iteration of loop has unique 'values[0]').
Can you help me with this issue?
Thank you in advance!
So, regarding this jenkins issue issues.jenkins.io/browse/JENKINS-50307 and workaround which could be found there, task could be closed!

Returning Boolean value in Groovy function when Maven build fails in shell script

I have wrote a Jenkins Pipeline Groovy for executing multiple project maven sonar analysis. The code is working fine but the issue is that sometimes build fails for some projects which I need to track it properly. My executeMavenSonarBuild function is given as below
def executeMavenSonarBuild(projectName) {
stage ('Execute Maven Build for '+projectName)
{
sh """ {
cd ${projectName}/
mvn clean install verify sonar:sonar
} || {
echo 'Build Failed'
}
"""
}
return true;
}
If build fails it prints echo 'Build Failed' but how we can return a false Boolean as the return to the function.
You have to get the status from the mvn call itself..which should look like this:
def result = sh ( script: 'mvn ...', returnStatus: true)

jenkins pipeline function errors with no error

I am using a jenkins pipeline script to make product tests on our machines
the father of all tests looks like this
node('nightly-master') {
stage 'run'
println PRODUCTS
oliTest('win7.nightly.test', 'checkAndWaitForInstalledProduct.py', 'esxi', 'opsi-local-image-prepare', 'opsi-local-image-win7', PRODUCTS)
)
}
PRODUCTS is a textbox variable, enetered at the build start
the function oliTest() is this:
def call(SERVERID, CHECKSCRIPT, VIRTUALIZATION, OLIPREPARE, OLINETBOOT, PRODUCTS){
try {
timeout(time: 5, unit: 'HOURS') {
println SERVERID
println CHECKSCRIPT
println VIRTUALIZATION
println OLIPREPARE
println OLINETBOOT
println PRODUCTS
//oliPrepare(SERVERID, CHECKSCRIPT, VIRTUALIZATION, OLIPREPARE, OLINETBOOT)
oliProd(SERVERID, CHECKSCRIPT, VIRTUALIZATION, PRODUCTS)
oliBackup(SERVERID, CHECKSCRIPT, VIRTUALIZATION)
oliRestore(SERVERID, CHECKSCRIPT, VIRTUALIZATION)
}
} catch(error) {
sh "fab -f /home/adminuser/scripts/${VIRTUALIZATIO}Nfab.py powerOffVm:vmName=${SERVERID}"
sh 'return 1'
}
}
the println values are printed correctly into the jenkins log
as soon as the function oliProd() is called the test fails without any error message at the forr loop in the following block
def call(SERVERID, CHECKSCRIPT, VIRTUALIZATION, PRODUCTS){
stage 'install Products'
println SERVERID
println CHECKSCRIPT
println VIRTUALIZATION
println PRODUCTS
sh " echo ${PRODUCTS}"
sh "echo ${SERVERID}"
sh "for i in ${PRODUCTS}; do opsi-admin -d method setProductActionRequestWithDependencies $i ${SERVERID} setup;done"
}
writing it multi line with '''COMMAND''' exists with an error, because ${SERVERID} is not expanded and left empty
Any suggestions how to make things work??
Cheers
Note that you could use have triple double-quotes instead of triple single-quotes. That would have fixed that simple problem.
However, you really should be doing your iteration in the script code itself, instead of trying to do iteration in the shell.
Jon S suggested to resolve script methods such as "echo" against a reference to the "pipeline object as in oliTest(this, ...) where oliTest declares a Script parameter and passes it along to other methods/instances to be used to resolve echo as scriptObj.echo.
println in "call" method of "vars/foo.groovy" works, but not in method in class

Resources