Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Continuous Delivery As Code

1,184 views

Published on

Continuous Delivery enables building, testing and deploying of software through build pipelines faster and more frequently with a well known steps.
But how to implement a continuous delivery pipeline in real world? How to translate the theory into practice?

In this session we are going to discuss how Jenkins and Gradle can help you on build this pipeline/workflow and the advantages of implementing this pipeline as code instead of using Jenkins static build steps.

We will start by a really simple Java EE application and learn how to build it with Gradle, automating unit, integration and functional tests, incorporating popular code quality tools, as well as packaging, publishing and deploying the deliverable using Jenkins Workflow as the director of the whole process.

Published in: Technology
  • Be the first to comment

Continuous Delivery As Code

  1. 1. with Jenkins and Gradle  alexsotob C O N T I N U O U S D E L I V E R Y A S C O D E
  2. 2. A L E X S O T O C L O U D B E E S E N G I N E E R O P E N S O U R C E A D V O C A T E @ A L E X S O T O B  alexsotob  lordofthejars
  3. 3. Q U E S T I O N S  alexsotob  lordofthejars
  4. 4. S O F T W A R E I S E A T I N G T H E W O R L D  alexsotob  lordofthejars
  5. 5.  alexsotob  lordofthejars
  6. 6.  alexsotob  lordofthejars
  7. 7.  alexsotob  lordofthejars
  8. 8.  alexsotob  lordofthejars
  9. 9. Faster  alexsotob  lordofthejars
  10. 10. Faster Sooner  alexsotob  lordofthejars
  11. 11. Faster Sooner Better  alexsotob  lordofthejars
  12. 12. W H A T I S C O N T I N U O U S D E L I V E R Y?  alexsotob  lordofthejars
  13. 13. D E L I V E R B U S I N E S S V A L U E M O R E F R E Q U E N T L Y  alexsotob  lordofthejars
  14. 14.  alexsotob  lordofthejars
  15. 15. N O M O R E T H E O R Y P L E A S E ! !  alexsotob  lordofthejars
  16. 16. C O M M I T S T A G E  alexsotob  lordofthejars
  17. 17. apply pluginapply plugin:: 'war''war' B U I L D . G R A D L E  alexsotob  lordofthejars
  18. 18. apply pluginapply plugin:: 'war''war' allprojects allprojects {{ sourceCompatibility sourceCompatibility == 1.81.8 targetCompatibility targetCompatibility == 1.81.8 group group == 'org.starwars''org.starwars' version version == '1.0-SNAPSHOT''1.0-SNAPSHOT' repositories repositories {{ mavenCentralmavenCentral(()) }} }} B U I L D . G R A D L E  alexsotob  lordofthejars
  19. 19. apply pluginapply plugin:: 'war''war' allprojects allprojects {{ sourceCompatibility sourceCompatibility == 1.81.8 targetCompatibility targetCompatibility == 1.81.8 group group == 'org.starwars''org.starwars' version version == '1.0-SNAPSHOT''1.0-SNAPSHOT' repositories repositories {{ mavenCentralmavenCentral(()) }} }} dependencies dependencies {{ providedCompile providedCompile 'javax:javaee-api:7.0''javax:javaee-api:7.0' }} B U I L D . G R A D L E  alexsotob  lordofthejars
  20. 20. apply pluginapply plugin:: 'war''war' allprojects allprojects {{ sourceCompatibility sourceCompatibility == 1.81.8 targetCompatibility targetCompatibility == 1.81.8 group group == 'org.starwars''org.starwars' version version == '1.0-SNAPSHOT''1.0-SNAPSHOT' repositories repositories {{ mavenCentralmavenCentral(()) }} }} dependencies dependencies {{ providedCompile providedCompile 'javax:javaee-api:7.0''javax:javaee-api:7.0' }} B U I L D . G R A D L E ./gradlew compileJava  alexsotob  lordofthejars
  21. 21. apply pluginapply plugin:: 'war''war' allprojects allprojects {{ sourceCompatibility sourceCompatibility == 1.81.8 targetCompatibility targetCompatibility == 1.81.8 group group == 'org.starwars''org.starwars' version version == '1.0-SNAPSHOT''1.0-SNAPSHOT' repositories repositories {{ mavenCentralmavenCentral(()) }} }} dependencies dependencies {{ providedCompile providedCompile 'javax:javaee-api:7.0''javax:javaee-api:7.0' }} B U I L D . G R A D L E ./gradlew compileJava Gradle 2.12 > compileOnly scope  alexsotob  lordofthejars
  22. 22. dependencies dependencies {{ testCompile testCompile 'junit:junit:4.12''junit:junit:4.12' testCompile testCompile 'org.hamcrest:hamcrest-library:1.3''org.hamcrest:hamcrest-library:1.3' testCompiletestCompile(('org.mockito:mockito-all:1.10.19''org.mockito:mockito-all:1.10.19')) {{ exclude group exclude group:: 'org.hamcrest''org.hamcrest' }} }} B U I L D . G R A D L E  alexsotob  lordofthejars
  23. 23. dependencies dependencies {{ testCompile testCompile 'junit:junit:4.12''junit:junit:4.12' testCompile testCompile 'org.hamcrest:hamcrest-library:1.3''org.hamcrest:hamcrest-library:1.3' testCompiletestCompile(('org.mockito:mockito-all:1.10.19''org.mockito:mockito-all:1.10.19')) {{ exclude group exclude group:: 'org.hamcrest''org.hamcrest' }} }} test test {{ systemProperties System systemProperties System..getPropertiesgetProperties(()) systemProperties systemProperties[['starwars_planets_url''starwars_planets_url']] == 'http://preproduction:8080/starwars''http://preproduction:8080/starwars' }} B U I L D . G R A D L E  alexsotob  lordofthejars
  24. 24. dependencies dependencies {{ testCompile testCompile 'junit:junit:4.12''junit:junit:4.12' testCompile testCompile 'org.hamcrest:hamcrest-library:1.3''org.hamcrest:hamcrest-library:1.3' testCompiletestCompile(('org.mockito:mockito-all:1.10.19''org.mockito:mockito-all:1.10.19')) {{ exclude group exclude group:: 'org.hamcrest''org.hamcrest' }} }} test test {{ systemProperties System systemProperties System..getPropertiesgetProperties(()) systemProperties systemProperties[['starwars_planets_url''starwars_planets_url']] == 'http://preproduction:8080/starwars''http://preproduction:8080/starwars' }} B U I L D . G R A D L E ./gradlew :test  alexsotob  lordofthejars
  25. 25. U N I T T E S T S A R E N O T E N O U G H  alexsotob  lordofthejars
  26. 26. include include 'integration-test''integration-test' S E T T I N G S . G R A D L E I N T E G R A T I O N - T E S T / B U I L D . G R A D L E  alexsotob  lordofthejars
  27. 27. include include 'integration-test''integration-test' test test {{ ifif ((projectproject..hasPropertyhasProperty(("happyPath""happyPath")))) {{ filter filter {{ includePatterns includePatterns == [["org.starwars.PlanetServiceAPITest.shouldReturnTheAverage""org.starwars.PlanetServiceAPITest.shouldReturnTheAverage"]] }} }} }} S E T T I N G S . G R A D L E I N T E G R A T I O N - T E S T / B U I L D . G R A D L E  alexsotob  lordofthejars
  28. 28. include include 'integration-test''integration-test' test test {{ ifif ((projectproject..hasPropertyhasProperty(("happyPath""happyPath")))) {{ filter filter {{ includePatterns includePatterns == [["org.starwars.PlanetServiceAPITest.shouldReturnTheAverage""org.starwars.PlanetServiceAPITest.shouldReturnTheAverage"]] }} }} }} S E T T I N G S . G R A D L E I N T E G R A T I O N - T E S T / B U I L D . G R A D L E ./gradlew :integration-test:test -PhappyPath  alexsotob  lordofthejars
  29. 29. C O D E A N A L Y S I S  alexsotob  lordofthejars
  30. 30. L E T D E V E L O P E R S G O  alexsotob  lordofthejars
  31. 31. I N T E G R A T I O N T E S T S  alexsotob  lordofthejars
  32. 32. C O D E C O V E R A G E
  33. 33. apply pluginapply plugin:: 'jacoco''jacoco' B U I L D . G R A D L E  alexsotob  lordofthejars
  34. 34. apply pluginapply plugin:: 'jacoco''jacoco' jacoco jacoco {{ toolVersion toolVersion == "0.7.5.201505241946""0.7.5.201505241946" }} B U I L D . G R A D L E  alexsotob  lordofthejars
  35. 35. apply pluginapply plugin:: 'jacoco''jacoco' jacoco jacoco {{ toolVersion toolVersion == "0.7.5.201505241946""0.7.5.201505241946" }} task task jacocoRootTestReportjacocoRootTestReport((typetype:: JacocoReport JacocoReport)) {{ sourceSets sourceSets sourceSets sourceSets..mainmain def jacocoTestFiles def jacocoTestFiles == [["$buildDir/jacoco/test.exec""$buildDir/jacoco/test.exec"]] subprojects subprojects..each each {{ p p -->> def coverageFileLocation def coverageFileLocation == "$p.buildDir/jacoco/test.exec""$p.buildDir/jacoco/test.exec" ifif ((newnew FileFile((coverageFileLocationcoverageFileLocation))..existsexists(()))) {{ jacocoTestFiles jacocoTestFiles <<<< coverageFileLocation coverageFileLocation }} }} B U I L D . G R A D L E  alexsotob  lordofthejars
  36. 36. apply pluginapply plugin:: 'jacoco''jacoco' jacoco jacoco {{ toolVersion toolVersion == "0.7.5.201505241946""0.7.5.201505241946" }} task task jacocoRootTestReportjacocoRootTestReport((typetype:: JacocoReport JacocoReport)) {{ sourceSets sourceSets sourceSets sourceSets..mainmain def jacocoTestFiles def jacocoTestFiles == [["$buildDir/jacoco/test.exec""$buildDir/jacoco/test.exec"]] subprojects subprojects..each each {{ p p -->> def coverageFileLocation def coverageFileLocation == "$p.buildDir/jacoco/test.exec""$p.buildDir/jacoco/test.exec" ifif ((newnew FileFile((coverageFileLocationcoverageFileLocation))..existsexists(()))) {{ jacocoTestFiles jacocoTestFiles <<<< coverageFileLocation coverageFileLocation }} }} executionData executionData filesfiles((jacocoTestFilesjacocoTestFiles)) reports reports {{ xml xml..enabled enabled falsefalse csv csv..enabled enabled falsefalse }} }} B U I L D . G R A D L E  alexsotob  lordofthejars
  37. 37. apply pluginapply plugin:: 'jacoco''jacoco' jacoco jacoco {{ toolVersion toolVersion == "0.7.5.201505241946""0.7.5.201505241946" }} task task jacocoRootTestReportjacocoRootTestReport((typetype:: JacocoReport JacocoReport)) {{ sourceSets sourceSets sourceSets sourceSets..mainmain def jacocoTestFiles def jacocoTestFiles == [["$buildDir/jacoco/test.exec""$buildDir/jacoco/test.exec"]] subprojects subprojects..each each {{ p p -->> def coverageFileLocation def coverageFileLocation == "$p.buildDir/jacoco/test.exec""$p.buildDir/jacoco/test.exec" ifif ((newnew FileFile((coverageFileLocationcoverageFileLocation))..existsexists(()))) {{ jacocoTestFiles jacocoTestFiles <<<< coverageFileLocation coverageFileLocation }} }} executionData executionData filesfiles((jacocoTestFilesjacocoTestFiles)) reports reports {{ xml xml..enabled enabled falsefalse csv csv..enabled enabled falsefalse }} }} B U I L D . G R A D L E ./gradlew jacocoRootTestReport  alexsotob  lordofthejars
  38. 38.  alexsotob  lordofthejars
  39. 39. V E R S I O N I N G S T R A T E G Y  alexsotob  lordofthejars
  40. 40. 1 . 0 - S N A P S H O T - > 1 . 0 . 1 3 4  alexsotob  lordofthejars
  41. 41. importimport java java..utilutil..regexregex..MatcherMatcher importimport java java..utilutil..regexregex..PatternPattern Pattern SHORT_VERSION_PATTERN Pattern SHORT_VERSION_PATTERN == ~~/(d+).(d+)//(d+).(d+)/ Pattern SNAPSHOT_SHORT_VERSION_PATTERN Pattern SNAPSHOT_SHORT_VERSION_PATTERN == ~~/$WHITESPACE$SHORT_VERSION_PATTERN$SNAPSHOT_IDENTIFIER$WHITESPACE//$WHITESPACE$SHORT_VERSION_PATTERN$SNAPSHOT_IDENTIFIER$WHITESPACE/ Matcher m Matcher m == checkInputAgainstPatterncheckInputAgainstPattern((versionversion,, SNAPSHOT_SHORT_VERSION_PATTERN SNAPSHOT_SHORT_VERSION_PATTERN)) G R A D L E / V E R S I O N I N G . G R A D L E  alexsotob  lordofthejars
  42. 42. importimport java java..utilutil..regexregex..MatcherMatcher importimport java java..utilutil..regexregex..PatternPattern Pattern SHORT_VERSION_PATTERN Pattern SHORT_VERSION_PATTERN == ~~/(d+).(d+)//(d+).(d+)/ Pattern SNAPSHOT_SHORT_VERSION_PATTERN Pattern SNAPSHOT_SHORT_VERSION_PATTERN == ~~/$WHITESPACE$SHORT_VERSION_PATTERN$SNAPSHOT_IDENTIFIER$WHITESPACE//$WHITESPACE$SHORT_VERSION_PATTERN$SNAPSHOT_IDENTIFIER$WHITESPACE/ Matcher m Matcher m == checkInputAgainstPatterncheckInputAgainstPattern((versionversion,, SNAPSHOT_SHORT_VERSION_PATTERN SNAPSHOT_SHORT_VERSION_PATTERN)) ifif ((mm)) {{ Integer major Integer major == m m[[00]][[11]]..toIntegertoInteger(()) Integer minor Integer minor == m m[[00]][[22]]..toIntegertoInteger(()) project project..version version == newnew ProjectVersionProjectVersion((majormajor,, minor minor,, System System..envenv..SOURCE_BUILD_NUMBERSOURCE_BUILD_NUMBER)) }} G R A D L E / V E R S I O N I N G . G R A D L E  alexsotob  lordofthejars
  43. 43. importimport java java..utilutil..regexregex..MatcherMatcher importimport java java..utilutil..regexregex..PatternPattern Pattern SHORT_VERSION_PATTERN Pattern SHORT_VERSION_PATTERN == ~~/(d+).(d+)//(d+).(d+)/ Pattern SNAPSHOT_SHORT_VERSION_PATTERN Pattern SNAPSHOT_SHORT_VERSION_PATTERN == ~~/$WHITESPACE$SHORT_VERSION_PATTERN$SNAPSHOT_IDENTIFIER$WHITESPACE//$WHITESPACE$SHORT_VERSION_PATTERN$SNAPSHOT_IDENTIFIER$WHITESPACE/ Matcher m Matcher m == checkInputAgainstPatterncheckInputAgainstPattern((versionversion,, SNAPSHOT_SHORT_VERSION_PATTERN SNAPSHOT_SHORT_VERSION_PATTERN)) ifif ((mm)) {{ Integer major Integer major == m m[[00]][[11]]..toIntegertoInteger(()) Integer minor Integer minor == m m[[00]][[22]]..toIntegertoInteger(()) project project..version version == newnew ProjectVersionProjectVersion((majormajor,, minor minor,, System System..envenv..SOURCE_BUILD_NUMBERSOURCE_BUILD_NUMBER)) }} classclass ProjectVersionProjectVersion {{ Integer major Integer major Integer minor Integer minor String buildNumber String buildNumber @Override @Override String String toStringtoString(()) {{ String fullVersion String fullVersion == "$major.$minor""$major.$minor" ifif((buildNumberbuildNumber)) fullVersion fullVersion ++== ".$buildNumber"".$buildNumber" returnreturn fullVersion fullVersion }} }} G R A D L E / V E R S I O N I N G . G R A D L E  alexsotob  lordofthejars
  44. 44. P A C K A G I N G A P P L I C A T I O N  alexsotob  lordofthejars
  45. 45. allprojects allprojects {{ apply apply fromfrom:: "$rootDir/gradle/versioning.gradle""$rootDir/gradle/versioning.gradle" }} B U I L D . G R A D L E  alexsotob  lordofthejars
  46. 46. allprojects allprojects {{ apply apply fromfrom:: "$rootDir/gradle/versioning.gradle""$rootDir/gradle/versioning.gradle" }} war war {{ manifest manifest {{ attributes attributes "Implementation-Version""Implementation-Version":: project project..versionversion..toStringtoString(()) }} }} B U I L D . G R A D L E  alexsotob  lordofthejars
  47. 47. allprojects allprojects {{ apply apply fromfrom:: "$rootDir/gradle/versioning.gradle""$rootDir/gradle/versioning.gradle" }} war war {{ manifest manifest {{ attributes attributes "Implementation-Version""Implementation-Version":: project project..versionversion..toStringtoString(()) }} }} B U I L D . G R A D L E ./gradlew assemble  alexsotob  lordofthejars
  48. 48. P U B L I S H I N G  alexsotob  lordofthejars
  49. 49. apply pluginapply plugin:: 'maven-publish''maven-publish' task task sourceJarsourceJar((typetype:: Jar Jar)) {{ fromfrom sourceSets sourceSets..mainmain..allJavaallJava }} task javadocJar task javadocJar ((typetype:: Jar Jar,, dependsOn dependsOn:: javadoc javadoc)) {{ fromfrom javadoc javadoc..destinationDirdestinationDir }} B U I L D . G R A D L E  alexsotob  lordofthejars
  50. 50. apply pluginapply plugin:: 'maven-publish''maven-publish' task task sourceJarsourceJar((typetype:: Jar Jar)) {{ fromfrom sourceSets sourceSets..mainmain..allJavaallJava }} task javadocJar task javadocJar ((typetype:: Jar Jar,, dependsOn dependsOn:: javadoc javadoc)) {{ fromfrom javadoc javadoc..destinationDirdestinationDir }} extext..repoUrl repoUrl == "$config.binaryRepository.url/$config.binaryRepository.name""$config.binaryRepository.url/$config.binaryRepository.name" publishing publishing {{ publications publications {{ webAppwebApp((MavenPublicationMavenPublication)){{ fromfrom components components..webweb artifact sourceJar artifact sourceJar {{classifier classifier "sources""sources"}} artifact javadocJar artifact javadocJar {{classifier classifier "javadoc""javadoc"}} }} }} repositories repositories {{ maven maven {{ url repoUrl url repoUrl}} }} }} B U I L D . G R A D L E  alexsotob  lordofthejars
  51. 51. apply pluginapply plugin:: 'maven-publish''maven-publish' task task sourceJarsourceJar((typetype:: Jar Jar)) {{ fromfrom sourceSets sourceSets..mainmain..allJavaallJava }} task javadocJar task javadocJar ((typetype:: Jar Jar,, dependsOn dependsOn:: javadoc javadoc)) {{ fromfrom javadoc javadoc..destinationDirdestinationDir }} extext..repoUrl repoUrl == "$config.binaryRepository.url/$config.binaryRepository.name""$config.binaryRepository.url/$config.binaryRepository.name" publishing publishing {{ publications publications {{ webAppwebApp((MavenPublicationMavenPublication)){{ fromfrom components components..webweb artifact sourceJar artifact sourceJar {{classifier classifier "sources""sources"}} artifact javadocJar artifact javadocJar {{classifier classifier "javadoc""javadoc"}} }} }} repositories repositories {{ maven maven {{ url repoUrl url repoUrl}} }} }} B U I L D . G R A D L E ./gradlew publish  alexsotob  lordofthejars
  52. 52. A C C E P T A N C E S T A G E  alexsotob  lordofthejars
  53. 53. with Serenity BDD A C C E P T A N C E T E S T S  alexsotob  lordofthejars
  54. 54. R E P O R T  alexsotob  lordofthejars
  55. 55. with Gatling S T R E S S T E S T S  alexsotob  lordofthejars
  56. 56. R E P O R T  alexsotob  lordofthejars
  57. 57. with Pact-JVM C O N T R A C T T E S T S  alexsotob  lordofthejars
  58. 58. C O N T R A C T D R I V E N T E S T S  alexsotob  lordofthejars
  59. 59. with Jenkins O R C H E S T R A T I N G S T A G E S
  60. 60.  alexsotob  lordofthejars
  61. 61.  alexsotob  lordofthejars
  62. 62.  alexsotob  lordofthejars
  63. 63.  alexsotob  lordofthejars
  64. 64.  alexsotob  lordofthejars
  65. 65.  alexsotob  lordofthejars
  66. 66.  alexsotob  lordofthejars
  67. 67.  alexsotob  lordofthejars
  68. 68. N O M O R E J O B S P L E A S E  alexsotob  lordofthejars
  69. 69. J E N K I N S P I P E L I N E - A S - C O D E  alexsotob  lordofthejars
  70. 70. F E A T U R E S O F P I P E L I N E P L U G I N Configuration in Source Repositories
  71. 71. F E A T U R E S O F P I P E L I N E P L U G I N Configuration in Source Repositories Less click-and-type, more code
  72. 72. F E A T U R E S O F P I P E L I N E P L U G I N Configuration in Source Repositories Less click-and-type, more code From simple to complex
  73. 73. F E A T U R E S O F P I P E L I N E P L U G I N Configuration in Source Repositories Less click-and-type, more code From simple to complex Survives Jenkins restarts & connection losses
  74. 74. F E A T U R E S O F P I P E L I N E P L U G I N Configuration in Source Repositories Less click-and-type, more code From simple to complex Survives Jenkins restarts & connection losses Reusable Definitions
  75. 75. F E A T U R E S O F P I P E L I N E P L U G I N Configuration in Source Repositories Less click-and-type, more code From simple to complex Survives Jenkins restarts & connection losses Reusable Definitions Build history/trend segregated per branches
  76. 76. F E A T U R E S O F P I P E L I N E P L U G I N Configuration in Source Repositories Less click-and-type, more code From simple to complex Survives Jenkins restarts & connection losses Reusable Definitions Build history/trend segregated per branches UI
  77. 77. stage 'compile'stage 'compile' node {node { checkout scm checkout scm sh "./gradlew clean compileJava" sh "./gradlew clean compileJava" stash excludes: 'build/', includes: '**', name: 'source' stash excludes: 'build/', includes: '**', name: 'source' }} J E N K I N S F I L E ( 1 / 3 )  alexsotob  lordofthejars
  78. 78. stage 'compile'stage 'compile' node {node { checkout scm checkout scm sh "./gradlew clean compileJava" sh "./gradlew clean compileJava" stash excludes: 'build/', includes: '**', name: 'source' stash excludes: 'build/', includes: '**', name: 'source' }} stage 'commitTest'stage 'commitTest' parallel 'unit' : {parallel 'unit' : { node { node { unstash 'source' unstash 'source' sh "./gradlew :test" sh "./gradlew :test" stash includes: 'build/jacoco/*.exec', name: 'unitCodeCoverage' stash includes: 'build/jacoco/*.exec', name: 'unitCodeCoverage' step([$class: 'JUnitResultArchiver', testResults: '**/build/test-results/*.xml']) step([$class: 'JUnitResultArchiver', testResults: '**/build/test-results/*.xml']) } } }, 'integration': {}, 'integration': { node { node { unstash 'source' unstash 'source' sh "./gradlew -PhappyPath :integration-test:test" sh "./gradlew -PhappyPath :integration-test:test" step([$class: 'JUnitResultArchiver', testResults: '**/build/test-results/*.xml']) step([$class: 'JUnitResultArchiver', testResults: '**/build/test-results/*.xml']) } } }} J E N K I N S F I L E ( 1 / 3 )  alexsotob  lordofthejars
  79. 79. def def assembleassemble((String switches String switches == nullnull)) {{ run run 'assemble''assemble',, switches switches }} J E N K I N S / G R A D L E . G R O O V Y J E N K I N S F I L E ( 2 / 3 )  alexsotob  lordofthejars
  80. 80. def def assembleassemble((String switches String switches == nullnull)) {{ run run 'assemble''assemble',, switches switches }} voidvoid runrun((String tasksString tasks,, String switches String switches == nullnull)) {{ String gradleCommand String gradleCommand == """";; gradleCommand gradleCommand ++== './gradlew ''./gradlew ' gradleCommand gradleCommand ++== tasks tasks ifif((switches switches !=!= nullnull)) {{ gradleCommand gradleCommand ++== ' '' ' gradleCommand gradleCommand ++== switches switches }} sh gradleCommand sh gradleCommand..toStringtoString(()) }} J E N K I N S / G R A D L E . G R O O V Y J E N K I N S F I L E ( 2 / 3 )  alexsotob  lordofthejars
  81. 81. def def assembleassemble((String switches String switches == nullnull)) {{ run run 'assemble''assemble',, switches switches }} voidvoid runrun((String tasksString tasks,, String switches String switches == nullnull)) {{ String gradleCommand String gradleCommand == """";; gradleCommand gradleCommand ++== './gradlew ''./gradlew ' gradleCommand gradleCommand ++== tasks tasks ifif((switches switches !=!= nullnull)) {{ gradleCommand gradleCommand ++== ' '' ' gradleCommand gradleCommand ++== switches switches }} sh gradleCommand sh gradleCommand..toStringtoString(()) }} returnreturn thisthis;; J E N K I N S / G R A D L E . G R O O V Y J E N K I N S F I L E ( 2 / 3 )  alexsotob  lordofthejars
  82. 82. def def assembleassemble((String switches String switches == nullnull)) {{ run run 'assemble''assemble',, switches switches }} voidvoid runrun((String tasksString tasks,, String switches String switches == nullnull)) {{ String gradleCommand String gradleCommand == """";; gradleCommand gradleCommand ++== './gradlew ''./gradlew ' gradleCommand gradleCommand ++== tasks tasks ifif((switches switches !=!= nullnull)) {{ gradleCommand gradleCommand ++== ' '' ' gradleCommand gradleCommand ++== switches switches }} sh gradleCommand sh gradleCommand..toStringtoString(()) }} returnreturn thisthis;; def gradle def gradle == load load 'jenkins/gradle.groovy''jenkins/gradle.groovy' J E N K I N S / G R A D L E . G R O O V Y J E N K I N S F I L E ( 2 / 3 )  alexsotob  lordofthejars
  83. 83. def def assembleassemble((String switches String switches == nullnull)) {{ run run 'assemble''assemble',, switches switches }} voidvoid runrun((String tasksString tasks,, String switches String switches == nullnull)) {{ String gradleCommand String gradleCommand == """";; gradleCommand gradleCommand ++== './gradlew ''./gradlew ' gradleCommand gradleCommand ++== tasks tasks ifif((switches switches !=!= nullnull)) {{ gradleCommand gradleCommand ++== ' '' ' gradleCommand gradleCommand ++== switches switches }} sh gradleCommand sh gradleCommand..toStringtoString(()) }} returnreturn thisthis;; def gradle def gradle == load load 'jenkins/gradle.groovy''jenkins/gradle.groovy' nodenode(('linux''linux')) {{ unstash unstash 'source''source' withEnvwithEnv(([["SOURCE_BUILD_NUMBER=${env.BUILD_NUMBER}""SOURCE_BUILD_NUMBER=${env.BUILD_NUMBER}"]])) {{ gradle gradle..assembleassemble(()) }} }} J E N K I N S / G R A D L E . G R O O V Y J E N K I N S F I L E ( 2 / 3 )  alexsotob  lordofthejars
  84. 84. input messageinput message:: "Deploy Application to QA ?""Deploy Application to QA ?" J E N K I N S F I L E ( 3 / 3 )  alexsotob  lordofthejars
  85. 85. input messageinput message:: "Deploy Application to QA ?""Deploy Application to QA ?" stage namestage name:: 'Deploy to QA''Deploy to QA',, concurrency concurrency:: 11 node node {{ echo echo "Application Deployed to QA.""Application Deployed to QA." J E N K I N S F I L E ( 3 / 3 )  alexsotob  lordofthejars
  86. 86. input messageinput message:: "Deploy Application to QA ?""Deploy Application to QA ?" stage namestage name:: 'Deploy to QA''Deploy to QA',, concurrency concurrency:: 11 node node {{ echo echo "Application Deployed to QA.""Application Deployed to QA." withCredentialswithCredentials(([[[[$$classclass:: 'UsernamePasswordMultiBinding''UsernamePasswordMultiBinding',, credentialsId credentialsId:: 'MyID''MyID',, usernameVariable usernameVariable:: 'GIT_USERNAME''GIT_USERNAME',, passwordVariable passwordVariable:: 'GIT_PASSWORD''GIT_PASSWORD']]]])) {{ sh sh "git tag -a some_tag -m 'Jenkins'""git tag -a some_tag -m 'Jenkins'" sh sh "git push https://${env.GIT_USERNAME}:${env.GIT_PASSWORD}@ --tags""git push https://${env.GIT_USERNAME}:${env.GIT_PASSWORD}@ --tags" }} hipchatSendhipchatSend((messagemessage:: 'Build tagged''Build tagged')) }} J E N K I N S F I L E ( 3 / 3 )  alexsotob  lordofthejars
  87. 87. D O C K E R P I P E L I N E I N T E G R A T I O N
  88. 88. dockerdocker..withRegistrywithRegistry(('https://lordofthejars-docker-continuous_delivery.bintray.io''https://lordofthejars-docker-continuous_delivery.bintray.io',, 'd4fc3fa9-39f7-47ea-a57c-795642f90989''d4fc3fa9-39f7-47ea-a57c-795642f90989')) {{ git git 'git@github.com:lordofthejars/busybox.git''git@github.com:lordofthejars/busybox.git' def newApp def newApp == docker docker..build build "lordofthejars-docker-continuous_delivery.bintray.io/lordofthejars/javatest:${env.BUILD_TAG}""lordofthejars-docker-continuous_delivery.bintray.io/lordofthejars/javatest:${env.BUILD_TAG}" newApp newApp..pushpush(()) }} J E N K I N S F I L E  alexsotob  lordofthejars
  89. 89. dockerdocker..withRegistrywithRegistry(('https://lordofthejars-docker-continuous_delivery.bintray.io''https://lordofthejars-docker-continuous_delivery.bintray.io',, 'd4fc3fa9-39f7-47ea-a57c-795642f90989''d4fc3fa9-39f7-47ea-a57c-795642f90989')) {{ git git 'git@github.com:lordofthejars/busybox.git''git@github.com:lordofthejars/busybox.git' def newApp def newApp == docker docker..build build "lordofthejars-docker-continuous_delivery.bintray.io/lordofthejars/javatest:${env.BUILD_TAG}""lordofthejars-docker-continuous_delivery.bintray.io/lordofthejars/javatest:${env.BUILD_TAG}" newApp newApp..pushpush(()) }} dockerdocker..imageimage(('lordofthejars/javatest''lordofthejars/javatest'))..withRun withRun {{c c -->> sh sh './executeTests.sh''./executeTests.sh' }} J E N K I N S F I L E  alexsotob  lordofthejars
  90. 90. dockerdocker..withRegistrywithRegistry(('https://lordofthejars-docker-continuous_delivery.bintray.io''https://lordofthejars-docker-continuous_delivery.bintray.io',, 'd4fc3fa9-39f7-47ea-a57c-795642f90989''d4fc3fa9-39f7-47ea-a57c-795642f90989')) {{ git git 'git@github.com:lordofthejars/busybox.git''git@github.com:lordofthejars/busybox.git' def newApp def newApp == docker docker..build build "lordofthejars-docker-continuous_delivery.bintray.io/lordofthejars/javatest:${env.BUILD_TAG}""lordofthejars-docker-continuous_delivery.bintray.io/lordofthejars/javatest:${env.BUILD_TAG}" newApp newApp..pushpush(()) }} dockerdocker..imageimage(('lordofthejars/javatest''lordofthejars/javatest'))..withRun withRun {{c c -->> sh sh './executeTests.sh''./executeTests.sh' }} dockerdocker..imageimage(('8-jdk-alpine''8-jdk-alpine'))..insideinside(('-v ~/.gradle:/root/.gradle -u 1000:50''-v ~/.gradle:/root/.gradle -u 1000:50')) {{ // workspace is mounted inside image automatically// workspace is mounted inside image automatically sh sh './gradlew compileJava''./gradlew compileJava' }} J E N K I N S F I L E  alexsotob  lordofthejars
  91. 91.  alexsotob  lordofthejars
  92. 92. M U L T I B R A N C H P I P E L I N E  alexsotob  lordofthejars
  93. 93. M U L T I B R A N C H P I P E L I N E J O B  alexsotob  lordofthejars
  94. 94. D A S H B O A R D W I T H D E T E C T E D B R A N C H E S  alexsotob  lordofthejars
  95. 95. L E T ' S W I N D D O W N  alexsotob  lordofthejars
  96. 96. O N L Y O N E P I E C E O F T H E J I G S A W  alexsotob  lordofthejars
  97. 97. F O L L O W T H E R U L E S , A D A P T T O Y O U R N E E D S  alexsotob  lordofthejars
  98. 98.  C L O U D B E E S J E N K I N S
  99. 99. I T I S N O T N E C E S S A R Y T O C H A N G E . S U R V I V A L I S N O T M A N D A T O R Y. W. Edwards Deming  alexsotob  lordofthejars
  100. 100.  http://www.slideshare.net/asotobu/continuous-delivery-as-code  asotobu@gmail.com  alexsotob  lordofthejars
  101. 101. https://github.com/lordofthejars/starwars https://jenkins.io/ https://jenkins.io/solutions/pipeline/ http://arquillian.org/ http://www.thucydides.info/ http://gatling.io/ https://github.com/DiUS/pact-jvm https://gradle.org/  alexsotob  lordofthejars

×