Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat-sonarqube: Added sonar quality gateway conversion #257

Merged
merged 6 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions convert/jenkinsjson/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,9 @@ func collectStepsWithID(currentNode jenkinsjson.Node, stepWithIDList *[]StepWith
case "unarchive":
*stepWithIDList = append(*stepWithIDList, StepWithID{Step: jenkinsjson.ConvertUnarchive(currentNode, currentNode.ParameterMap), ID: id})

case "waitForQualityGate":
*stepWithIDList = append(*stepWithIDList, StepWithID{Step: jenkinsjson.ConvertSonarQualityGate(currentNode), ID: id})

default:
placeholderStr := fmt.Sprintf("echo %q", "This is a place holder for: "+currentNode.AttributesMap["jenkins.pipeline.step.type"])
b, err := json.MarshalIndent(currentNode.ParameterMap, "", " ")
Expand Down
81 changes: 81 additions & 0 deletions convert/jenkinsjson/convertTestFiles/sonarQualityGate/Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
pipeline {
agent any

environment {
// SonarScanner version to download
SONAR_SCANNER_VERSION = '4.7.0.2747'
}

tools {
maven 'maven1' // Make sure this matches the name you gave to your Maven installation in Jenkins
}

stages {
stage('Clone Repository') {
steps {
// Clone the repository
git url: 'https://github.com/SonarSource/sonar-scanner-maven.git', branch: 'master'
}
}

stage('Install Dependencies') {
steps {
// Install Maven dependencies and build the project
sh 'mvn clean install'
}
}

stage('Debug Workspace') {
steps {
sh 'ls -l' // Debug workspace to ensure 'src' directory exists
}
}
stage('Prepare SonarScanner') {
steps {
script {
sh 'rm -rf sonar-scanner'
// Download and configure SonarScanner
sh """
mkdir -p sonar-scanner
curl -k -o sonar-scanner-cli.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}.zip
unzip -q sonar-scanner-cli.zip -d sonar-scanner
mv sonar-scanner/sonar-scanner-* sonar-scanner/sonar-scanner
export PATH=\$PWD/sonar-scanner/sonar-scanner/bin:\$PATH
"""
}
script {
env.SONAR_SCANNER = "${pwd()}/sonar-scanner/sonar-scanner/bin/sonar-scanner"
}
}
}

stage('SonarQube Analysis') {
steps {
withSonarQubeEnv('SonarCloud') { // Matches the name in Jenkins configuration
sh "${SONAR_SCANNER} -Dsonar.projectKey=vanisrikanithi_Test-Sonarqube" +
'-Dsonar.organization=vanisrikanithi' +
'-Dsonar.login=b751ddb91e11f466d7cdfa0abd65b4a6c393d938 ' +
'-Dsonar.sources=src ' +
'-Dsonar.java.binaries=target/classes'
}
}
}

stage('Quality Gate') {
steps {
script {
def qualityGate = waitForQualityGate()
// If the quality gate fails, log the status but don't abort the pipeline
if (qualityGate.status != 'OK' && qualityGate.status != 'NONE') {
echo "Quality Gate failed with status: ${qualityGate.status}. Continuing the pipeline."
} else if (qualityGate.status == 'NONE') {
echo 'Quality Gate status is NONE. Check SonarQube configuration.'
} else {
echo "Quality Gate passed with status: ${qualityGate.status}."
}
}
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"spanId": "6278c948712d469b",
"traceId": "cabb36d4166869b97fa171bad088089e",
"parent": "vani_sonar",
"all-info": "span(name: waitForQualityGate, spanId: 6278c948712d469b, parentSpanId: 946f9b55ba22bc28, traceId: cabb36d4166869b97fa171bad088089e, attr: ci.pipeline.run.user:SYSTEM;harness-attribute-extra-pip: com.cloudbees.workflow.rest.endpoints.FlowNodeAPI@41a4035:com.cloudbees.workflow.rest.endpoints.FlowNodeAPI@41a4035;harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@5a518db2:io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@5a518db2;harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@17761c17:org.jenkinsci.plugins.workflow.actions.TimingAction@17761c17;harness-others:;jenkins.pipeline.step.id:92;jenkins.pipeline.step.name:Wait for SonarQube analysis to be completed and return quality gate status;jenkins.pipeline.step.plugin.name:sonar;jenkins.pipeline.step.plugin.version:2.17.2;jenkins.pipeline.step.type:waitForQualityGate;)",
"name": "vani_sonar #13",
"attributesMap": {
"harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@5a518db2": "io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@5a518db2",
"harness-others": "",
"jenkins.pipeline.step.name": "Wait for SonarQube analysis to be completed and return quality gate status",
"ci.pipeline.run.user": "SYSTEM",
"jenkins.pipeline.step.id": "92",
"jenkins.pipeline.step.type": "waitForQualityGate",
"harness-attribute-extra-pip: com.cloudbees.workflow.rest.endpoints.FlowNodeAPI@41a4035": "com.cloudbees.workflow.rest.endpoints.FlowNodeAPI@41a4035",
"harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@17761c17": "org.jenkinsci.plugins.workflow.actions.TimingAction@17761c17",
"jenkins.pipeline.step.plugin.name": "sonar",
"jenkins.pipeline.step.plugin.version": "2.17.2"
},
"type": "Run Phase Span",
"parentSpanId": "946f9b55ba22bc28",
"spanName": "waitForQualityGate"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
- step:
identifier: waitforqualitygate6278c9
name: Sonarqube_Quality_Gate
spec:
image: 'plugins/sonarqube-scanner:latest'
settings:
scm_disabled: 'false'
skip_scan: 'false'
sonar_host: <+input>
sonar_key: <+input>
sonar_name: <+input>
sonar_organization: <+input>
sonar_quality_enabled: 'true'
sonar_qualitygate: OK
sonar_token: <+input>
sources: .
timeout: '300'
timeout: ''
type: Plugin
Original file line number Diff line number Diff line change
@@ -1,51 +1,51 @@
{
"spanId": "c9943fda45b8312f",
"traceId": "f59bb3660fe13cc634fb357b59c0f1d7",
"parent": "sonarcube",
"all-info": "span(name: Stage: null, spanId: c9943fda45b8312f, parentSpanId: 32035723074a4821, traceId: f59bb3660fe13cc634fb357b59c0f1d7, attr: harness-others:;jenkins.pipeline.step.type:wrap;)",
"children": [
{
"spanId": "952bc3bfafb5bdcf",
"traceId": "f59bb3660fe13cc634fb357b59c0f1d7",
"parent": "sonarcube",
"all-info": "span(name: Stage: null, spanId: 952bc3bfafb5bdcf, parentSpanId: c9943fda45b8312f, traceId: f59bb3660fe13cc634fb357b59c0f1d7, attr: harness-others:;jenkins.pipeline.step.type:wrap;)",
"name": "sonarcube #9",
"attributesMap": {
"harness-others": "",
"jenkins.pipeline.step.type": "wrap"
"spanId": "c9943fda45b8312f",
"traceId": "f59bb3660fe13cc634fb357b59c0f1d7",
"parent": "sonarcube",
"all-info": "span(name: Stage: null, spanId: c9943fda45b8312f, parentSpanId: 32035723074a4821, traceId: f59bb3660fe13cc634fb357b59c0f1d7, attr: harness-others:;jenkins.pipeline.step.type:wrap;)",
"children": [
{
"spanId": "952bc3bfafb5bdcf",
"traceId": "f59bb3660fe13cc634fb357b59c0f1d7",
"parent": "sonarcube",
"all-info": "span(name: Stage: null, spanId: 952bc3bfafb5bdcf, parentSpanId: c9943fda45b8312f, traceId: f59bb3660fe13cc634fb357b59c0f1d7, attr: harness-others:;jenkins.pipeline.step.type:wrap;)",
"name": "sonarcube #9",
"attributesMap": {
"harness-others": "",
"jenkins.pipeline.step.type": "wrap"
},
"type": "Run Phase Span",
"parentSpanId": "c9943fda45b8312f",
"spanName": "Stage: null"
},
"type": "Run Phase Span",
"parentSpanId": "c9943fda45b8312f",
"spanName": "Stage: null"
{
"spanId": "65bb92aeb82fcdc5",
"traceId": "f59bb3660fe13cc634fb357b59c0f1d7",
"parent": "sonarcube",
"all-info": "span(name: sh, spanId: 65bb92aeb82fcdc5, parentSpanId: c9943fda45b8312f, traceId: f59bb3660fe13cc634fb357b59c0f1d7, attr: ci.pipeline.run.user:SYSTEM;harness-attribute:{\n \"script\" : \"/Users/rakshitagarwal/.jenkins/tools/hudson.plugins.sonar.SonarRunnerInstallation/sonar_cube/bin/sonar-scanner -Dsonar.projectKey=jenkins-SonarCube -Dsonar.projectName=jenkins-SonarCube -Dsonar.sources=.\"\n};harness-others:-WATCHING_RECURRENCE_PERIOD-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep WATCHING_RECURRENCE_PERIOD-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.WATCHING_RECURRENCE_PERIOD-long-USE_WATCHING-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep USE_WATCHING-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.USE_WATCHING-boolean-REMOTE_TIMEOUT-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep REMOTE_TIMEOUT-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.REMOTE_TIMEOUT-long;jenkins.pipeline.step.id:19;jenkins.pipeline.step.name:Shell Script;jenkins.pipeline.step.plugin.name:workflow-durable-task-step;jenkins.pipeline.step.plugin.version:1336.v768003e07199;jenkins.pipeline.step.type:sh;)",
"name": "sonarcube #9",
"attributesMap": {
"harness-others": "-WATCHING_RECURRENCE_PERIOD-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep WATCHING_RECURRENCE_PERIOD-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.WATCHING_RECURRENCE_PERIOD-long-USE_WATCHING-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep USE_WATCHING-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.USE_WATCHING-boolean-REMOTE_TIMEOUT-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep REMOTE_TIMEOUT-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.REMOTE_TIMEOUT-long",
"jenkins.pipeline.step.name": "Shell Script",
"ci.pipeline.run.user": "SYSTEM",
"jenkins.pipeline.step.id": "19",
"jenkins.pipeline.step.type": "sh",
"harness-attribute": "{\n \"script\" : \"/Users/rakshitagarwal/.jenkins/tools/hudson.plugins.sonar.SonarRunnerInstallation/sonar_cube/bin/sonar-scanner -Dsonar.projectKey=jenkins-SonarCube -Dsonar.projectName=jenkins-SonarCube -Dsonar.sources=.\"\n}",
"jenkins.pipeline.step.plugin.name": "workflow-durable-task-step",
"jenkins.pipeline.step.plugin.version": "1336.v768003e07199"
},
"type": "Run Phase Span",
"parentSpanId": "c9943fda45b8312f",
"parameterMap": {"script": "/Users/rakshitagarwal/.jenkins/tools/hudson.plugins.sonar.SonarRunnerInstallation/sonar_cube/bin/sonar-scanner -Dsonar.projectKey=jenkins-SonarCube -Dsonar.projectName=jenkins-SonarCube -Dsonar.sources=."},
"spanName": "sh"
}
],
"name": "sonarcube #9",
"attributesMap": {
"harness-others": "",
"jenkins.pipeline.step.type": "wrap"
},
{
"spanId": "65bb92aeb82fcdc5",
"traceId": "f59bb3660fe13cc634fb357b59c0f1d7",
"parent": "sonarcube",
"all-info": "span(name: sh, spanId: 65bb92aeb82fcdc5, parentSpanId: c9943fda45b8312f, traceId: f59bb3660fe13cc634fb357b59c0f1d7, attr: ci.pipeline.run.user:SYSTEM;harness-attribute:{\n \"script\" : \"/Users/rakshitagarwal/.jenkins/tools/hudson.plugins.sonar.SonarRunnerInstallation/sonar_cube/bin/sonar-scanner -Dsonar.projectKey=jenkins-SonarCube -Dsonar.projectName=jenkins-SonarCube -Dsonar.sources=.\"\n};harness-others:-WATCHING_RECURRENCE_PERIOD-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep WATCHING_RECURRENCE_PERIOD-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.WATCHING_RECURRENCE_PERIOD-long-USE_WATCHING-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep USE_WATCHING-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.USE_WATCHING-boolean-REMOTE_TIMEOUT-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep REMOTE_TIMEOUT-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.REMOTE_TIMEOUT-long;jenkins.pipeline.step.id:19;jenkins.pipeline.step.name:Shell Script;jenkins.pipeline.step.plugin.name:workflow-durable-task-step;jenkins.pipeline.step.plugin.version:1336.v768003e07199;jenkins.pipeline.step.type:sh;)",
"name": "sonarcube #9",
"attributesMap": {
"harness-others": "-WATCHING_RECURRENCE_PERIOD-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep WATCHING_RECURRENCE_PERIOD-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.WATCHING_RECURRENCE_PERIOD-long-USE_WATCHING-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep USE_WATCHING-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.USE_WATCHING-boolean-REMOTE_TIMEOUT-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep REMOTE_TIMEOUT-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.REMOTE_TIMEOUT-long",
"jenkins.pipeline.step.name": "Shell Script",
"ci.pipeline.run.user": "SYSTEM",
"jenkins.pipeline.step.id": "19",
"jenkins.pipeline.step.type": "sh",
"harness-attribute": "{\n \"script\" : \"/Users/rakshitagarwal/.jenkins/tools/hudson.plugins.sonar.SonarRunnerInstallation/sonar_cube/bin/sonar-scanner -Dsonar.projectKey=jenkins-SonarCube -Dsonar.projectName=jenkins-SonarCube -Dsonar.sources=.\"\n}",
"jenkins.pipeline.step.plugin.name": "workflow-durable-task-step",
"jenkins.pipeline.step.plugin.version": "1336.v768003e07199"
},
"type": "Run Phase Span",
"parentSpanId": "c9943fda45b8312f",
"parameterMap": {"script": "/Users/rakshitagarwal/.jenkins/tools/hudson.plugins.sonar.SonarRunnerInstallation/sonar_cube/bin/sonar-scanner -Dsonar.projectKey=jenkins-SonarCube -Dsonar.projectName=jenkins-SonarCube -Dsonar.sources=."},
"spanName": "sh"
}
],
"name": "sonarcube #9",
"attributesMap": {
"harness-others": "",
"jenkins.pipeline.step.type": "wrap"
},
"type": "Run Phase Span",
"parentSpanId": "32035723074a4821",
"spanName": "Stage: null"
}
"type": "Run Phase Span",
"parentSpanId": "32035723074a4821",
"spanName": "Stage: null"
}
33 changes: 33 additions & 0 deletions convert/jenkinsjson/json/sonarQualityGate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package json

import (
harness "github.com/drone/spec/dist/go"
)

// ConvertSonarQualityGate creates a Harness step for nunit plugin.
func ConvertSonarQualityGate(node Node) *harness.Step {

convertSonarQualityGate := &harness.Step{
Name: "Sonarqube_Quality_Gate",
Type: "plugin",
Id: SanitizeForId(node.SpanName, node.SpanId),
Spec: &harness.StepPlugin{
Image: "plugins/sonarqube-scanner:latest",
With: map[string]interface{}{
"sonar_key": "<+input>",
"sonar_name": "<+input>",
"sonar_host": "<+input>",
"sonar_token": "<+input>",
"timeout": "300",
"sources": ".",
"skip_scan": "false",
"sonar_qualitygate": "OK",
"sonar_quality_enabled": "true",
"sonar_organization": "<+input>",
"scm_disabled": "false",
},
},
}

return convertSonarQualityGate
}
44 changes: 44 additions & 0 deletions convert/jenkinsjson/json/sonarQualityGate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package json

import (
"testing"

harness "github.com/drone/spec/dist/go"
"github.com/google/go-cmp/cmp"
)

func TestConvertSonarQualityGate(t *testing.T) {

var tests []runner
tests = append(tests, prepare(t, "/sonarQualityGate/sonarQualityGate_snippet", &harness.Step{
Id: "waitForQualityGate6278c9",
Name: "Sonarqube_Quality_Gate",
Type: "plugin",
Spec: &harness.StepPlugin{
Image: "plugins/sonarqube-scanner:latest",
With: map[string]interface{}{
"sonar_key": "<+input>",
"sonar_name": "<+input>",
"sonar_host": "<+input>",
"sonar_token": "<+input>",
"timeout": "300",
"sources": ".",
"skip_scan": "false",
"sonar_qualitygate": "OK",
"sonar_quality_enabled": "true",
"sonar_organization": "<+input>",
"scm_disabled": "false",
},
},
}))

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ConvertSonarQualityGate(tt.input)

if diff := cmp.Diff(got, tt.want); diff != "" {
t.Errorf("ConvertSonarQualityGate() mismatch (-want +got):\n%s", diff)
}
})
}
}
30 changes: 18 additions & 12 deletions samples/jenkins/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ line3'''
steps {
javadoc javadocDir: 'complete/build/docs/javadoc', keepAll: true
}
}
}
//Kube-ctl
stage('Check Docker') {
steps {
Expand Down Expand Up @@ -815,22 +815,28 @@ line3'''
//Nodejs conversion Step
stage('Install Packages') {
steps {
// Set up the NodeJS environment
nodejs(nodeJSInstallationName: 'node') {
sh '''
# Ensure npm uses the public registry
echo "registry=https://registry.npmjs.org/" > .npmrc
npm install
'''
withSonarQubeEnv('SonarCloud') { // Matches the name in Jenkins configuration
sh "${SONAR_SCANNER} -Dsonar.projectKey=vanisrikanithi_Test-Sonarqube" +
'-Dsonar.organization=vanisrikanithi' +
'-Dsonar.login=b751ddb91e11f466d7cdfa0abd65b4a6c393d938 ' +
'-Dsonar.sources=src ' +
'-Dsonar.java.binaries=target/classes'
}
}
}

stage('Run Tests') {
stage('Quality Gate') {
steps {
nodejs(nodeJSInstallationName: 'node') {
// Run npm test to execute the "test" script in package.json
sh 'npm test'
script {
def qualityGate = waitForQualityGate()
// If the quality gate fails, log the status but don't abort the pipeline
if (qualityGate.status != 'OK' && qualityGate.status != 'NONE') {
echo "Quality Gate failed with status: ${qualityGate.status}. Continuing the pipeline."
} else if (qualityGate.status == 'NONE') {
echo 'Quality Gate status is NONE. Check SonarQube configuration.'
} else {
echo "Quality Gate passed with status: ${qualityGate.status}."
}
}
}
}
Expand Down