Creating Jenkins CI/CD Pipeline (Code sample)

Sharing common code which may help you to build CI/CD for your repository in Git . It consists of multiple stages in which it performs operations to – clean, build and deploy your project build to server or any drop location .

Below Jenkins Pipeline is written in groovy language and its build code targets to .Net Core 3.1 version.

//--Global Variable declaration 
def projectVersion
gitBranch = ' You Git Branch' ---Your Branch name
commit_id = ' '
gitUrl = 'https://github.com/W3TechSchool/MyProject121.git'
gitCredentialsId = 'git-W3TechSchool-com'
serviceName = ' '
//----------------------------------------------------------
//---Below is starting part of pipeline---------------------
pipeline {
	agent any
	options {
	      timestamps()
	}

//----Setting up environment for Sonar----------------------
//---That plugin must be set in your jenkins server and on 
//---other part there must be sonarQube set up in somewhere .
//--Sonar help you to publish your code smell and code 
//--coverage to server in HTML format  
	 environment {
SONAR_HOME = tool name: 'SonarMSCore', type: 'hudson.plugins.sonar.MsBuildSQRunnerInstallation'
               }
//----------------------------------------------------------
//---You can define your parameters if you want to run build //in jenkins sever using below parameters
parameters 
{ 
string(name: 'FROM_BRANCH', defaultValue: '', description: 'Manual build against specific branch (blank for default):')

string(name: 'FROM_TAG', defaultValue: '', description: 'Manual build against specific tag (blank for default):')

string(name: 'SERVICE_NAME', description: 'ServiceName (W3TS_API,W3TS_APINxt)(blank for default):')
		string(name:'SonarQubeProjectKey',defaultValue:'', description:'Add the Project Key of sonarqube project (blank for default):')
}
//----------------------------------------------------------
//--Below are stages where we perform multiple set of //operations to generate quantifiable code for deploy 
stages {
stage ('Checkout code') {
 steps {
	script {
		gitBranch = get_sourceBranch()
	       }

echo "Checking out: ${gitBranch}"
checkout([$class: 'GitSCM',
branches: [[name: gitBranch]],					doGenerateSubmoduleConfigurations: false,
userRemoteConfigs: [[						credentialsId: gitCredentialsId,						url: gitUrl
]]
])

script {
	commit_id = get_commit_id()					notify_Bitbucket('INPROGRESS', commit_id, 'Starting the build...')
	}
}		
}// End of stage ('Checkout code')

stage ('Get Version'){
 steps {
     script {
	projectVersion = get_version()
            }            
       }
} // End of stage ('Get Version')

//In Build stage we are using two utilities that must need to // be exists in Jenkins sever 1.dotnet core 3.1 runtime //(https://dotnet.microsoft.com/download/dotnet-core/3.1)
//2. utility for file compression 		
stage ('Build') {
    steps {                
	script {
	    serviceName = env.SERVICE_NAME
	      }
        script {
         bat """
         cd src/${serviceName}
         dotnet publish -c Release 
         cd bin/Release/netcoreapp3.1/publish
         "D:/Utils/7-Zip/7z.exe" a W3TechTeam_Microservices_${serviceName}.zip "*.*" -r
	"""
         }
      }
  }//End of stage ('Build')

// Code to build unit test projects 
 stage('Test: Unit Test'){
  steps {
        unit_test()
        }
}

//Below code is for code smell and code coverage report //generation and publish it on sonarqube sever 
stage ('Static Code Analysis') {
steps {                                                    static_code_analysis()                                              }
}
//--Publishing Artifacts and deploying using Octopus 	
stage('publishArtifacts') {
 steps {
   script {
     bat """
cd src/${serviceName}/bin/Release/netcoreapp3.1/publish
rename W3TechTeam_Microservices_${serviceName}.zip W3TechTeam-Microservices-${serviceName}-${projectVersion}.zip
                """
}
archiveArtifacts artifacts: "src/${serviceName}/bin/Release/netcoreapp3.1/publish/W3TechTeam-Microservices-${serviceName}-${projectVersion}.zip", onlyIfSuccessful: true
 uploadToOctopus() // using Octopus for deployment
          }
      }
    }
    
post {
always {
	echo 'Build Finished'
step([$class: 'MSTestPublisher', testResultsFile:"**/TestResults/UnitTests.trx", failOnError: true, keepLongStdio: true])
 //Setting up the environment variable (for sonarqube project //key) to be passed into the email template 
script{
    env.projectKeyValue = "${params.SonarQubeProjectKey}"
}
}
success {
 script {
	 echo 'Build was successful'
				notify_Bitbucket('SUCCESSFUL', commit_id, 'Build was successful')
				notify_recipients(true)
	}
}
fixed {
   echo 'Build is now stable'
   notify_recipients(true)
  }
changed {
   echo 'Build status changed'
	}
aborted {
	echo 'Build was manually aborted'
	}
failure {
script {
	echo "Build Failed"
notify_Bitbucket('FAILURE', commit_id, 'Build failed')
		notify_recipients(false)
	}
}
regression {
echo 'Build was successful before but is now failing'
	}
unstable {
 echo 'Build is Unstable'
  }
unsuccessful {
	 echo 'Build was something other than success'
	  }
cleanup {
	echo 'Cleaning up the workspace'
	cleanWs()
	}
}
}

//--Version file exists in project 
def get_version(){
	  projectVersion = readFile file: "src/version"
	  projectVersion = projectVersion.trim() + ".${BUILD_NUMBER}"
	  echo "Project version ${projectVersion}"	
	  return projectVersion
    }
 //--Getting source branch/tag   
def get_sourceBranch() {
	if (params.FROM_BRANCH != '') {
		return "*/${params.FROM_BRANCH}"
	}

	if (params.FROM_TAG != '') {
		return "refs/tags/${params.FROM_TAG}"
	}

	echo "env.GIT_BRANCH: ${env.GIT_BRANCH}"
	echo "env.GIT_LOCAL_BRANCH: ${env.GIT_LOCAL_BRANCH}"

	// detect branch from environment
	def branch = env.GIT_BRANCH

	// fall-back to master
	if (branch == null) {
		branch = 'master'
	}
	branch = branch.replace('origin/', '')
	echo "branch: ${branch}"

	return "*/${branch}"
}

def tag_commit() {
	echo "attempt to tag commit \"${semVer}\""

	def tagName = "v${semVer}"
	if (!is_webhook()) {
		echo "Skip tagging on manual builds"
		return
	}

	sshagent([gitCredentialsId]) 
	{
		bat label: 'Generate tag', script: "git tag -a ${tagName} -m \"${tagName}\""
		bat label: 'Push tag', script: "git push origin ${tagName}"
	}
}

def is_webhook() {
// this is checking via the Git Push/Pull Request        //Trigger plugin
	return env.BITBUCKET_SOURCE_BRANCH;
}

def isPullRequest() {
	return env.BITBUCKET_TARGET_BRANCH;
}

def get_commit_id() {
	def gitCommit = bat(returnStdout: true, script: '@echo off & git rev-parse HEAD').trim()
	echo "gitCommit: ${gitCommit}"
	return gitCommit
}

def notify_Bitbucket(buildState, commitId, message) {
	if (!is_webhook()) {
		return
	}
	
	bitbucketStatusNotify(
		buildState: buildState,
		buildKey: 'build',
		buildName: 'Build',
		repoSlug: 'W3TechSchoolTechTeam',
		commitId: "${commitId}",
		buildDescription: message)
}

def notify_recipients(isSuccess = true, additionalInfo = "") {
	// see triggers: //https://wiki.jenkins.io/display/JENKINS/Email-    //ext+plugin#Email-extplugin-Triggers
	
	def recipientProviders = [ requestor() ];
	def directRecipients = ""
	if (isSuccess) {
		directRecipients = "[email protected]"
	}
	else {
		recipientProviders.add(culprits())
		recipientProviders.add(developers())
		directRecipients = "[email protected]"
	}

	def status = isSuccess ? 'SUCCESS' : 'FAILURE'

    emailext (
            to: directRecipients,
            recipientProviders: recipientProviders,
subject: "${status}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'",
body: """<p>${status}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]':</p>
<p>Check console output at <a href='${env.BUILD_URL}'>${env.JOB_NAME} [${env.BUILD_NUMBER}]</a></p>
                <p>${additionalInfo}</p>""",
        )
}

def uploadToOctopus() {
  bat "octo push --server ${octopusServer} --package src/${serviceName}/bin/Release/netcoreapp3.1/publish/W3TechTeam-Microservices-${serviceName}-${projectVersion}.zip --apiKey ${octopusKey}"
}

def static_code_analysis() {
        def sonar_url = "https://sonarqube.r1rcm.com"
        def sonar_login = "asdfasdfasdfasdf23423"

        echo "SONAR_HOME: ${env.SONAR_HOME}"

        def code = bat label: '', returnStatus: true, script: "dotnet ${SONAR_HOME}\\SonarScanner.MSBuild.dll begin /k:R1_PAS_Services_Jenkins /n:W3TechTeamServices /d:sonar.host.url=\"${sonar_url}\" /d:sonar.login=\"${sonar_login}\" /d:sonar.cs.dotcover.reportsPaths=\"coverage-report.html\""
        if (code != 0) {
               error('Failed to begin static code analysis')
        }

        code = bat label: '', returnStatus: true, script: 'dotnet build --no-incremental src/W3TechTeamServices.sln'
        if (code != 0) {
               error('Failed to rebuild for static code analysis')
        }

        code = bat label: '', returnStatus: true, script: 'dotcover cover src/dot-cover.xml --TargetExecutable=\"C:\\Program Files\\dotnet\\dotnet.exe\"'
        // code = bat label: '', returnStatus: true, script: 'dotcover dotnet dot-cover.xml'
        if (code != 0) {
               error('Failed to run dotcover')
        }

        code = bat label: '', returnStatus: true, script: "dotnet ${SONAR_HOME}\\SonarScanner.MSBuild.dll end /d:sonar.login=\"${sonar_login}\""
        if (code != 0) {
               error('Failed to end static code analysis run')
        }
}
def unit_test(){
	def code = bat label: '', returnStatus: true, script: 'dotnet test src/PAS-Services.sln --logger \"trx;LogFileName=UnitTests.trx\"'
	echo "Windows batch scripts exit code: ${code}"
	if (code != 0) {
		error('Unit Test Report Generation Failed')
	}			
}

I hope it would be helpful for you to create CI/CD pipleline.

Happy Learning!

Leave a Reply