I am interested in including quality gate for my projects. Once built at Jenkins, I have added a script that creates a project on SonarQube server and decides if quality of testing is sufficient (code origin can be found here). Script is bellow
stage('SonarCloud') {
steps {
withSonarQubeEnv('SonarQube') {
sh 'mvn clean package sonar:sonar '
}
}
}
stage("Quality Gate") {
steps {
timeout(time: 15, unit: 'MINUTES') { // If analysis takes longer than indicated time, then build will be aborted
waitForQualityGate abortPipeline: true
script{
def qg = waitForQualityGate() // Waiting for analysis to be completed
if(qg.status != 'OK'){ // If quality gate was not met, then present error
error "Pipeline aborted due to quality gate failure: ${qg.status}"
}
}
}
}
}
The problem is that my build never finishes itself (it gets aborted after timeout. Removing timeout makes it run forever it seems. That being said, the analysis gets created and placed on SonarQube server). This is the message that I see before timeout:
SonarQube task 'AXUx0uqFm6myUuXQbknO' status is 'IN_PROGRESS'
Cancelling nested steps due to timeout
My problem is that I am not an admin of our SonarQube server, so I cannot add a webhook that would solve this problem. I wonder if there is a work around?
I tried replacing
sh 'mvn clean package sonar:sonar '
with
sh 'mvn clean package sonar:sonar -Dsonar.webhooks.project=https://my-jenkins-server.com/sonarqube-webhook/'
but didn't get anywhere.
I also tried to adapt this code, discussed in the similar question, but didn't get far either.
There actually is a way to get around this problem. The proper fix for this is installing the webhook back to Jenkins, but you apparently can't fix that.
The next "proper" fix is to use the SonarQube REST api, but first I need to explain what happens in "waitForQualityGate()".
The first thing it does is use the REST api endpoint "/api/ce/task" to see if the background task is complete. It gets the task id to check for from the "report-task.txt" file, which is formatted like a properties file. If that first check is not SUCCESS or ERROR, then it goes into a wait loop, waiting for the webhook to be called.
So, you could implement a really cheap fix by simply adding a "sleep" of more seconds than it ever takes the background task to take, and then calling "waitForQualityGate()".
A more proper fix would do something like this:
def reportFilePath = "target/sonar/report-task.txt"
def reportTaskFileExists = fileExists "${reportFilePath}"
if (reportTaskFileExists) {
echo "Found report task file"
def taskProps = readProperties file: "${reportFilePath}"
echo "taskId[${taskProps['ceTaskId']}]"
while (true) {
sleep 20
def taskStatusResult =
sh(returnStdout: true,
script: "curl -s -X GET -u ${authString} \'${sonarProps['sonar.host.url']}/api/ce/task?id=${taskProps['ceTaskId']}\'")
echo "taskStatusResult[${taskStatusResult}]"
def taskStatus = new JsonSlurper().parseText(taskStatusResult).task.status
echo "taskStatus[${taskStatus}]"
// Status can be SUCCESS, ERROR, PENDING, or IN_PROGRESS. The last two indicate it's
// not done yet.
if (taskStatus != "IN_PROGRESS" && taskStatus != "PENDING") {
break;
}
}
}
Related
I am trying to use the below :
pipeline {
agent { label 'slave1 || slave2' }
stages{
}
}
When I am using the above format, the job is executing in slave1. But when I am reversing the format i.e
agent { label 'slave2 || slave1' }, its still executing on slave1.
Could you please help in clarifying is it the expected way of working. Isn't it something like the label written first, is given first precedence .
This is a feature of Jenkins, not a bug. It tries to be consistent in choosing a slave, as this has a potential of saving some time. For example, on a slave that was used previously, the results of a checkout may still be in the workspace.
Since slave1 fits both the requirements of 'slave1 || slave2' and 'slave2 || slave1', Jenkins will use it. If it's unavailable or busy, some other slave will be used instead.
I'm using Jenkins ver. 2.150.1 and have some freestyle jobs and some pipeline jobs.
In both job types I am using the emailext plugin, with template and pre-send scripts.
It seems that the build variable, which is available in the freestyle projects, is null in the pipeline projects.
The pre-send script is the following (just an example, my script is more complex):
msg.setSubject(msg.getSubject() + " [" + build.getUrl() + "]")
There is no problem with the msg variable.
In the freestyle job, this script adds the build url to the mail subject.
In the pipeline job, the following is given in the job console:
java.lang.NullPointerException: Cannot invoke method getUrl() on null object
The invocation of emailext in the pipeline job is:
emailext body: '${SCRIPT, template="groovy-html.custom.pipeline.sandbox.template"}',
presendScript: '${SCRIPT, template="presend.sandbox.groovy"}',
subject: '$DEFAULT_SUBJECT',
to: 'user#domain.com'
I would rather find a general solution to this problem (i.e. Access the build variable in a pipeline pre-send script), but would also appreciate any workarounds to my current needs:
Access job name, job number, and workspace folder in a pipeline pre-send script.
I have finally found the answer -
Apparently for presend script in pipeline jobs, the build object does not exist, and instead the run object does. At the time I posted this question this was still undocumented!
Found the answer in this thread
Which got the author to update the description in the wiki:
run - the build this message belongs to (may be used with FreeStyle or Pipeline jobs)
build - the build this message belongs to (only use with FreeStyle jobs)
You can access the build in a script like this:
// findUrl.groovy
def call(script) {
println script.currentBuild.rawBuild.url
// or if you just need the build url
println script.env.BUILD_URL
}
and would call the script like this from the pipeline:
stage('Get build URL') {
steps {
findUrl this
}
}
The currentBuild gives you a RunWrapper object and the rawBuild a Run. Hope this helps.
I'm generating a Jenkins pipeline using a script. This pipeline is then loaded and executed. This works fine on any linux node and with sh statements etc.
I have now encountered an issue executing this on a windows node with the powershell and bat steps:
The checkout scm works fine, but any steps with the powershell or bat steps hang indefinitely. Copying the data from the generated file and replaying everything in a single Jenkinsfile works as expected.
An example of what is running (excluding the library):
"Main" Jenkinsfile:
def pod_label = "my_linux_node"
node(pod_label) {
stage("Checkout") {
checkout scm
}
stage("Pipeline generation") {
// genarate pipeline and save in "gen_pipeline.groovy"
}
stage("Run Pipeline") {
pipeline = load "gen_pipeline.groovy"
pipeline.run_pipeline()
}
}
Script1:
def run_pipeline(){
node('my_win_node') {
checkout scm
bat "echo foobar"
}
}
return this
I have a project that imports a Git submodule to run a part of an XCTest test suite. If the submodule is not available (not checked out), I want the test suite to succeed, but issue a warning that not all tests were run. Is that possible?
Searching for similar issue I have found out that we could add messages to test logs as string attachments. If you want to have a warning sign you can add ⚠️ emoji in name.
Here is a function example that adds it.
func addLogMessage(_ message: String, attachmentLifetime: XCTAttachment.Lifetime = .keepAlways) {
XCTContext.runActivity(named: "Log message") { activity in
let messageAttachment = XCTAttachment(string: message)
messageAttachment.lifetime = attachmentLifetime
activity.add(messageAttachment)
}
}
I am running grails 2.3.3 in a GGTS.
I am successfully running a single unit test for a service function within the Spring GGTS.
I am hoping to be able to use this unit test to develop the particular function - such an approach will really speed up my development going forward.
This means I need to make changes to the service function that is being tested and then retest over and over again (no doubt a sad reflection on my coding skills!). The problem is when I make a change to the logic or any log.debug output it does not come through in the test. In other words the test continues to run against the original service function and not the updated one.
In order for me to force it to use the updated function the only way I have found that will do this is to restart the GGTS!
Is there a command I can use in GGTS to force a test on the most recent version of the function I am testing?
Here are the commands I am using within the GTTS:
test-app unit: UtilsService
I do run a clean after a function update without any success:
test-app -clean
I am also struggling with getting additional output from within the test function - introducing 'println' or 'log.debug' commands results in a failure of the test.
It would be useful to know of a good link to documentation about the test syntax - I have looked at grails section 12 about testing in general.
Here is the test file:
package homevu1
import grails.test.mixin.TestFor
import spock.lang.Specification
/**
* See the API for {#link grails.test.mixin.services.ServiceUnitTestMixin} for usage instructions
*/
#TestFor(UtilsService)
class UtilsServiceSpec extends Specification {
// to test utilSumTimes for example use the command :
// test-app utilSumTimes
// test-app HotelStay
def setup() {
}
def cleanup() {
}
void "test something"() {
when:
def currSec = service.utilSumTimeSecs( 27, 1, false)
//println "currSec" , currSec
then:
//println "currSec" , currSec
assert currSec == "26"
}
}
If I uncomment either of the println lines these comments are not displayed and the test fails.
Welcome any suggestions.
-mike
I've to get this working now by running grail from a command prompt (in MS Windows).
In the command prompt I moved to the root folder/directory of the grails project - in my case:
cd C:\grails\workspace\rel_3.1.0\HomeVu
Then I type grails to start a grails command line session.
The unit test command I used being:
test-app -unit UtilsService -echoOut -echoErr
That said I still am unable to successfully put any print commands in the test file - but I can use the assert to determine any problems.
Also output from the last log.debug line of the grails code of the service function fails to appears. Perhaps there is some output buffering issue with MS Windows here.
At least I can now do some rapid function development, by making changes to the service/function code and instantly test is against a set of known requirement conditions.
Hope this helps others.
-mike