diff --git a/convert/jenkinsjson/convert.go b/convert/jenkinsjson/convert.go index 7d785f0d..ffade3fe 100644 --- a/convert/jenkinsjson/convert.go +++ b/convert/jenkinsjson/convert.go @@ -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, "", " ") diff --git a/convert/jenkinsjson/convertTestFiles/sonarQualityGate/Jenkinsfile b/convert/jenkinsjson/convertTestFiles/sonarQualityGate/Jenkinsfile new file mode 100644 index 00000000..f252c6fc --- /dev/null +++ b/convert/jenkinsjson/convertTestFiles/sonarQualityGate/Jenkinsfile @@ -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}." + } + } + } + } + + } +} diff --git a/convert/jenkinsjson/convertTestFiles/sonarQualityGate/sonarQualityGate_snippet.json b/convert/jenkinsjson/convertTestFiles/sonarQualityGate/sonarQualityGate_snippet.json new file mode 100644 index 00000000..cc9a31e4 --- /dev/null +++ b/convert/jenkinsjson/convertTestFiles/sonarQualityGate/sonarQualityGate_snippet.json @@ -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" +} \ No newline at end of file diff --git a/convert/jenkinsjson/convertTestFiles/sonarQualityGate/sonarQuanlityGate.yaml b/convert/jenkinsjson/convertTestFiles/sonarQualityGate/sonarQuanlityGate.yaml new file mode 100644 index 00000000..1c260991 --- /dev/null +++ b/convert/jenkinsjson/convertTestFiles/sonarQualityGate/sonarQuanlityGate.yaml @@ -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 \ No newline at end of file diff --git a/convert/jenkinsjson/convertTestFiles/sonarqube/sonarqubeSnippet.json b/convert/jenkinsjson/convertTestFiles/sonarqube/sonarqubeSnippet.json index 08ffb99a..680e889c 100644 --- a/convert/jenkinsjson/convertTestFiles/sonarqube/sonarqubeSnippet.json +++ b/convert/jenkinsjson/convertTestFiles/sonarqube/sonarqubeSnippet.json @@ -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" -} \ No newline at end of file + "type": "Run Phase Span", + "parentSpanId": "32035723074a4821", + "spanName": "Stage: null" + } \ No newline at end of file diff --git a/convert/jenkinsjson/json/sonarQualityGate.go b/convert/jenkinsjson/json/sonarQualityGate.go new file mode 100644 index 00000000..b3565bad --- /dev/null +++ b/convert/jenkinsjson/json/sonarQualityGate.go @@ -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 +} diff --git a/convert/jenkinsjson/json/sonarQualityGate_test.go b/convert/jenkinsjson/json/sonarQualityGate_test.go new file mode 100644 index 00000000..20d7a9f1 --- /dev/null +++ b/convert/jenkinsjson/json/sonarQualityGate_test.go @@ -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) + } + }) + } +} diff --git a/samples/jenkins/Jenkinsfile b/samples/jenkins/Jenkinsfile index 4e7a1050..c2b80d61 100644 --- a/samples/jenkins/Jenkinsfile +++ b/samples/jenkins/Jenkinsfile @@ -606,7 +606,7 @@ line3''' steps { javadoc javadocDir: 'complete/build/docs/javadoc', keepAll: true } - } + } //Kube-ctl stage('Check Docker') { steps { @@ -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}." + } } } }