How to set non-default quality gate for new sonar projects - jenkins

We use jenkins, sonarqube 5.5, maven and git. When developers create a new git branch and push it, jenkins analyses the branch too, so the developers can fix everything before merging. To avoid this development branch analysis mixing up with the master branch analysis, jenkins passes the branch name into the analysis. The causes sonarqube to create a new project for each branch. So far that's ok.
But recently we switched from one default quality gate for all projects to different quality gates for projects under active development and projects which are just in maintenance.
So how can we tell sonar when creating an new project for a new branch which quality gate to use? Until some versions ago, there was a sonar.qualitygate property which could be set. But now this is deprecated. So what's the new way to define the proper quality gate for a newly created project?

You can use the rest api provided by Sonar.
Step 1. Create gate
def result = ["curl", "--user", auth, "-X", "POST", "-H", "Content-Type: application/json", "-d", "{'name':'" + qualityGateName + "'}", "https://yoursonarserver/api/qualitygates/create"].execute().text
Step 2 Bind project into the gate
["curl", "--user", auth, "-X", "POST", "-H", "Content-Type: application/json", "-d", "{'gateId':'"+qualityGateId+"','projectId':'"+projectId+"'}", "https://yoursonarserver/qualitygates/select"].execute().text
About how to get the projectId and qualityGateId, you can use the following two apis
Get project ID
String result = ["curl", "--user", auth , "-X", "GET", "-H", "Accept: application/json", "https://yoursonarserver/api/projects/index", "-d", "search=" + projectName ].execute().text
Get Quality gate id
def result = ["curl", "--user", auth, "-X", "GET", "-H", "Accept: application/json", "https://yoursonarserver/api/qualitygates/list"].execute().text
The above two apis will get a list of ids, so you need parse them based the project name.
Br,
Tim

Related

Excluding Draft PRs from Jenkins

I will like to be able to choose to only run Jenkins build on PRs who are not marked as draft. Is there currently a way to do that?
I found something like this: https://github.com/jenkinsci/github-branch-source-plugin/pull/416, but cannot seem to find any place in the Jenkins dashboard that will allow me to exclude draft PRs.
Thanks!
The GitHub API allows you to view details of a PR and see if the PR is a draft:
Request:
curl \
-H "Accept: application/vnd.github+json" \
-H "Authorization: token <TOKEN>" \
https://api.github.com/repos/OWNER/REPO/pulls/PULL_NUMBER
Response:
{
"url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347",
"id": 1,
"node_id": "MDExOlB1bGxSZXF1ZXN0MQ==",
...
"auto_merge": null,
"draft": false, <---- This is what you want
"merged": false,
...
"deletions": 3,
"changed_files": 5
}
You will have to modify the Jenkins job itself to perform this API call, parse the response and get the value of draft, and continue or abort the build depending on the value.

Unable to get the payload from GitHub web hook trigger in jenkins pipeline

I have configured a Github web hook with the below settings:
Payload URL: https:///github-webhook/
Content Type: application/x-www-form-urlencoded
Events : Pushes, Pull Requests
The Jenkins job that I have, is a pipeline job that has the below enabled:
Build Trigger: GitHub hook trigger for GITScm polling
With the above configuration, I see that in response to an event ie; push/PR in GitHub, the jenkins job gets triggered successfully. In GitHub, under Recent Deliveries for the web hook, I see the details of the payload and a successful Response of 200.
I am trying to get the payload in Jenkins Pipeline for further processing. I need some details eg: PR URL/PR number, refs type, branch name etc for conditional processing in the Jenkins Pipeline.
I tried accessing the "payload" variable (as mentioned in other stack overflow posts and the documentations available around) and printing it as part of the pipeline, but I have had no luck yet.
So my question is, How can I get the payload from GitHub web hook trigger in my Jenkins Pipeline ?
You need to select Content type: application/json in your webhook in GitHub. Then you would be able to access any variable from the payload GitHub sends as follows: $. pull_request.url for pr url, for example.
Unsure if this is possible.
With the GitHub plugin we use (Pipeline Github), PR number is stored in the variable CHANGE_ID.
PR URL is pretty easy to generate given the PR number. Branch name is stored in the variable BRANCH_NAME. In case of pull requests, the global variable pullRequest is populated with lots of data.
Missing information can be obtained from Github by using their API. Here's an example of checking if PR is "behind", you can modify that to your specific requirements:
def checkPrIsNotBehind(String repo) {
withCredentials([usernamePassword(credentialsId: "<...>",
passwordVariable: 'TOKEN',
usernameVariable: 'USER')]) {
def headers = ' -H "Content-Type: application/json" -H "Authorization: token $TOKEN" '
def url = "https://api.github.com/repos/<...>/<...>/pulls/${env.CHANGE_ID}"
def head_sha = sh (label: "Check PR head SHA",
returnStdout: true,
script: "curl -s ${url} ${headers} | jq -r .head.sha").trim().toUpperCase()
println "PR head sha is ${head_sha}"
headers = ' -H "Accept: application/vnd.github.v3+json" -H "Authorization: token $TOKEN" '
url = "https://api.github.com/repos/<...>/${repo}/compare/${pullRequest.base}...${head_sha}"
def behind_by = sh (label: "Check PR commits behind",
returnStdout: true,
script: "curl -s ${url} ${headers} | jq -r .behind_by").trim().toUpperCase()
if (behind_by != '0') {
currentBuild.result = "ABORTED"
currentBuild.displayName = "#${env.BUILD_NUMBER}-Out of date"
error("The head ref is out of date. Please update your branch.")
}
}
}

