diff --git a/jobs-dsl/jobs/DevSecOps/svace_analyze_project.groovy b/jobs-dsl/jobs/DevSecOps/svace_analyze_project.groovy new file mode 100644 index 0000000..110002d --- /dev/null +++ b/jobs-dsl/jobs/DevSecOps/svace_analyze_project.groovy @@ -0,0 +1,54 @@ +pipelineJob('DevSecOps/svace_analyze_project') { + parameters { + booleanParam { + description("Check if SonarQube scan is requred (project should have sonar-project.properties file)") + name('RUN_SONARQUBE_SCAN') + defaultValue(false) + } + string { + description('Git project (organization/project)') + name('GIT_PROJECT') + defaultValue('') + } + string { + description('Git project branch') + name('BRANCH') + defaultValue('') + } + string { + description('Git project commmit') + name('COMMIT_SHA') + defaultValue('') + } + string { + description('Git project main branch') + name('MAIN_BRANCH') + defaultValue('master') + } + choice { + description('Main language for analysis') + name('LANGUAGE') + choices('python\njavascript\n') + } + string { + description('Name, version and arch of build. Example: aurora5_armv7hl') + name('BUILD_PATFORM') + defaultValue('') + } + } + + definition { + cpsScm { + scm { + git { + remote { + url("${JENKINS_GIT_REPOSITORY_URL}/DevOps/jenkins-pipelines.git") + credentials("${JENKINS_GIT_CREDENTIALS_HTTP}") + } + branch('master') + } + } + scriptPath('pipelines/DevSecOps/svace-analyze-project.groovy') + } + } +} diff --git a/pipelines/DevSecOps/svace-analyze-project.groovy b/pipelines/DevSecOps/svace-analyze-project.groovy new file mode 100644 index 0000000..1f97042 --- /dev/null +++ b/pipelines/DevSecOps/svace-analyze-project.groovy @@ -0,0 +1,202 @@ +/** + * Copyright (c) AVROID, Ltd., 2024 + * + * You can not use the contents of the file in any way without + * AVROID, Ltd. written permission. + * + * To obtain such a permit, you should contact AVROID, Ltd. + * at https://avroid.ru + */ + +@Library('shared-lib') _ + +import tech.avroid.api.Nexus +import tech.avroid.jenkins.Jenkins +import tech.avroid.scm.Git + +// +// Git variables +// +Git git = new Git(this, env.JENKINS_GIT_CREDENTIALS_SSH) +String commitSha = '' + +// +// Nexus variables +// +Nexus nexus = new Nexus(this, env.JENKINS_NEXUS_URL, env.JENKINS_NEXUS_CREDENTIALS) + +//build stage +String buildType = 'Release' +String buildThreads = '1' + +// +//Svace variables +// +String svaceResultsLink = '' +String svaceCmd = "/opt/svace-${env.JENKINS_SVACE_VERSION}-x64-linux/bin/svace" + +Boolean runSonarQubeScan = false + +List listPipelineTriggers = [] + +List listProperties = [ + buildDiscarder(logRotator(artifactDaysToKeepStr: '30', + artifactNumToKeepStr: '10', + daysToKeepStr: '30', + numToKeepStr: '10')), + parameters([ + booleanParam(name: 'RUN_SONARQUBE_SCAN', defaultValue: runSonarQubeScan), + string(name: 'GIT_PROJECT', defaultValue: ''), + string(name: 'BRANCH', defaultValue: ''), + string(name: 'COMMIT_SHA', defaultValue: ''), + string(name: 'MAIN_BRANCH', defaultValue: 'master'), + choice(name: 'LANGUAGE', defaultValue: '', choices: "python\njavascript"), + string(name: 'BUILD_PLATFORM', + defaultValue: '', + description: 'name, version and arch of build. Example: aurora5_armv7hl') + ]), + pipelineTriggers(listPipelineTriggers) +] + +if (env.BRANCH_NAME != 'master') { + listProperties.push(disableConcurrentBuilds(abortPrevious: true)) +} + +properties (listProperties) + + runSonarQubeScan = params.RUN_SONARQUBE_SCAN + + +podTemplate(yaml: getPodTemplate('avroliteLinux')) { + node(POD_LABEL) { + stage('Env') { + println "Using agent ${env.NODE_NAME} (${env.JENKINS_URL})" + println "param RUN_SONARQUBE_SCAN ${params.RUN_SONARQUBE_SCAN}" + println "param GIT_PROJECT ${params.GIT_PROJECT}" + println "param BRANCH ${params.BRANCH}" + println "param COMMIT_SHA ${params.COMMIT_SHA}" + println "param MAIN_BRANCH ${params.MAIN_BRANCH}" + println "param BUILD_PLATFORM ${params.BUILD_PLATFORM}" + println "WORKSPACE: ${env.WORKSPACE}" + sh 'printenv' + + currentBuild.description = "${params.GIT_PROJECT}
${params.BRANCH}" + if (params.COMMIT_SHA) { + currentBuild.description += " (${params.COMMIT_SHA})" + } + } + + stage('Download sources') { + Boolean isDisableSubmodules = (params.GIT_PROJECT == 'Eisen/OS') ? true : false + + git.clone([ + urlRepo: "${env.JENKINS_GIT_REPOSITORY_SSH_URL}/${params.GIT_PROJECT}", + branch: params.BRANCH, + path: "${env.WORKSPACE}/${params.GIT_PROJECT}", + disableSubmodules: isDisableSubmodules, + shallow: false + ]) + + dir("${env.WORKSPACE}/${params.GIT_PROJECT}") { + commitSha = (params.COMMIT_SHA) ? params.COMMIT_SHA : git.log([count:1, format: "%h"]) + git.checkout(commitSha) + } + } + + container(name: 'linux') { + stage('Build') { + sh """ + set -eux + mkdir '${JENKINS_SVACE_BUILD_DIR}' + ${svaceCmd} init ${JENKINS_SVACE_BUILD_DIR} + ${svaceCmd} build --svace-dir ${JENKINS_SVACE_BUILD_DIR} --${params.LANGUAGE} "${env.WORKSPACE}/${params.GIT_PROJECT}" + """ + } + + stage('upload artifacts') { + String nexusRepoPath = "${params.GIT_PROJECT}/${params.BRANCH}/${commitSha}" + sh """ + set -e + tar -cf ${env.JENKINS_SVACE_BUILD_RESULTS} ${JENKINS_SVACE_BUILD_DIR} + """ + println("Uploading svace result: ${env.JENKINS_SVACE_BUILD_RESULTS}") + nexus.upload([artifactPath: "${env.JENKINS_SVACE_BUILD_RESULTS}", + repository: env.JENKINS_SVACE_NEXUS_REPO, + path: nexusRepoPath]) + + svaceResultsLink = "${env.JENKINS_NEXUS_URL}/" + \ + "repository/" + \ + "${env.JENKINS_SVACE_NEXUS_REPO}/" + \ + "${nexusRepoPath}" + } + } + } +} + +stage('Svace analyze') { + build job: 'DevSecOps/svace_analyze', + parameters: [ + string(name: 'GIT_PROJECT', value: params.GIT_PROJECT), + string(name: 'BRANCH', value: params.BRANCH), + string(name: 'COMMIT_SHA', value: commitSha), + string(name: 'SVACE_BUILD_RESULTS_LINK', value: "${svaceResultsLink}/${env.JENKINS_SVACE_BUILD_RESULTS}"), + string(name: 'MAIN_BRANCH', value: params.MAIN_BRANCH) + ], + wait: true +} + +if (runSonarQubeScan) { + podTemplate(yaml: getPodTemplate('sonarCubeScanner')) { + node(POD_LABEL) { + stage('Download sources and artifacts') { + Boolean isDisableSubmodules = (params.GIT_PROJECT == 'Eisen/OS') ? true : false + git.clone([ + urlRepo: "${env.JENKINS_GIT_REPOSITORY_SSH_URL}/${params.GIT_PROJECT}", + branch: params.BRANCH, + path: "${env.WORKSPACE}/${params.GIT_PROJECT}", + disableSubmodules: isDisableSubmodules, + shallow: false + ]) + + dir("${env.WORKSPACE}/${params.GIT_PROJECT}") { + commitSha = (params.COMMIT_SHA) ? params.COMMIT_SHA : git.log([count:1, format: "%h"]) + git.checkout(commitSha) + } + nexus.download("${svaceResultsLink}/${env.JENKINS_SVACE_SARIF_FILE}") + } + + container(name: 'sonar-scanner') { + stage('SonarQube: Scan') { + withSonarQubeEnv('sonarqube.avroid.tech') { + dir("${env.WORKSPACE}/${params.GIT_PROJECT}") { + if (env.CHANGE_ID) { + sh """sonar-scanner \ + -X \ + -Dsonar.pullrequest.key="PR-${env.CHANGE_ID}" \ + -Dsonar.pullrequest.branch="${env.CHANGE_BRANCH}" \ + -Dsonar.pullrequest.base="${env.CHANGE_TARGET}" \ + -Dsonar.sarifReportPaths="${env.JENKINS_SVACE_SARIF_FILE}" + """ + } else { + sh """sonar-scanner \ + -X \ + -Dsonar.branch.name="${env.BRANCH_NAME}" \ + -Dsonar.sarifReportPaths="${env.JENKINS_SVACE_SARIF_FILE}" + """ + } + } + } + } + } + + stage("SonarQube: Quality Gate"){ + timeout(time: 1, unit: 'HOURS') { + def qg = waitForQualityGate() + if (qg.status != 'OK') { + unstable("Pipeline aborted due to quality gate failure: ${qg.status}") + } + } + } + } + } +}