From c80d1ff6f13d3cc64d40cabfee10d06caba2c874 Mon Sep 17 00:00:00 2001 From: Greg Turnquist Date: Sat, 8 Jun 2019 07:43:47 -0500 Subject: [PATCH] Introduce Jenkins. --- Jenkinsfile | 186 ++++++++++++++++++ .../examples/EmployeeControllerTests.java | 26 +-- ci/build.sh | 11 +- ci/build.yml | 20 -- ci/promote-to-bintray.sh | 20 +- ci/promote-to-bintray.yml | 19 -- ci/sync-to-maven-central.sh | 31 ++- ci/sync-to-maven-central.yml | 21 -- ci/test.sh | 8 +- ci/test.yml | 17 -- pom.xml | 123 ++++++++++++ 11 files changed, 348 insertions(+), 134 deletions(-) create mode 100644 Jenkinsfile delete mode 100644 ci/build.yml delete mode 100644 ci/promote-to-bintray.yml delete mode 100644 ci/sync-to-maven-central.yml delete mode 100644 ci/test.yml diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..ffc5f5e --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,186 @@ +pipeline { + agent none + + triggers { + pollSCM 'H/10 * * * *' + } + + options { + disableConcurrentBuilds() + } + + stages { + stage("test: baseline (jdk8)") { + agent { + docker { + image 'adoptopenjdk/openjdk8:latest' + args '-v $HOME/.m2:/root/.m2' + } + } + steps { + sh "PROFILE=none ci/test.sh" + } + } + + stage("Test other configurations") { + parallel { + stage("test: baseline (jdk11)") { + agent { + docker { + image 'adoptopenjdk/openjdk11:latest' + args '-v $HOME/.m2:/root/.m2' + } + } + steps { + sh "PROFILE=none ci/test.sh" + } + } + stage("test: baseline (jdk12)") { + agent { + docker { + image 'adoptopenjdk/openjdk12:latest' + args '-v $HOME/.m2:/root/.m2' + } + } + steps { + sh "PROFILE=none ci/test.sh" + } + } + } + } + + stage('Deploy to Artifactory') { + agent { + docker { + image 'springci/spring-hateoas-openjdk8-with-graphviz-and-jq:latest' + args '-v $HOME/.m2:/root/.m2' + } + } + + environment { + ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c') + } + + steps { + script { + // Warm up this plugin quietly before using it. + sh "./mvnw -q org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version" + + PROJECT_VERSION = sh( + script: "./mvnw org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version -o | grep -v INFO", + returnStdout: true + ).trim() + + RELEASE_TYPE = 'milestone' // .RC? or .M? + + if (PROJECT_VERSION.endsWith('BUILD-SNAPSHOT')) { + RELEASE_TYPE = 'snapshot' + } else if (PROJECT_VERSION.endsWith('RELEASE')) { + RELEASE_TYPE = 'release' + } + + OUTPUT = sh( + script: "PROFILE=ci,${RELEASE_TYPE} ci/build.sh", + returnStdout: true + ).trim() + + echo "$OUTPUT" + + build_info_path = OUTPUT.split('\n') + .find { it.contains('Artifactory Build Info Recorder') } + .split('Saving Build Info to ')[1] + .trim()[1..-2] + + dir(build_info_path + '/..') { + stash name: 'build_info', includes: "*.json" + } + } + } + } + stage('Promote to Bintray') { + when { + branch 'release' + } + agent { + docker { + image 'springci/spring-hateoas-openjdk8-with-graphviz-and-jq:latest' + args '-v $HOME/.m2:/root/.m2' + } + } + + environment { + ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c') + } + + steps { + script { + // Warm up this plugin quietly before using it. + sh "./mvnw -q org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version" + + PROJECT_VERSION = sh( + script: "./mvnw org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version -o | grep -v INFO", + returnStdout: true + ).trim() + + if (PROJECT_VERSION.endsWith('RELEASE')) { + unstash name: 'build_info' + sh "ci/promote-to-bintray.sh" + } else { + echo "${PROJECT_VERSION} is not a candidate for promotion to Bintray." + } + } + } + } + stage('Sync to Maven Central') { + when { + branch 'release' + } + agent { + docker { + image 'springci/spring-hateoas-openjdk8-with-graphviz-and-jq:latest' + args '-v $HOME/.m2:/root/.m2' + } + } + + environment { + BINTRAY = credentials('Bintray-spring-operator') + SONATYPE = credentials('oss-token') + } + + steps { + script { + // Warm up this plugin quietly before using it. + sh "./mvnw -q org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version" + + PROJECT_VERSION = sh( + script: "./mvnw org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version -o | grep -v INFO", + returnStdout: true + ).trim() + + if (PROJECT_VERSION.endsWith('RELEASE')) { + unstash name: 'build_info' + sh "ci/sync-to-maven-central.sh" + } else { + echo "${PROJECT_VERSION} is not a candidate for syncing to Maven Central." + } + } + } + } + } + + post { + changed { + script { + slackSend( + color: (currentBuild.currentResult == 'SUCCESS') ? 'good' : 'danger', + channel: '#spring-hateoas', + message: "${currentBuild.fullDisplayName} - `${currentBuild.currentResult}`\n${env.BUILD_URL}") + emailext( + subject: "[${currentBuild.fullDisplayName}] ${currentBuild.currentResult}", + mimeType: 'text/html', + recipientProviders: [[$class: 'CulpritsRecipientProvider'], [$class: 'RequesterRecipientProvider']], + body: "${currentBuild.fullDisplayName} is reported as ${currentBuild.currentResult}") + } + } + } +} diff --git a/affordances/src/test/java/org/springframework/hateoas/examples/EmployeeControllerTests.java b/affordances/src/test/java/org/springframework/hateoas/examples/EmployeeControllerTests.java index a205c13..87f781e 100644 --- a/affordances/src/test/java/org/springframework/hateoas/examples/EmployeeControllerTests.java +++ b/affordances/src/test/java/org/springframework/hateoas/examples/EmployeeControllerTests.java @@ -15,16 +15,6 @@ */ package org.springframework.hateoas.examples; -import static org.hamcrest.CoreMatchers.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - -import java.util.Arrays; -import java.util.Optional; - import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -36,6 +26,18 @@ import org.springframework.http.HttpHeaders; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; +import java.util.Arrays; +import java.util.Optional; + +import static org.hamcrest.CoreMatchers.is; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + /** * @author Greg Turnquist */ @@ -58,7 +60,7 @@ public class EmployeeControllerTests { mvc.perform(get("/employees").accept(MediaTypes.HAL_FORMS_JSON_VALUE)) // .andDo(print()) // .andExpect(status().isOk()) // - .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaTypes.HAL_FORMS_JSON_VALUE + ";charset=UTF-8")) + .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaTypes.HAL_FORMS_JSON_VALUE)) .andExpect(jsonPath("$._embedded.employees[0].id", is(1))) .andExpect(jsonPath("$._embedded.employees[0].firstName", is("Frodo"))) @@ -113,7 +115,7 @@ public class EmployeeControllerTests { mvc.perform(get("/employees/1").accept(MediaTypes.HAL_FORMS_JSON_VALUE)) // .andDo(print()) // .andExpect(status().isOk()) // - .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaTypes.HAL_FORMS_JSON_VALUE + ";charset=UTF-8")) + .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaTypes.HAL_FORMS_JSON_VALUE)) .andExpect(jsonPath("$.id", is(1))) // .andExpect(jsonPath("$.firstName", is("Frodo"))) // diff --git a/ci/build.sh b/ci/build.sh index e530c8c..6a202bb 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -2,13 +2,4 @@ set -euo pipefail -[[ -d $PWD/maven && ! -d $HOME/.m2 ]] && ln -s $PWD/maven $HOME/.m2 - -spring_hateoas_examples_artifactory=$(pwd)/spring-hateoas-examples-artifactory - -rm -rf $HOME/.m2/repository/org/springframework/hateoas 2> /dev/null || : - -cd spring-hateoas-examples-github - -./mvnw -Pdistribute -Dmaven.test.skip=true clean deploy \ - -DaltDeploymentRepository=distribution::default::file://${spring_hateoas_examples_artifactory} +./mvnw -P${PROFILE} -Dmaven.test.skip=true clean deploy -B diff --git a/ci/build.yml b/ci/build.yml deleted file mode 100644 index 396d02d..0000000 --- a/ci/build.yml +++ /dev/null @@ -1,20 +0,0 @@ ---- -platform: linux - -image_resource: - type: docker-image - source: - repository: openjdk - tag: 8-jdk - -inputs: -- name: spring-hateoas-examples-github - -outputs: -- name: spring-hateoas-examples-artifactory - -caches: -- path: maven - -run: - path: spring-hateoas-examples-github/ci/build.sh diff --git a/ci/promote-to-bintray.sh b/ci/promote-to-bintray.sh index 2d72b6e..a00bb8d 100755 --- a/ci/promote-to-bintray.sh +++ b/ci/promote-to-bintray.sh @@ -2,24 +2,20 @@ set -e -u -apt-get update -apt-get install -y jq +buildName=`jq -r '.name' build-info.json` +buildNumber=`jq -r '.number' build-info.json` +groupId=`jq -r '.modules[0].id' build-info.json | sed 's/\(.*\):.*:.*/\1/'` +version=`jq -r '.modules[0].id' build-info.json | sed 's/.*:.*:\(.*\)/\1/'` -buildName=$( cat spring-hateoas-examples-artifactory/build-info.json | jq -r '.buildInfo.name' ) -buildNumber=$( cat spring-hateoas-examples-artifactory/build-info.json | jq -r '.buildInfo.number' ) -groupId=$( cat spring-hateoas-examples-artifactory/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/\(.*\):.*:.*/\1/' ) -version=$( cat spring-hateoas-examples-artifactory/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' ) -targetRepo="libs-release-local" - -echo "Promoting ${buildName}/${buildNumber} to ${targetRepo}" +echo "Promoting ${buildName}/${buildNumber}/${groupId}/${version} to libs-release-local" curl \ -s \ --connect-timeout 240 \ --max-time 2700 \ - -u ${ARTIFACTORY_USERNAME}:${ARTIFACTORY_PASSWORD} \ - -H "Content-type:application/json" \ - -d "{\"sourceRepos\": [\"libs-release-local\"], \"targetRepo\" : \"spring-distributions\", \"async\":\"true\"}" \ + -u ${ARTIFACTORY_USR}:${ARTIFACTORY_PSW} \ + -H 'Content-type:application/json' \ + -d '{"sourceRepos": ["libs-release-local"], "targetRepo" : "spring-distributions", "async":"true"}' \ -f \ -X \ POST "https://repo.spring.io/api/build/distribute/${buildName}/${buildNumber}" > /dev/null || { echo "Failed to distribute" >&2; exit 1; } diff --git a/ci/promote-to-bintray.yml b/ci/promote-to-bintray.yml deleted file mode 100644 index 09208c8..0000000 --- a/ci/promote-to-bintray.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -platform: linux - -image_resource: - type: docker-image - source: - repository: openjdk - tag: 8-jdk - -inputs: -- name: spring-hateoas-examples-artifactory -- name: spring-hateoas-examples-github - -run: - path: spring-hateoas-examples-github/ci/promote-to-bintray.sh - -params: - ARTIFACTORY_USERNAME: - ARTIFACTORY_PASSWORD: diff --git a/ci/sync-to-maven-central.sh b/ci/sync-to-maven-central.sh index f2b97cb..7150ca7 100755 --- a/ci/sync-to-maven-central.sh +++ b/ci/sync-to-maven-central.sh @@ -2,23 +2,22 @@ set -e -u -apt-get update -apt-get install -y jq +buildName=`jq -r '.name' build-info.json` +buildNumber=`jq -r '.number' build-info.json` +groupId=`jq -r '.modules[0].id' build-info.json | sed 's/\(.*\):.*:.*/\1/'` +version=`jq -r '.modules[0].id' build-info.json | sed 's/.*:.*:\(.*\)/\1/'` -buildName=$( cat spring-hateoas-examples-artifactory/build-info.json | jq -r '.buildInfo.name' ) -buildNumber=$( cat spring-hateoas-examples-artifactory/build-info.json | jq -r '.buildInfo.number' ) -groupId=$( cat spring-hateoas-examples-artifactory/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/\(.*\):.*:.*/\1/' ) -version=$( cat spring-hateoas-examples-artifactory/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' ) +echo "Syncing ${buildName}/${buildNumber}/${groupId}/${version} to Maven Central..." -echo "Syncing ${buildName}/${buildNumber} to Maven Central" - curl \ - -s \ - --connect-timeout 240 \ - --max-time 2700 \ - -u ${BINTRAY_USERNAME}:${BINTRAY_API_KEY} \ - -H "Content-Type: application/json" -d "{ \"username\": \"${SONATYPE_USER_TOKEN}\", \"password\": \"${SONATYPE_PASSWORD_TOKEN}\"}" \ - -f \ - -X \ - POST "https://api.bintray.com/maven_central_sync/spring/jars/${groupId}/versions/${version}" > /dev/null || { echo "Failed to sync" >&2; exit 1; } +curl \ + -s \ + --connect-timeout 240 \ + --max-time 2700 \ + -u ${BINTRAY_USR}:${BINTRAY_PSW} \ + -H 'Content-Type: application/json' \ + -d "{ \"username\": \"${SONATYPE_USR}\", \"password\": \"${SONATYPE_PSW}\"}" \ + -f \ + -X \ + POST "https://api.bintray.com/maven_central_sync/spring/jars/${groupId}/versions/${version}" > /dev/null || { echo "Failed to sync" >&2; exit 1; } echo "Sync complete" diff --git a/ci/sync-to-maven-central.yml b/ci/sync-to-maven-central.yml deleted file mode 100644 index cbec386..0000000 --- a/ci/sync-to-maven-central.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -platform: linux - -image_resource: - type: docker-image - source: - repository: openjdk - tag: 8-jdk - -inputs: -- name: spring-hateoas-examples-artifactory -- name: spring-hateoas-examples-github - -run: - path: spring-hateoas-examples-github/ci/sync-to-maven-central.sh - -params: - BINTRAY_USERNAME: - BINTRAY_API_KEY: - SONATYPE_USER_TOKEN: - SONATYPE_PASSWORD_TOKEN: diff --git a/ci/test.sh b/ci/test.sh index bf76ae2..f6bb0bf 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -2,10 +2,4 @@ set -euo pipefail -[[ -d $PWD/maven && ! -d $HOME/.m2 ]] && ln -s $PWD/maven $HOME/.m2 - -rm -rf $HOME/.m2/repository/org/springframework/hateoas 2> /dev/null || : - -cd spring-hateoas-examples-github - -./mvnw clean dependency:list test -P${PROFILE} -Dsort +./mvnw -P${PROFILE} clean dependency:list test -Dsort -B diff --git a/ci/test.yml b/ci/test.yml deleted file mode 100644 index d35fec0..0000000 --- a/ci/test.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -platform: linux - -image_resource: - type: docker-image - source: - repository: openjdk - tag: 8-jdk - -inputs: -- name: spring-hateoas-examples-github - -caches: -- path: maven - -run: - path: spring-hateoas-examples-github/ci/test.sh diff --git a/pom.xml b/pom.xml index 23bff7a..0687396 100644 --- a/pom.xml +++ b/pom.xml @@ -91,6 +91,129 @@ + + snapshot + + + + + org.jfrog.buildinfo + artifactory-maven-plugin + 2.6.1 + false + + + build-info + + publish + + + + {{BUILD_URL}} + + + spring-hateoas + spring-hateoas + false + *:*:*:*@zip + + + https://repo.spring.io + {{ARTIFACTORY_USR}} + {{ARTIFACTORY_PSW}} + libs-snapshot-local + libs-snapshot-local + + + + + + + + + + + milestone + + + + + org.jfrog.buildinfo + artifactory-maven-plugin + 2.6.1 + false + + + build-info + + publish + + + + {{BUILD_URL}} + + + spring-hateoas + spring-hateoas + false + *:*:*:*@zip + + + https://repo.spring.io + {{ARTIFACTORY_USR}} + {{ARTIFACTORY_PSW}} + libs-milestone-local + libs-milestone-local + + + + + + + + + + + release + + + + + org.jfrog.buildinfo + artifactory-maven-plugin + 2.6.1 + false + + + build-info + + publish + + + + {{BUILD_URL}} + + + spring-hateoas + spring-hateoas + false + *:*:*:*@zip + + + https://repo.spring.io + {{ARTIFACTORY_USR}} + {{ARTIFACTORY_PSW}} + libs-release-local + libs-release-local + + + + + + + + +