How to access variables relating to a TFS commit in build definition

I'm using the "Post to Slack" task as one of my build steps in TFS 2018 and I'm wondering how to access variables relating to that commit. I would like to include them as part of the Message field (something like "Commit: $(CommitMessage) link to changeset $(ChangesetLink)" but those variables don't exist). Here is where I need to reference the variables in TFS:
This document: link describes how to access build variables but it doesn't mention anything relating to the commit. I would like to access the commit message, associated commit changesets and the link to the changeset(s) associated with the commit. Does anyone know how to do this or know where I can find documentation for it? Thank you
Cruiser is right, no such Predefined variables in TFS, you can retrieve the needed information by REST API, then set corresponding variables using the Logging Commands.
Create a PowerShell script to set the avariables (Reference below
sample, you can also Use the OAuth token to access the REST API), then commit and push the script into TFS.
Add a PowerShell task before the "Post to Slack" task in your
definition to run the PS script
Use the variables $(commitID), $(CommitMessage) and
$(commitUrl) in "Post to Slack" task
Note: For Git it's commit, For TFVC it's changeset
You can use below script to set the variables:
Param(
[string]$collectionurl = "http://server:8080/tfs/DefaultCollection",
[string]$repoid = "389e8215-1fb2-4fdc-bd04-ebc8a8a4410e",
[string]$user = "username",
[string]$token = "password"
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$searchCriteria = "$" + "top=1"
$baseUrl = "$collectionurl/_apis/git/repositories/$repoid/commits?$searchCriteria"
$response = (Invoke-RestMethod -Uri $baseUrl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
#Retrieve values
$commitID = $response.value.commitID
$CommitMessage = $response.value.comment
$commitUrl = $response.value.remoteUrl
#Set variables
Write-Host "##vso[task.setvariable variable=commitID]$commitID"
Write-Host "##vso[task.setvariable variable=CommitMessage]$CommitMessage"
Write-Host "##vso[task.setvariable variable=commitUrl]$commitUrl"
UPDATE:
You can use this REST API to get the repository ID:
GET http://server:8080/tfs/DefaultCollection/{ProjectName}/_apis/git/repositories

Get BuildInfo From Artifactory Using Jenkins

Using Jenkins DSL I can create and publish build info using Artifactory.newBuildInfo but am looking for the complementary method to read the BuildInfo JSON data that is generated on Artifactory. Have trolled through many resources. Any suggestions would be appreciated.
From Artifactory REST API it sure looks like you can retrieve buildInfo. I'd expect this must be exposed from the jenkins plugin as well.
Build Info
Description: Build Info
Since: 2.2.0
Security: Requires a privileged user with deploy permissions (can be anonymous)
Usage: GET /api/build/{buildName}/{buildNumber}
Produces: application/vnd.org.jfrog.build.BuildInfo+json
...
JFrog's project examples on github is a fabulous resource as is their jenkins plugin
From a quick search it looks like you'd define a download spec and then use server.download method (see Working with Pipeline Jobs in Jenkins
def buildInfo1 = server.download downloadSpec
The previous answer creates a new buildInfo, it does not download the original buildInfo into I've been trying for days to try to figure out how to do what the original poster wants to do. The best I've succeeded at is downloading the buildinfo into a hashtable, work with that, then upload the changes doing REST calls.
def curlstr = "curl -H 'X-JFrog-Art-Api:${password}' ${arturl}api/build/${buildName}/${buildNumber}"
def buildInfoString = sh(
script: curlstr,
returnStdout: true
).trim()
buildInfo = (new JsonSlurperClassic().parseText(buildInfoString))
sh("echo '${JsonOutput.toJson(buildInfo)}'|curl -XPUT -H 'X-JFrog-Art-Api:${password}' -H 'Content-Type: application/json' ${arturl}api/build --upload-file - ")
I was able to modify the buildInfo in the artifactory repository using this technique. Not as clean as I would like. I've been unable to get the jfrogCLI to modify existing buildInfo files either.
For whatever it's worth the intent of what I'm trying to do is promote a docker artifact and change the name while doing it. There is no way I've found to express this to artifactory not involving downloading the artifact to docker and then pushing it again. I'd love it if someone from #jfrog could clue me in how to do it.
UPDATE: Attention! I've got the question wrong. This is how you get the local BuildInfo-Object in a declarative pipeline script.
I managed this by using an internal api from jenkins-artifactory-plugin.
// found in org.jfrog.hudson.pipeline.declarative.utils.DeclarativePipelineUtils
/**
* Get build info as defined in previous rtBuildInfo{...} scope.
*
* #param rootWs - Step's root workspace.
* #param build - Step's build.
* #param customBuildName - Step's custom build name if exist.
* #param customBuildNumber - Step's custom build number if exist.
* #return build info object as defined in previous rtBuildInfo{...} scope or a new build info.
*/
public static BuildInfo getBuildInfo(FilePath rootWs, Run<?, ?> build, String customBuildName, String customBuildNumber, String project) throws IOException, InterruptedException {
...
}
Whith this code you can fetch the BuildInfo inside a declarative pipeline script step.
def buildInfo = org.jfrog.hudson.pipeline.declarative.utils.DeclarativePipelineUtils.getBuildInfo(new hudson.FilePath(new java.io.File(env.WORKSPACE)), currentBuild.rawBuild, null, null, null);
UPDATE: Beware of custom build names and numbers. I you have defined a custom build name and/or build number, you have to provide it with the getBuildInfo call.

Artifactory build options for maven build and issues

I am new to Artifactory and I find that there is a lot of documentation on the different ways to get artifacts to Artifactory but nothing that is complete.
For example:
The pipeline plugin used by jenkins:
sample code:
node {
def server = Artifactory.newServer url: SERVER_URL, credentialsId: CREDENTIALS
def rtMaven = Artifactory.newMavenBuild()
stage 'Build'
git url: 'https://github.com/jfrogdev/project-examples.git'
stage 'Artifactory configuration'
rtMaven.tool = MAVEN_TOOL // Tool name from Jenkins configuration
rtMaven.deployer releaseRepo:'libs-release-local', snapshotRepo:'libs-snapshot-local', server: server
rtMaven.resolver releaseRepo:'libs-release', snapshotRepo:'libs-snapshot', server: server
def buildInfo = Artifactory.newBuildInfo()
stage 'Exec Maven'
rtMaven.run pom: 'maven-example/pom.xml', goals: 'clean install', buildInfo: buildInfo
stage 'Publish build info'
server.publishBuildInfo buildInfo
}
I am not sure how to set up some variables like CREDENTIALS. specially if I want to use api key not user id and password.
Also, if I want to use the Artifactory rest API to build and promote my project(Maven Build). should I be using:
curl -X PUT "http://localhost:8080/artifactory/api/build" -H "Content-Type: application/json" --upload-file build.json
Where build.json is the sample JSON at https://www.jfrog.com/confluence/display/RTF/Artifactory+REST+API under Build Upload.
If i use the API do i still need the above jenkins plugin code or can just use the API?
Where do I pass my credentials (Userid and APi key) in the curl command?
If any experienced user could guide me with these questions that will be of great help.

Resources