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

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)

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'

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!

jenkinsfile - How do I access custom properties in my pom.xml?

Let's say I have a custom property in my pom.xml set like this:
<properties>
<app>com.myProject.app</app>
</properties>
How can I access it in my jenkinsfile?
This:
def pom = readMavenPom file: 'pom.xml'
def appName = pom.app
returns
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: unclassified field org.apache.maven.model.Model app
Thanks in advance!
I know two approaches:
Use properties-maven-plugin to write the properties to a file. Use readProperties in the Jenkinsfile to read the properties.
Works only if properties aren't needed until after Maven ran.
Also, with the right circumstances, the properties file may be the stale one from a previous run, which is insiduous because the property values will be right anyway 99.9% of the time.
Use pom = readMavenPom 'path/to/pom.xml'. Afterwards, access the property like this: pom.properties['com.myProject.app'].
I like approach 2 much better: No extra plugin configuration in the POM, no file written, less sequencing constraints, less fragilities.
In pipeline style, inside Jenkinsfile you can access the value as follows
pipeline {
environment {
POM_APP = readMavenPom().getProperties().getProperty('app')
}
stages{
stage('app stage'){
steps{
script{
sh """
echo ${POM_APP}
"""
}
}
}
}
Read a maven project file
try this:
IMAGE = readMavenPom().getArtifactId()
VERSION = readMavenPom().getVersion()
jenkins pipeline add this stage.
more see
stage('info')
{
steps
{
script
{
def version = sh script: 'mvn help:evaluate -Dexpression=project.version -q -DforceStdout', returnStdout: true
def artifactId = sh script: 'mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout', returnStdout: true
}
}
}

Unable to create a Gradle task rule with an Exec task

I'm trying to write a task rule to create a series of tasks that checkout various svn repository locations. Here is my rule:
tasks.addRule("Pattern: svnCheckout&ltClassifier> - Checks out the indicated svn repo") { String taskName ->
if(taskName.startsWith('svnCheckout')) {
task(name: taskName, type: Exec) {
String classifier = taskName - 'svnCheckout'
String svnDir = svnRepoUrl //defined elsewhere
switch(classifier) {
case 'SourceTrunk':
svnDir += 'branches/CleanBuild/trunk'
break
case 'AutoInstaller':
svnDir += 'Tools/AutoInstaller'
break
case 'ContentAutomation':
svnDir += 'Tools/ContentAutomation'
break
case 'InternalTools':
svnDir += 'Tools/Internal'
break
default:
throw new GradleException("Invalid svnCheckout classifier '$classifier'")
}
String svnCommand = "svn co $svnDir --trust-server-cert"
//commandLine 'cmd', '/c', "$svnCommand"
commandLine 'cmd', '/c/', "echo 'Task created'"
workingDir = "$workspace"
}
}
}
I then try to run the task 'svnCheckoutSourceTrunk' with this command:
gradlew -Pworkspace="." svnCheckoutSourceTrunk
which fails with the error
FAILURE: Could not determine which tasks to execute.
* What went wrong:
Task 'svnCheckoutSourceTrunk' not found in root project 'GradleScripts'.
* Try:
Run gradlew tasks to get a list of available tasks.
BUILD FAILED
Anyone see what I'm doing wrong? I put some println statements around the first few lines, and the execution is getting past the if statement, but it's not getting inside the task declaration.
The syntax used for declaring the task(s) is incorrect. (Not sure why it's not giving an error.) The first positional argument always need to be the task name:
task(taskName, type: Exec) { ... }
In a build script, this will also work:
task "$taskName"(type: Exec) { ... }

How to continue a Jenkins build even though a build step failed?

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

Resources