Reputation: 91
I have a Jenkins pipeline with parallel steps.
Step A is building a spring-boot application, while step B is launching another spring-boot application (mvn spring-boot:run), meant to make a bridge between the tests and the database.
My goal is to close step B (spring-boot:stop ?) when step A is done (Success or Failure).
I'm trying to avoid to use a timeout, as it's not very optimized.
Do you have any solution ?
Thanks a lot.
I've tried to launch spring-boot:stop after my test passed, but to na avail. Same thing with setting a boolean variable to stop a while loop/
parallel(
a: {
Sonar: {
withSonarQubeEnv {
withMaven(maven: 'Apache Maven 3.3.9') {
sh '''
echo "lauching sonar check"
cd git-42c
mvn -Dmaven.test.failure.ignore verify sonar:sonar
cd ..
'''
}
}
}
},
b: {
// Run the maven build
withMaven(maven: 'Apache Maven 3.3.9') {
dir('git-proxy') {
echo "launching mvn spring-boot:run"
sh "mvn spring-boot:run -Dpmd.skip=true -Dcpd.skip=true -Dfindbugs.skip=true"
}
}
}
)
}
I expect step B to stop when step A has finished (always), but my build stays suspended indefinitely as Step B is running the app.
Upvotes: 2
Views: 2708
Reputation: 91
OK, found a solution.
Reminder : my goal was launching and stopping a spring boot app in parallel of my build.
As I could not find a way to remotely kill a parallel step from antoher step, I had to use a non-elegant way to do it : time out.
A step time-out does not work, as it times out only if the command does not launch, but spring-boot:run launches.
DOES NOT WORK : timeout(time: 1, unit: 'MINUTES') { [...] }
So the timeout has to be in the command itself. This is what it looks like at first :
sh "timeout -s KILL 1m mvn spring-boot:run -Dpmd.skip=true -Dcpd.skip=true -Dfindbugs.skip=true
So after 1 minute, my run is killed. This implies a new problem, the kill fails the parallel step, so even if the job finishes with a build success, it is still considered failed, as one branch of the job has "failed".
Now, to avoid the fail, a solution would be to consider the spring-boot step to always be succesful. This is done by using command || true
.
Like this :
sh "timeout -s KILL 1m mvn spring-boot:run -Dpmd.skip=true -Dcpd.skip=true -Dfindbugs.skip=true || true"
As for now, my parallel step finishes in a green success.
Per my sample in the question, this is the same sample working :
stage('Scan Sonar') {
parallel(
a: {
Sonar: {
withSonarQubeEnv {
withMaven(maven: 'Apache Maven 3.3.9') {
sh '''
echo "lauching sonar check"
cd git-42c
mvn -Dmaven.test.failure.ignore verify sonar:sonar
cd ..
'''
}
}
}
},
b: {
// Run the maven build
withMaven(maven: 'Apache Maven 3.3.9') {
dir('git-proxy') {
echo "launching mvn spring-boot:run"
sh "timeout -s KILL 1m mvn spring-boot:run -Dpmd.skip=true -Dcpd.skip=true -Dfindbugs.skip=true || true"
}
}
}
)
}
Upvotes: 1
Reputation: 4678
An elegant solution I could think of would be sidecar
container, but that requires docker and scripted pipeline.
node {
checkout scm
docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw"') { c ->
docker.image('mysql:5').inside("--link ${c.id}:db") {
/* Wait until mysql service is up */
sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done'
}
docker.image('centos:7').inside("--link ${c.id}:db") {
/*
* Run some tests which require MySQL, and assume that it is
* available on the host name `db`
*/
sh 'make check'
}
}
}
There of course an option to synchronize on a flag like:
stop = false
parallel 'long': {
sleep 20
println "finished long process"
stop = true
}, 'short': {
while ( !stop ) {
println "work"
sleep 1
}
println "stopped by other branch"
}
But that wouldn't work for you as you don't have a loop anywhere.
Neither would failFast
on parallel.
It would seem that even if you would cancel the stage from Jenkins REST API you would still fail the build.
So what is the outcome you are looking for? If you don't what the build failed you have to introduce some mechanism to synchronize the state on.
Upvotes: 1