-
-
Save asim-mirza786/a9dba69063a92a44627dca3f1973a413 to your computer and use it in GitHub Desktop.
Revisions
-
jonico revised this gist
Mar 25, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -67,7 +67,7 @@ spec: }) def installCodeQL() { sh 'cd /tmp && test -f /tmp/codeql-runner-linux || curl -O -L https://github.com/github/codeql-action/releases/latest/download/codeql-runner-linux' sh 'chmod a+x /tmp/codeql-runner-linux' } -
jonico revised this gist
Mar 25, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -75,7 +75,7 @@ def initCodeQL() { stage 'Init CodeQL' installCodeQL() withCredentials([string(credentialsId: 'GITHUB_TOKEN', variable: 'ghe_token')]) { sh "/tmp/codeql-runner-linux init --repository ${getRepoSlug()} --github-url https://octodemo.com --github-auth \$ghe_token --languages java,javascript --config-file .github/codeq-config.yml" } } -
jonico revised this gist
Mar 25, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -75,7 +75,7 @@ def initCodeQL() { stage 'Init CodeQL' installCodeQL() withCredentials([string(credentialsId: 'GITHUB_TOKEN', variable: 'ghe_token')]) { sh "/tmp/codeql-runner-linux init --repository ${getRepoSlug()} --github-url https://octodemo.com --github-auth \$ghe_token --languages java,javascript --config-file: .github/codeq-config.yml" } } -
jonico revised this gist
Mar 24, 2021 . 1 changed file with 63 additions and 15 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -7,7 +7,7 @@ podTemplate(label: label, yaml: """ spec: containers: - name: mvn image: maven:3.3.9-jdk-8 command: - cat tty: true @@ -20,7 +20,7 @@ spec: # directory location on host path: /tmp type: Directory """, { node (label) { container ('mvn') { @@ -31,23 +31,32 @@ spec: buildInfo = Artifactory.newBuildInfo() buildInfo.env.capture = true (ref, commit) = checkout() // pull request or feature branch if (env.BRANCH_NAME != 'master' && env.BRANCH_NAME != 'main') { // test whether this is a regular branch build or a merged PR build if (!isPRMergeBuild()) { // branch build codeQl = false build() unitTest() preview() } else { // PR-build codeQl = true initCodeQL() build() analyzeAndUploadCodeQLResults(ref, commit) unitTest() // sonar() } } else { // master/main branch / production codeQl = true initCodeQL() build() analyzeAndUploadCodeQLResults(ref, commit) allTests() preProduction() manualPromotion() @@ -57,24 +66,59 @@ spec: } }) def installCodeQL() { sh 'cd /tmp && test -f /tmp/codeql-runner-linux || curl -O -L https://github.com/github/codeql-action/releases/download/codeql-bundle-20201106/codeql-runner-linux' sh 'chmod a+x /tmp/codeql-runner-linux' } def initCodeQL() { stage 'Init CodeQL' installCodeQL() withCredentials([string(credentialsId: 'GITHUB_TOKEN', variable: 'ghe_token')]) { sh "/tmp/codeql-runner-linux init --repository ${getRepoSlug()} --github-url https://octodemo.com --github-auth \$ghe_token --languages java,javascript" } } def analyzeAndUploadCodeQLResults(ref, commit) { stage 'Analyze & Upload CodeQL results' withCredentials([string(credentialsId: 'GITHUB_TOKEN', variable: 'ghe_token')]) { sh "/tmp/codeql-runner-linux analyze --repository ${getRepoSlug()} --github-url https://octodemo.com --github-auth \$ghe_token --ref ${ref} --commit ${commit}" } } def isPRMergeBuild() { return (env.BRANCH_NAME ==~ /^PR-\d+$/) } def getPRNumber() { def matcher = (env.BRANCH_NAME =~ /^PR-(?<PR>\d+)$/) assert matcher.matches() return matcher.group("PR") } // in order for CodeQL to publish its results for PRs, the special ref refs/pull<PR>/merge has to get retrieved while checking out // this can be done by telling Jenkins to add the following ref spec: +refs/pull/*/merge:refs/remotes/@{remote}/refs/pull/*/merge def checkout () { stage 'Checkout code' context="continuous-integration/jenkins/" context += isPRMergeBuild()?"pr-merge/checkout":"branch/checkout" def scmVars = checkout scm setBuildStatus ("${context}", 'Checking out completed', 'SUCCESS') if (isPRMergeBuild()) { prMergeRef = "refs/pull/${getPRNumber()}/merge" mergeCommit=sh(returnStdout: true, script: "git show-ref ${prMergeRef} | cut -f 1 -d' '") echo "Merge commit: ${mergeCommit}" return [prMergeRef, mergeCommit] } else { return ["refs/heads/${env.BRANCH_NAME}", scmVars.GIT_COMMIT] } } def build () { stage 'Build' 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' @@ -199,8 +243,8 @@ def switchSnapshotBuildToRelease() { def buildAndPublishToArtifactory() { def rtMaven = Artifactory.newMavenBuild() // rtMaven.tool = null withEnv(["MAVEN_HOME=/usr/share/maven", "JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk/jre"]) { rtMaven.deployer releaseRepo:'libs-release-local', snapshotRepo:'libs-snapshot-local', server: server rtMaven.resolver releaseRepo:'libs-release', snapshotRepo:'libs-snapshot', server: server rtMaven.run pom: 'pom.xml', goals: 'install', buildInfo: buildInfo @@ -255,7 +299,11 @@ def mvn(args) { ) { // Run the maven build if (codeQl) { sh ". codeql-runner/codeql-env.sh && mvn $args -Dmaven.test.failure.ignore -Dmaven.repo.local=/cache" } else { sh "mvn $args -Dmaven.test.failure.ignore -Dmaven.repo.local=/cache" } } } -
jonico revised this gist
Apr 8, 2019 . No changes.There are no files selected for viewing
-
jonico revised this gist
Apr 8, 2019 . 1 changed file with 141 additions and 176 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,97 +2,65 @@ import groovy.json.JsonOutput import groovy.json.JsonSlurper def label = "mypod-${UUID.randomUUID().toString()}" podTemplate(label: label, yaml: """ spec: containers: - name: mvn image: maven:3.3.9-jdk-8-alpine command: - cat tty: true volumeMounts: - mountPath: /cache name: maven-cache volumes: - name: maven-cache hostPath: # directory location on host path: /tmp type: Directory """, { node (label) { container ('mvn') { // env.JAVA_HOME="${tool 'Java SE DK 8u131'}" // env.PATH="${env.JAVA_HOME}/bin:${env.PATH}" server = Artifactory.server "artifactory" buildInfo = Artifactory.newBuildInfo() buildInfo.env.capture = true // 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() } else { // PR-build sonar() } } // 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/" @@ -110,11 +78,41 @@ def build () { def unitTest() { stage 'Unit tests' mvn 'test -B -Dmaven.javadoc.skip=true -Dcheckstyle.skip=true' if (currentBuild.result == "UNSTABLE") { sh "exit 1" } } def sonar() { stage('SonarQube analysis') { prNo = (env.BRANCH_NAME=~/^PR-(\d+)$/)[0][1] echo "PR-No: ${prNo}" // requires SonarQube Scanner 2.8+ mvn 'org.jacoco:jacoco-maven-plugin:prepare-agent install -Dmaven.test.failure.ignore=true -Pcoverage-per-test' withCredentials([[$class: 'StringBinding', credentialsId: 'GITHUB_TOKEN', variable: 'GITHUB_TOKEN']]) { githubToken=env.GITHUB_TOKEN withSonarQubeEnv('SonarQube Octodemoapps') { mvn "-Dsonar.analysis.mode=preview -Dsonar.github.pullRequest=${prNo} -Dsonar.github.oauth=${githubToken} -Dsonar.github.repository=Hyrule/reading-time-app -Dsonar.github.endpoint=https://octodemo.com/api/v3/ org.sonarsource.scanner.maven:sonar-maven-plugin:3.2:sonar" mvn "org.sonarsource.scanner.maven:sonar-maven-plugin:3.2:sonar" } } context="sonarqube/qualitygate" setBuildStatus ("${context}", 'Checking Sonarqube quality gate', 'PENDING') sleep 5 timeout(time: 1, unit: 'MINUTES') { // Just in case something goes wrong, pipeline will be killed after a timeout def qg = waitForQualityGate() // Reuse taskId previously collected by withSonarQubeEnv if (qg.status != 'OK') { setBuildStatus ("${context}", "Sonarqube quality gate fail: ${qg.status}", 'FAILURE') error "Pipeline aborted due to quality gate failure: ${qg.status}" } else { setBuildStatus ("${context}", "Sonarqube quality gate pass: ${qg.status}", 'SUCCESS') } } } } def allTests() { stage 'All tests' // don't skip anything @@ -126,65 +124,21 @@ def allTests() { } } def preview() { herokuApp = "${env.HEROKU_PREVIEW}" deployToStage("preview", herokuApp) // mvn 'deploy -DskipTests=true' } def preProduction() { switchSnapshotBuildToRelease() herokuApp = "${env.HEROKU_PREPRODUCTION}" deployToStage("preproduction", herokuApp) buildAndPublishToArtifactory() } 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 @@ -196,14 +150,44 @@ def manualPromotion() { } def production() { herokuApp = "${env.HEROKU_PRODUCTION}" step([$class: 'ArtifactArchiver', artifacts: '**/target/*.jar', fingerprint: true]) deployToStage("production", herokuApp) def version = getCurrentHerokuReleaseVersion("${env.HEROKU_PRODUCTION}") def createdAt = getCurrentHerokuReleaseDate("${env.HEROKU_PRODUCTION}", version) echo "Release version: ${version}" createRelease(version, createdAt) stage ("Promote in Artifactory") { promoteBuildInArtifactory() // distributeBuildToBinTray() } } void createRelease(tagName, createdAt) { withCredentials([[$class: 'StringBinding', credentialsId: 'GITHUB_TOKEN', variable: 'GITHUB_TOKEN']]) { def body = "**Created at:** ${createdAt}\n**Deployment job:** [${env.BUILD_NUMBER}](${env.BUILD_URL})\n**Environment:** [${env.HEROKU_PRODUCTION}](https://dashboard.heroku.com/apps/${env.HEROKU_PRODUCTION})" def payload = JsonOutput.toJson(["tag_name": "v${tagName}", "name": "${env.HEROKU_PRODUCTION} - v${tagName}", "body": "${body}"]) def apiUrl = "https://octodemo.com/api/v3/repos/${getRepoSlug()}/releases" 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 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 switchSnapshotBuildToRelease() { @@ -215,11 +199,13 @@ def switchSnapshotBuildToRelease() { def buildAndPublishToArtifactory() { def rtMaven = Artifactory.newMavenBuild() rtMaven.tool = null withEnv(["MAVEN_HOME=/usr/share/maven"]) { rtMaven.deployer releaseRepo:'libs-release-local', snapshotRepo:'libs-snapshot-local', server: server rtMaven.resolver releaseRepo:'libs-release', snapshotRepo:'libs-snapshot', server: server rtMaven.run pom: 'pom.xml', goals: 'install', buildInfo: buildInfo server.publishBuildInfo buildInfo } } def promoteBuildInArtifactory() { @@ -261,33 +247,22 @@ def distributeBuildToBinTray() { server.distribute distributionConfig } def mvn(args) { withMaven( // mavenSettingsConfig: '0e94d6c3-b431-434f-a201-7d7cda7180cb' //mavenLocalRepo: '/tmp/m2' ) { // Run the maven build sh "mvn $args -Dmaven.test.failure.ignore -Dmaven.repo.local=/cache" } } 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() { @@ -306,38 +281,28 @@ def getBranch() { 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) { step([ $class: "GitHubCommitStatusSetter", contextSource: [$class: "ManuallyEnteredCommitContextSource", context: context], errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]], reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://octodemo.com/${getRepoSlug()}"], statusResultSource: [ $class: "ConditionalStatusResultSource", results: [[$class: "AnyBuildResult", message: message, state: state]] ] ]); } -
jonico revised this gist
Oct 12, 2017 . 1 changed file with 236 additions and 39 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,22 +2,49 @@ import groovy.json.JsonOutput import groovy.json.JsonSlurper /* Please make sure to add the following environment variables: HEROKU_PREVIEW=<your heroku preview app> HEROKU_PREPRODUCTION=<your heroku pre-production app> HEROKU_PRODUCTION=<your heroku production app> Please also add the following credentials to the global domain of your organization's folder: Heroku API key as secret text with ID 'HEROKU_API_KEY' GitHub Token value as secret text with ID 'GITHUB_TOKEN' */ node { server = Artifactory.server "artifactory" buildInfo = Artifactory.newBuildInfo() buildInfo.env.capture = true // we need to set a newer JVM for Sonar env.JAVA_HOME="${tool 'Java SE DK 8u131'}" env.PATH="${env.JAVA_HOME}/bin:${env.PATH}" // 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()) { preview() sonarServer() allCodeQualityTests() } else { // Pull request sonarPreview() } } // master branch / production else { checkout() build() allTests() preview() sonarServer() allCodeQualityTests() preProduction() manualPromotion() production() @@ -28,28 +55,61 @@ def isPRMergeBuild() { return (env.BRANCH_NAME ==~ /^PR-\d+$/) } def sonarPreview() { stage('SonarQube Preview') { prNo = (env.BRANCH_NAME=~/^PR-(\d+)$/)[0][1] mvn "org.jacoco:jacoco-maven-plugin:prepare-agent install -Dmaven.test.failure.ignore=true -Pcoverage-per-test" withCredentials([[$class: 'StringBinding', credentialsId: 'GITHUB_TOKEN', variable: 'GITHUB_TOKEN']]) { githubToken=env.GITHUB_TOKEN repoSlug=getRepoSlug() withSonarQubeEnv('SonarQube Octodemoapps') { mvn "-Dsonar.analysis.mode=preview -Dsonar.github.pullRequest=${prNo} -Dsonar.github.oauth=${githubToken} -Dsonar.github.repository=${repoSlug} -Dsonar.github.endpoint=https://api.github.com/ org.sonarsource.scanner.maven:sonar-maven-plugin:3.2:sonar" } } } } def sonarServer() { stage('SonarQube Server') { mvn "org.jacoco:jacoco-maven-plugin:prepare-agent install -Dmaven.test.failure.ignore=true -Pcoverage-per-test" withSonarQubeEnv('SonarQube Octodemoapps') { mvn "org.sonarsource.scanner.maven:sonar-maven-plugin:3.2:sonar" } context="sonarqube/qualitygate" setBuildStatus ("${context}", 'Checking Sonarqube quality gate', 'PENDING') timeout(time: 1, unit: 'MINUTES') { // Just in case something goes wrong, pipeline will be killed after a timeout def qg = waitForQualityGate() // Reuse taskId previously collected by withSonarQubeEnv if (qg.status != 'OK') { setBuildStatus ("${context}", "Sonarqube quality gate fail: ${qg.status}", 'FAILURE') error "Pipeline aborted due to quality gate failure: ${qg.status}" } else { setBuildStatus ("${context}", "Sonarqube quality gate pass: ${qg.status}", 'SUCCESS') } } } } def checkout () { stage 'Checkout code' context="continuous-integration/jenkins/" context += isPRMergeBuild()?"pr-merge/checkout":"branch/checkout" checkout scm setBuildStatus ("${context}", 'Checking out completed', 'SUCCESS') } def build () { stage 'Build' 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' if (currentBuild.result == "UNSTABLE") { sh "exit 1" } @@ -66,18 +126,65 @@ def allTests() { } } def allCodeQualityTests() { stage 'Code Quality' lintTest() coverageTest() } def lintTest() { context="continuous-integration/jenkins/linting" setBuildStatus ("${context}", 'Checking code conventions', 'PENDING') lintTestPass = true try { mvn 'verify -DskipTests=true' } catch (err) { setBuildStatus ("${context}", 'Some code conventions are broken', 'FAILURE') lintTestPass = false } finally { if (lintTestPass) setBuildStatus ("${context}", 'Code conventions OK', 'SUCCESS') } } def coverageTest() { context="continuous-integration/jenkins/coverage" setBuildStatus ("${context}", 'Checking code coverage levels', 'PENDING') coverageTestStatus = true try { mvn 'cobertura:check' } catch (err) { setBuildStatus("${context}", 'Code coverage below 90%', 'FAILURE') throw err } setBuildStatus ("${context}", 'Code coverage above 90%', 'SUCCESS') } def preview() { stage name: 'Deploy to Preview env', concurrency: 1 def herokuApp = "${env.HEROKU_PREVIEW}" def id = createDeployment(getBranch(), "preview", "Deploying branch to test") echo "Deployment ID: ${id}" if (id != null) { setDeploymentStatus(id, "pending", "https://${herokuApp}.herokuapp.com/", "Pending deployment to test"); herokuDeploy "${herokuApp}" setDeploymentStatus(id, "success", "https://${herokuApp}.herokuapp.com/", "Successfully deployed to test"); } mvn 'deploy -DskipTests=true' } def preProduction() { stage name: 'Deploy to Pre-Production', concurrency: 1 switchSnapshotBuildToRelease() herokuDeploy "${env.HEROKU_PREPRODUCTION}" buildAndPublishToArtifactory() } def manualPromotion() { // 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 @@ -89,37 +196,98 @@ def manualPromotion() { } def production() { stage name: 'Deploy to Production', concurrency: 1 step([$class: 'ArtifactArchiver', artifacts: '**/target/*.jar', fingerprint: true]) herokuDeploy "${env.HEROKU_PRODUCTION}" def version = getCurrentHerokuReleaseVersion("${env.HEROKU_PRODUCTION}") def createdAt = getCurrentHerokuReleaseDate("${env.HEROKU_PRODUCTION}", version) echo "Release version: ${version}" createRelease(version, createdAt) promoteInArtifactoryAndDistributeToBinTray() } def switchSnapshotBuildToRelease() { def descriptor = Artifactory.mavenDescriptor() descriptor.version = '1.0.0' descriptor.pomFile = 'pom.xml' descriptor.transform() } def buildAndPublishToArtifactory() { def rtMaven = Artifactory.newMavenBuild() rtMaven.tool = "Maven 3.x" rtMaven.deployer releaseRepo:'libs-release-local', snapshotRepo:'libs-snapshot-local', server: server rtMaven.resolver releaseRepo:'libs-release', snapshotRepo:'libs-snapshot', server: server rtMaven.run pom: 'pom.xml', goals: 'install', buildInfo: buildInfo server.publishBuildInfo buildInfo } def promoteBuildInArtifactory() { def promotionConfig = [ // Mandatory parameters 'buildName' : buildInfo.name, 'buildNumber' : buildInfo.number, 'targetRepo' : 'libs-prod-local', // Optional parameters 'comment' : 'deploying to production', 'sourceRepo' : 'libs-release-local', 'status' : 'Released', 'includeDependencies': false, 'copy' : true, // 'failFast' is true by default. // Set it to false, if you don't want the promotion to abort upon receiving the first error. 'failFast' : true ] // Promote build server.promote promotionConfig } def distributeBuildToBinTray() { def distributionConfig = [ // Mandatory parameters 'buildName' : buildInfo.name, 'buildNumber' : buildInfo.number, 'targetRepo' : 'reading-time-dist', // Optional parameters //'publish' : true, // Default: true. If true, artifacts are published when deployed to Bintray. 'overrideExistingFiles' : true, // Default: false. If true, Artifactory overwrites builds already existing in the target path in Bintray. //'gpgPassphrase' : 'passphrase', // If specified, Artifactory will GPG sign the build deployed to Bintray and apply the specified passphrase. //'async' : false, // Default: false. If true, the build will be distributed asynchronously. Errors and warnings may be viewed in the Artifactory log. //"sourceRepos" : ["yum-local"], // An array of local repositories from which build artifacts should be collected. //'dryRun' : false, // Default: false. If true, distribution is only simulated. No files are actually moved. ] server.distribute distributionConfig } def promoteInArtifactoryAndDistributeToBinTray() { stage ("Promote in Artifactory and Distribute to BinTray") { promoteBuildInArtifactory() distributeBuildToBinTray() } } def mvn(args) { withMaven( // Maven installation declared in the Jenkins "Global Tool Configuration" maven: 'Maven 3.x', // Maven settings.xml file defined with the Jenkins Config File Provider Plugin // settings.xml referencing the GitHub Artifactory repositories mavenSettingsConfig: '0e94d6c3-b431-434f-a201-7d7cda7180cb', // we do not need to set a special local maven repo, take the one from the standard box //mavenLocalRepo: '.repository' ) { // Run the maven build sh "mvn $args -Dmaven.test.failure.ignore" } } 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 getRepoSlug() { @@ -138,29 +306,58 @@ def getBranch() { 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://api.github.com/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 createRelease(tagName, createdAt) { withCredentials([[$class: 'StringBinding', credentialsId: 'GITHUB_TOKEN', variable: 'GITHUB_TOKEN']]) { def body = "**Created at:** ${createdAt}\n**Deployment job:** [${env.BUILD_NUMBER}](${env.BUILD_URL})\n**Environment:** [${env.HEROKU_PRODUCTION}](https://dashboard.heroku.com/apps/${env.HEROKU_PRODUCTION})" def payload = JsonOutput.toJson(["tag_name": "v${tagName}", "name": "${env.HEROKU_PRODUCTION} - v${tagName}", "body": "${body}"]) def apiUrl = "https://api.github.com/repos/${getRepoSlug()}/releases" 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 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://api.github.com/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], reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://octodemo.com/${getRepoSlug()}"], errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]], statusResultSource: [ $class: "ConditionalStatusResultSource", results: [[$class: "AnyBuildResult", message: message, state: state]] ] ]); } def getCurrentHerokuReleaseVersion(app) { withCredentials([[$class: 'StringBinding', credentialsId: 'HEROKU_API_KEY', variable: 'HEROKU_API_KEY']]) { def apiUrl = "https://api.heroku.com/apps/${app}/dynos" def response = sh(returnStdout: true, script: "curl -s -H \"Authorization: Bearer ${env.HEROKU_API_KEY}\" -H \"Accept: application/vnd.heroku+json; version=3\" -X GET ${apiUrl}").trim() def jsonSlurper = new JsonSlurper() def data = jsonSlurper.parseText("${response}") return data[0].release.version } } def getCurrentHerokuReleaseDate(app, version) { withCredentials([[$class: 'StringBinding', credentialsId: 'HEROKU_API_KEY', variable: 'HEROKU_API_KEY']]) { def apiUrl = "https://api.heroku.com/apps/${app}/releases/${version}" def response = sh(returnStdout: true, script: "curl -s -H \"Authorization: Bearer ${env.HEROKU_API_KEY}\" -H \"Accept: application/vnd.heroku+json; version=3\" -X GET ${apiUrl}").trim() def jsonSlurper = new JsonSlurper() def data = jsonSlurper.parseText("${response}") return data.created_at } } -
jonico revised this gist
Jun 6, 2017 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -32,7 +32,8 @@ def checkout () { stage 'Checkout code' context="continuous-integration/jenkins/" context += isPRMergeBuild()?"branch/checkout":"pr-merge/checkout" // newer versions of Jenkins do not seem to support setting custom statuses before running the checkout scm step ... // setBuildStatus ("${context}", 'Checking out...', 'PENDING') checkout scm setBuildStatus ("${context}", 'Checking out completed', 'SUCCESS') } -
jonico revised this gist
Jan 27, 2017 . 1 changed file with 3 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -154,10 +154,12 @@ void setDeploymentStatus(deploymentId, state, targetUrl, description) { } 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]] ] ]); } -
jonico revised this gist
Jan 25, 2017 . No changes.There are no files selected for viewing
-
jonico revised this gist
Jan 25, 2017 . No changes.There are no files selected for viewing
-
jonico created this gist
Jan 25, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,163 @@ #!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) { step([ $class: "GitHubCommitStatusSetter", contextSource: [$class: "ManuallyEnteredCommitContextSource", context: context], errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]], statusResultSource: [ $class: "ConditionalStatusResultSource", results: [[$class: "AnyBuildResult", message: message, state: state]] ] ]); }