Skip to content

Instantly share code, notes, and snippets.

@asim-mirza786
Forked from jonico/Jenkinsfile
Created September 16, 2022 17:46
Show Gist options
  • Save asim-mirza786/a9dba69063a92a44627dca3f1973a413 to your computer and use it in GitHub Desktop.
Save asim-mirza786/a9dba69063a92a44627dca3f1973a413 to your computer and use it in GitHub Desktop.
Example for a full blown Jenkins pipeline script with CodeQL analysis steps, multiple stages, Kubernetes templates, shared volumes, input steps, injected credentials, heroku deploy, sonarqube and artifactory integration, Docker containers, multiple Git commit statuses, PR merge vs branch build detection, REST API calls to GitHub deployment API, …
#!groovy
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
node {
// pull request or feature branch
if (env.BRANCH_NAME != 'master') {
checkout()
build()
unitTest()
// test whether this is a regular branch build or a merged PR build
if (!isPRMergeBuild()) {
// maybe disabled for ChatOps
// preview()
}
} // master branch / production
else {
checkout()
build()
allTests()
preProduction()
manualPromotion()
production()
}
}
def isPRMergeBuild() {
return (env.BRANCH_NAME ==~ /^PR-\d+$/)
}
def checkout () {
stage 'Checkout code'
context="continuous-integration/jenkins/"
context += isPRMergeBuild()?"branch/checkout":"pr-merge/checkout"
setBuildStatus ("${context}", 'Checking out...', 'PENDING')
checkout scm
setBuildStatus ("${context}", 'Checking out completed', 'SUCCESS')
}
def build () {
stage 'Build'
// cache maven artifacts
shareM2 '/tmp/m2repo'
mvn 'clean install -DskipTests=true -Dmaven.javadoc.skip=true -Dcheckstyle.skip=true -B -V'
}
def unitTest() {
stage 'Unit tests'
mvn 'test -B -Dmaven.javadoc.skip=true -Dcheckstyle.skip=true'
step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*.xml'])
if (currentBuild.result == "UNSTABLE") {
sh "exit 1"
}
}
def allTests() {
stage 'All tests'
// don't skip anything
mvn 'test -B'
step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*.xml'])
if (currentBuild.result == "UNSTABLE") {
// input "Unit tests are failing, proceed?"
sh "exit 1"
}
}
def preview() {
herokuApp = "${env.HEROKU_PREVIEW}"
deployToStage("preview", herokuApp)
}
def preProduction() {
herokuApp = "${env.HEROKU_PREPRODUCTION}"
deployToStage("preproduction", herokuApp)
}
def manualPromotion() {
stage 'Manual Promotion'
// we need a first milestone step so that all jobs entering this stage are tracked an can be aborted if needed
milestone 1
// time out manual approval after ten minutes
timeout(time: 10, unit: 'MINUTES') {
input message: "Does Pre-Production look good?"
}
// this will kill any job which is still in the input step
milestone 2
}
def production() {
herokuApp = "${env.HEROKU_PRODUCTION}"
deployToStage("production", herokuApp)
step([$class: 'ArtifactArchiver', artifacts: '**/target/*.jar', fingerprint: true])
}
def deployToStage(stageName, herokuApp) {
stage name: "Deploy to ${stageName}", concurrency: 1
id = createDeployment(getBranch(), "${stageName}", "Deploying branch to ${stageName}")
echo "Deployment ID for ${stageName}: ${id}"
if (id != null) {
setDeploymentStatus(id, "pending", "https://${herokuApp}.herokuapp.com/", "Pending deployment to ${stageName}");
herokuDeploy "${herokuApp}"
setDeploymentStatus(id, "success", "https://${herokuApp}.herokuapp.com/", "Successfully deployed to ${stageName}");
}
}
def herokuDeploy (herokuApp) {
withCredentials([[$class: 'StringBinding', credentialsId: 'HEROKU_API_KEY', variable: 'HEROKU_API_KEY']]) {
mvn "heroku:deploy -DskipTests=true -Dmaven.javadoc.skip=true -B -V -D heroku.appName=${herokuApp}"
}
}
def mvn(args) {
// point to settings.xml with cached .m2 directory and proceed in case of test failures
sh "${tool 'Maven 3.x'}/bin/mvn -s settings.xml ${args} -Dmaven.test.failure.ignore"
}
def shareM2(file) {
// Set up a shared Maven repo so we don't need to download all dependencies on every build.
writeFile file: 'settings.xml',
text: "<settings><localRepository>${file}</localRepository></settings>"
}
def getRepoSlug() {
tokens = "${env.JOB_NAME}".tokenize('/')
org = tokens[tokens.size()-3]
repo = tokens[tokens.size()-2]
return "${org}/${repo}"
}
def getBranch() {
tokens = "${env.JOB_NAME}".tokenize('/')
branch = tokens[tokens.size()-1]
return "${branch}"
}
def createDeployment(ref, environment, description) {
withCredentials([[$class: 'StringBinding', credentialsId: 'GITHUB_TOKEN', variable: 'GITHUB_TOKEN']]) {
def payload = JsonOutput.toJson(["ref": "${ref}", "description": "${description}", "environment": "${environment}", "required_contexts": []])
def apiUrl = "https://octodemo.com/api/v3/repos/${getRepoSlug()}/deployments"
def response = sh(returnStdout: true, script: "curl -s -H \"Authorization: Token ${env.GITHUB_TOKEN}\" -H \"Accept: application/json\" -H \"Content-type: application/json\" -X POST -d '${payload}' ${apiUrl}").trim()
def jsonSlurper = new JsonSlurper()
def data = jsonSlurper.parseText("${response}")
return data.id
}
}
void setDeploymentStatus(deploymentId, state, targetUrl, description) {
withCredentials([[$class: 'StringBinding', credentialsId: 'GITHUB_TOKEN', variable: 'GITHUB_TOKEN']]) {
def payload = JsonOutput.toJson(["state": "${state}", "target_url": "${targetUrl}", "description": "${description}"])
def apiUrl = "https://octodemo.com/api/v3/repos/${getRepoSlug()}/deployments/${deploymentId}/statuses"
def response = sh(returnStdout: true, script: "curl -s -H \"Authorization: Token ${env.GITHUB_TOKEN}\" -H \"Accept: application/json\" -H \"Content-type: application/json\" -X POST -d '${payload}' ${apiUrl}").trim()
}
}
void setBuildStatus(context, message, state) {
// partially hard coded URL because of https://issues.jenkins-ci.org/browse/JENKINS-36961, adjust to your own GitHub instance
step([
$class: "GitHubCommitStatusSetter",
contextSource: [$class: "ManuallyEnteredCommitContextSource", context: context],
errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]],
reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/${getRepoSlug()}"],
statusResultSource: [ $class: "ConditionalStatusResultSource", results: [[$class: "AnyBuildResult", message: message, state: state]] ]
]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment