SlideShare ist ein Scribd-Unternehmen logo
1 von 19
Taking Jenkins Pipeline to the Extreme
Yinon Avraham
Tech Lead @ eBay
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.com
AGENDA
● Why
● What
● How
● WOW!
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
WHY
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
MICROSERVICES
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
Service
Service
Service Service
SQL
DB
Service
SQL
DB
Service
NoSQL
DB
HTTPHTTP
HTTP HTTP
3rd Party
Service
WHAT
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
IMPROVED CI/CD PROCESS
CI: For each active branch:
1. Build
2. Unit Tests
3. Publish Artifacts
4. Integration Tests
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
M
F RF D
CI
M
F RF D
CI
Deploy & TestDeploy & Test
Deploy to
Production
Deploy to
Production
Repo 2Repo 1
Deploy to Acceptance Environment & Test
REQUIREMENTS
1. Configuration as Code
2. Multibranch Coverage
3. Visibility
4. Reuse Job Configuration (D.R.Y)
5. Integration Tests Isolation
6. Self Contained Configuration
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
REQUIREMENTS
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
HOW
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
CODE REUSE - GLOBAL PIPELINE LIBRARIES
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
Jenkinsfile
#!groovy
@Library('buildtools@1.x') _
properties([
parameters([forcePublishParam()]),
discardOldBuildsProperty()
])
withMavenDockerNode(jdk: 'JDK8') { buildTools ->
stage('Setup') {
buildTools.init()
dir('app') {
checkout scm
}
}
dir('app') {
mavenBuildTestPublish()
}
failAsUnstable {
withDockerEx { dockerEx ->
def kafkaIp
stage('Start Sidecars') {
kafkaIp = startKafkaSidecar(dockerEx)
}
stage('Integration Tests') {
dir('app') {
runIntegrationTests(kafkaIp)
} } } } }
def call() {
stage('Build') {
sh 'mvn clean verify –U –B –fae –Dmaven.test.failure.ignore'
}
stage('Unit Tests') {
junit '**/target/surefire-reports/TEST-*.xml'
}
stage('Publish') {
def msg = canDeploy()
if (msg == 'ok' || params.FORCE_PUBLISH) {
sh 'mvn deploy'
} else {
echo "Publish skipped, cannot deploy: ${msg}"
}
}
}
vars/mavenBuildTestPublish
ISOLATION – “SIDECAR” PATTERN
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
Jenkins
Master
Jenkins
Slave
Jenkins
Slave
Kafka
Broker
Schema
Registry
Zookeeper
kafka sidecar
Kafka
Broker
Schema
Registry
Zookeeper
kafka sidecar
ISOLATION – “SIDECAR” PATTERN
Docker Extension – Support Docker Compose
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
import com.ebay.tools.DockerEx
def call(body) {
def dockerEx = new DockerEx(this)
try {
body(dockerEx)
} finally {
dockerEx.close()
}
}
vars/withDockerEx
def call(dockerEx) {
def kafka = dockerEx.compose('kafka',
[file: 'buildtools/docker/kafka.yml'])
kafka.defaultNetwork.create()
def ip = kafka.inspectGateway()
echo "Kafka IP: ${ip}"
withEnv(["KAFKA_IP=${ip}"]) {
kafka.up().ps()
}
waitForPort host: ip, port: 29092 // Kafka broker
waitForEndpoint url: "http://${ip}:8081" // Schema Registry
ip
}
vars/startKafkaSidecar
withDockerEx { dockerEx ->
def kafkaIp
stage('Start Sidecars') {
kafkaIp = startKafkaSidecar(dockerEx)
}
stage('Integration Tests') {
dir('app') {
runIntegrationTests(kafkaIp)
}
}
}
class DockerEx implements Serializable {
protected final def script
private final ArrayMap compositions = new ArrayMap()
DockerEx(script) {
this.script = script
}
DockerExCompose compose(String name, Map config = [:]) {
DockerEx dockerEx = this
compositions.get(name, { ->
new DockerExCompose(docker, name, config)
}
}
void close() {
closeAllCompositions()
}
void closeAllCompositions() {
compositions.forEach { _, compose ->
try { compose.down() } catch (e) {
script.echo "Destroy '${compose.name}' failed: ${e}"
}
}
}
}
src/com/ebay/tools/DockerEx
ISOLATION – “SIDECAR” PATTERN
Docker Extension – Support Docker Compose
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
class DockerExCompose implements Serializable {
private final DockerEx dockerEx
private final def script
private final ArrayMap config
final String name
DockerExCompose(DockerEx dockerEx, String name,
Map config = [:]) {
this.dockerEx = dockerEx
this.script = dockerEx.script
this.name = name
this.config = config
}
DockerExCompose up() {
script.sh "docker-compose –project-name $name " +
"${fileArg()} up -d"
this
}
DockerExCompose down() {
script.sh "docker-compose ${fileArg()} down"
this
}
src/com/ebay/tools/DockerExCompose
DockerExCompose ps() {
script.sh "docker-compose ${fileArg()} ps"
this
}
String inspectGateway() {
defaultNetwork.inspectGateway()
}
DockerExNetwork getDefaultNetwork() {
docker.network("${name}_default".toString())
}
private String fileArg() {
def file = config.get('file')
file ? "--file ${file}" : ''
}
}
String inspectGateway() {
def res = script.sh(script: "docker network inspect -f " +
"'{{range .IPAM.Config}}{{.Gateway}}{{end}}' $name",
returnStdout: true)
res.trim().split('/')[0].toString()
}
SELF CONTAINED CONFIGURATION
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
withMavenDockerNode
import com.ebay.tools.BuildTools
def call(Map args, body) {
timestamps {
def timeoutArgs = args.timeout ?: [time: 1, unit: 'HOURS']
timeout (timeoutArgs) {
def label = 'maven-docker-builder'
mavenDockerPodTemplate(label) {
node(label) {
def buildTools = new BuildTools(this, args)
body(buildTools)
}
}
}
}
}
private void mavenDockerPodTemplate(String label, body) {
podTemplate(
label: label,
containers: [
containerTemplate(
name: 'jnlp',
image: ...
)] ...
) {
body()
}
}
Jenkinsfile
#!groovy
@Library('buildtools@1.x') _
properties([
parameters([forcePublishParam()]),
discardOldBuildsProperty()
])
...
src/com/ebay/tools/BuildTools
class BuildTools implements Serializable {
private final def script
private final ArrayMap args
void init() {
gitCloneBuildTools()
setJavaHome(args.get('jdk'))
printToolsVersion()
}
private void printToolsVersion() {
script.sh script: 'mvn --version', returnStatus: true
script.sh script: 'java -version', returnStatus: true
script.sh script: 'docker version', returnStatus: true
}
}
TIPS & TRICKS
● Do not load global libraries implicitly by default.
This is sometimes redundant and it is not visible
● Do load global libraries explicitly with specific stable development branch, e.g. “1.x”.
This way you get fixes and enhancements transparently, but keep the option for “2.x”
● Do treat your global pipeline library as any other library you write (e.g. versioning,
testing, etc.)
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
Global Pipeline Library Management
TIPS & TRICKS
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
Global Pipeline Library Management - Testing
#!groovy
@Library('buildtools@1.x') _
import static com.ebay.tools.test.PipelineTestUtils.*
withMavenDockerNode {
pipelineTests(this) {
testSuite('withBuildTools, shEx') {
test("withBuildTools - Test build tools with JDK8") {
withBuildTools(jdk: 'JDK8') { buildTools ->
def result = shEx(script: 'java -version')
assertStringContains expected: 'version "1.8.',
actual: result.get('err'),
message: 'Java version not as expected'
assertEquals expected: 0,
actual: result.get('status'),
message: "Return status not as expected"
}
}
...
}
}
}
TIPS & TRICKS
● Do prototype, test and play using the online script editor
● Do use the “Replay” functionality
● Do echo, echo, echo – write decisions and state to the console
● Trick: interactiveShell
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
Pipeline Script Development and Debugging
def call() {
timeout(time: 10, unit: 'MINUTES') {
echo "[Shell] ***** Starting interactive shell *****"
String cmd = ''
while (cmd != 'exit') {
cmd = input(id: 'cmd', message: 'Command:', parameters: [
[$class: 'TextParameterDefinition', name: 'cmd',
description: 'Enter shell command to run, "exit" to stop the shell']
])
def ret = sh(script: cmd, returnStatus: true)
echo "[Shell] Return Code: $ret"
}
echo "[Shell] Bye!"
}
}
TIPS & TRICKS
● Do organize in stages to reflect your pipeline flow, think visibility
● Do echo, echo, echo (yes, I already wrote it, it’s important)
● Do control the result status to reflect the actual result
● Do write your global library to express your DSL
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
Increase Visibility and Readability
Any Questions?
THANK YOU!
Yinon Avraham
yavraham@ebay.com
@yinonavraham
Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference

Weitere ähnliche Inhalte

Was ist angesagt?

10 Cool Facts about Gradle
10 Cool Facts about Gradle10 Cool Facts about Gradle
10 Cool Facts about Gradle
Evgeny Goldin
 
Gradle - time for a new build
Gradle - time for a new buildGradle - time for a new build
Gradle - time for a new build
Igor Khotin
 

Was ist angesagt? (20)

COSCUP 2020 Google 技術 x 公共參與 x 開源 口罩地圖技術開源
COSCUP 2020 Google 技術 x 公共參與 x 開源 口罩地圖技術開源COSCUP 2020 Google 技術 x 公共參與 x 開源 口罩地圖技術開源
COSCUP 2020 Google 技術 x 公共參與 x 開源 口罩地圖技術開源
 
Dev fest 2020 taiwan how to debug microservices on kubernetes as a pros (ht...
Dev fest 2020 taiwan   how to debug microservices on kubernetes as a pros (ht...Dev fest 2020 taiwan   how to debug microservices on kubernetes as a pros (ht...
Dev fest 2020 taiwan how to debug microservices on kubernetes as a pros (ht...
 
[Image Results] Java Build Tools: Part 2 - A Decision Maker's Guide Compariso...
[Image Results] Java Build Tools: Part 2 - A Decision Maker's Guide Compariso...[Image Results] Java Build Tools: Part 2 - A Decision Maker's Guide Compariso...
[Image Results] Java Build Tools: Part 2 - A Decision Maker's Guide Compariso...
 
Gradle in 45min - JBCN2-16 version
Gradle in 45min - JBCN2-16 versionGradle in 45min - JBCN2-16 version
Gradle in 45min - JBCN2-16 version
 
Service Discovery. Spring Cloud Internals
Service Discovery. Spring Cloud InternalsService Discovery. Spring Cloud Internals
Service Discovery. Spring Cloud Internals
 
Custom deployments with sbt-native-packager
Custom deployments with sbt-native-packagerCustom deployments with sbt-native-packager
Custom deployments with sbt-native-packager
 
Using the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM DevelopmentUsing the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM Development
 
Coscup x ruby conf tw 2021 google cloud buildpacks 剖析與實踐
Coscup x ruby conf tw 2021  google cloud buildpacks 剖析與實踐Coscup x ruby conf tw 2021  google cloud buildpacks 剖析與實踐
Coscup x ruby conf tw 2021 google cloud buildpacks 剖析與實踐
 
10 Cool Facts about Gradle
10 Cool Facts about Gradle10 Cool Facts about Gradle
10 Cool Facts about Gradle
 
GraphQL IN Golang
GraphQL IN GolangGraphQL IN Golang
GraphQL IN Golang
 
Madrid JAM limitaciones - dificultades
Madrid JAM limitaciones - dificultadesMadrid JAM limitaciones - dificultades
Madrid JAM limitaciones - dificultades
 
Cool JVM Tools to Help You Test
Cool JVM Tools to Help You TestCool JVM Tools to Help You Test
Cool JVM Tools to Help You Test
 
Gradle Introduction
Gradle IntroductionGradle Introduction
Gradle Introduction
 
How to Add Original Library to Android NDK
How to Add Original Library to Android NDKHow to Add Original Library to Android NDK
How to Add Original Library to Android NDK
 
Ship your Scala code often and easy with Docker
Ship your Scala code often and easy with DockerShip your Scala code often and easy with Docker
Ship your Scala code often and easy with Docker
 
Docker In Bank Unrated
Docker In Bank UnratedDocker In Bank Unrated
Docker In Bank Unrated
 
The world of gradle - an introduction for developers
The world of gradle  - an introduction for developersThe world of gradle  - an introduction for developers
The world of gradle - an introduction for developers
 
Docker In the Bank
Docker In the BankDocker In the Bank
Docker In the Bank
 
Groovy & Grails: Scripting for Modern Web Applications
Groovy & Grails: Scripting for Modern Web ApplicationsGroovy & Grails: Scripting for Modern Web Applications
Groovy & Grails: Scripting for Modern Web Applications
 
Gradle - time for a new build
Gradle - time for a new buildGradle - time for a new build
Gradle - time for a new build
 

Ähnlich wie Taking Jenkins Pipeline to the Extreme

Going live with BommandBox and docker Into The Box 2018
Going live with BommandBox and docker Into The Box 2018Going live with BommandBox and docker Into The Box 2018
Going live with BommandBox and docker Into The Box 2018
Ortus Solutions, Corp
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
David Padbury
 
2012 coscup - Build your PHP application on Heroku
2012 coscup - Build your PHP application on Heroku2012 coscup - Build your PHP application on Heroku
2012 coscup - Build your PHP application on Heroku
ronnywang_tw
 

Ähnlich wie Taking Jenkins Pipeline to the Extreme (20)

RichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesRichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile Devices
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
 
Into The Box 2018 Going live with commandbox and docker
Into The Box 2018 Going live with commandbox and dockerInto The Box 2018 Going live with commandbox and docker
Into The Box 2018 Going live with commandbox and docker
 
Going live with BommandBox and docker Into The Box 2018
Going live with BommandBox and docker Into The Box 2018Going live with BommandBox and docker Into The Box 2018
Going live with BommandBox and docker Into The Box 2018
 
Greach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut ConfigurationsGreach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut Configurations
 
Having Fun with Play
Having Fun with PlayHaving Fun with Play
Having Fun with Play
 
Dropwizard and Friends
Dropwizard and FriendsDropwizard and Friends
Dropwizard and Friends
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
 
Automated integration testing of distributed systems with Docker Compose and ...
Automated integration testing of distributed systems with Docker Compose and ...Automated integration testing of distributed systems with Docker Compose and ...
Automated integration testing of distributed systems with Docker Compose and ...
 
Lesson 2
Lesson 2Lesson 2
Lesson 2
 
Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)
 
Bangpypers april-meetup-2012
Bangpypers april-meetup-2012Bangpypers april-meetup-2012
Bangpypers april-meetup-2012
 
Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!
 
Introduction to PowerShell
Introduction to PowerShellIntroduction to PowerShell
Introduction to PowerShell
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidence
 
Deep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKDeep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UK
 
2012 coscup - Build your PHP application on Heroku
2012 coscup - Build your PHP application on Heroku2012 coscup - Build your PHP application on Heroku
2012 coscup - Build your PHP application on Heroku
 
GradleFX
GradleFXGradleFX
GradleFX
 

Kürzlich hochgeladen

+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 

Kürzlich hochgeladen (20)

+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 

Taking Jenkins Pipeline to the Extreme

  • 1. Taking Jenkins Pipeline to the Extreme Yinon Avraham Tech Lead @ eBay Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.com
  • 2. AGENDA ● Why ● What ● How ● WOW! Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
  • 3. WHY Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
  • 4. MICROSERVICES Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference Service Service Service Service SQL DB Service SQL DB Service NoSQL DB HTTPHTTP HTTP HTTP 3rd Party Service
  • 5. WHAT Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
  • 6. IMPROVED CI/CD PROCESS CI: For each active branch: 1. Build 2. Unit Tests 3. Publish Artifacts 4. Integration Tests Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference M F RF D CI M F RF D CI Deploy & TestDeploy & Test Deploy to Production Deploy to Production Repo 2Repo 1 Deploy to Acceptance Environment & Test
  • 7. REQUIREMENTS 1. Configuration as Code 2. Multibranch Coverage 3. Visibility 4. Reuse Job Configuration (D.R.Y) 5. Integration Tests Isolation 6. Self Contained Configuration Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
  • 8. REQUIREMENTS Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
  • 9. HOW Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference
  • 10. CODE REUSE - GLOBAL PIPELINE LIBRARIES Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference Jenkinsfile #!groovy @Library('buildtools@1.x') _ properties([ parameters([forcePublishParam()]), discardOldBuildsProperty() ]) withMavenDockerNode(jdk: 'JDK8') { buildTools -> stage('Setup') { buildTools.init() dir('app') { checkout scm } } dir('app') { mavenBuildTestPublish() } failAsUnstable { withDockerEx { dockerEx -> def kafkaIp stage('Start Sidecars') { kafkaIp = startKafkaSidecar(dockerEx) } stage('Integration Tests') { dir('app') { runIntegrationTests(kafkaIp) } } } } } def call() { stage('Build') { sh 'mvn clean verify –U –B –fae –Dmaven.test.failure.ignore' } stage('Unit Tests') { junit '**/target/surefire-reports/TEST-*.xml' } stage('Publish') { def msg = canDeploy() if (msg == 'ok' || params.FORCE_PUBLISH) { sh 'mvn deploy' } else { echo "Publish skipped, cannot deploy: ${msg}" } } } vars/mavenBuildTestPublish
  • 11. ISOLATION – “SIDECAR” PATTERN Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference Jenkins Master Jenkins Slave Jenkins Slave Kafka Broker Schema Registry Zookeeper kafka sidecar Kafka Broker Schema Registry Zookeeper kafka sidecar
  • 12. ISOLATION – “SIDECAR” PATTERN Docker Extension – Support Docker Compose Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference import com.ebay.tools.DockerEx def call(body) { def dockerEx = new DockerEx(this) try { body(dockerEx) } finally { dockerEx.close() } } vars/withDockerEx def call(dockerEx) { def kafka = dockerEx.compose('kafka', [file: 'buildtools/docker/kafka.yml']) kafka.defaultNetwork.create() def ip = kafka.inspectGateway() echo "Kafka IP: ${ip}" withEnv(["KAFKA_IP=${ip}"]) { kafka.up().ps() } waitForPort host: ip, port: 29092 // Kafka broker waitForEndpoint url: "http://${ip}:8081" // Schema Registry ip } vars/startKafkaSidecar withDockerEx { dockerEx -> def kafkaIp stage('Start Sidecars') { kafkaIp = startKafkaSidecar(dockerEx) } stage('Integration Tests') { dir('app') { runIntegrationTests(kafkaIp) } } } class DockerEx implements Serializable { protected final def script private final ArrayMap compositions = new ArrayMap() DockerEx(script) { this.script = script } DockerExCompose compose(String name, Map config = [:]) { DockerEx dockerEx = this compositions.get(name, { -> new DockerExCompose(docker, name, config) } } void close() { closeAllCompositions() } void closeAllCompositions() { compositions.forEach { _, compose -> try { compose.down() } catch (e) { script.echo "Destroy '${compose.name}' failed: ${e}" } } } } src/com/ebay/tools/DockerEx
  • 13. ISOLATION – “SIDECAR” PATTERN Docker Extension – Support Docker Compose Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference class DockerExCompose implements Serializable { private final DockerEx dockerEx private final def script private final ArrayMap config final String name DockerExCompose(DockerEx dockerEx, String name, Map config = [:]) { this.dockerEx = dockerEx this.script = dockerEx.script this.name = name this.config = config } DockerExCompose up() { script.sh "docker-compose –project-name $name " + "${fileArg()} up -d" this } DockerExCompose down() { script.sh "docker-compose ${fileArg()} down" this } src/com/ebay/tools/DockerExCompose DockerExCompose ps() { script.sh "docker-compose ${fileArg()} ps" this } String inspectGateway() { defaultNetwork.inspectGateway() } DockerExNetwork getDefaultNetwork() { docker.network("${name}_default".toString()) } private String fileArg() { def file = config.get('file') file ? "--file ${file}" : '' } } String inspectGateway() { def res = script.sh(script: "docker network inspect -f " + "'{{range .IPAM.Config}}{{.Gateway}}{{end}}' $name", returnStdout: true) res.trim().split('/')[0].toString() }
  • 14. SELF CONTAINED CONFIGURATION Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference withMavenDockerNode import com.ebay.tools.BuildTools def call(Map args, body) { timestamps { def timeoutArgs = args.timeout ?: [time: 1, unit: 'HOURS'] timeout (timeoutArgs) { def label = 'maven-docker-builder' mavenDockerPodTemplate(label) { node(label) { def buildTools = new BuildTools(this, args) body(buildTools) } } } } } private void mavenDockerPodTemplate(String label, body) { podTemplate( label: label, containers: [ containerTemplate( name: 'jnlp', image: ... )] ... ) { body() } } Jenkinsfile #!groovy @Library('buildtools@1.x') _ properties([ parameters([forcePublishParam()]), discardOldBuildsProperty() ]) ... src/com/ebay/tools/BuildTools class BuildTools implements Serializable { private final def script private final ArrayMap args void init() { gitCloneBuildTools() setJavaHome(args.get('jdk')) printToolsVersion() } private void printToolsVersion() { script.sh script: 'mvn --version', returnStatus: true script.sh script: 'java -version', returnStatus: true script.sh script: 'docker version', returnStatus: true } }
  • 15. TIPS & TRICKS ● Do not load global libraries implicitly by default. This is sometimes redundant and it is not visible ● Do load global libraries explicitly with specific stable development branch, e.g. “1.x”. This way you get fixes and enhancements transparently, but keep the option for “2.x” ● Do treat your global pipeline library as any other library you write (e.g. versioning, testing, etc.) Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference Global Pipeline Library Management
  • 16. TIPS & TRICKS Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference Global Pipeline Library Management - Testing #!groovy @Library('buildtools@1.x') _ import static com.ebay.tools.test.PipelineTestUtils.* withMavenDockerNode { pipelineTests(this) { testSuite('withBuildTools, shEx') { test("withBuildTools - Test build tools with JDK8") { withBuildTools(jdk: 'JDK8') { buildTools -> def result = shEx(script: 'java -version') assertStringContains expected: 'version "1.8.', actual: result.get('err'), message: 'Java version not as expected' assertEquals expected: 0, actual: result.get('status'), message: "Return status not as expected" } } ... } } }
  • 17. TIPS & TRICKS ● Do prototype, test and play using the online script editor ● Do use the “Replay” functionality ● Do echo, echo, echo – write decisions and state to the console ● Trick: interactiveShell Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference Pipeline Script Development and Debugging def call() { timeout(time: 10, unit: 'MINUTES') { echo "[Shell] ***** Starting interactive shell *****" String cmd = '' while (cmd != 'exit') { cmd = input(id: 'cmd', message: 'Command:', parameters: [ [$class: 'TextParameterDefinition', name: 'cmd', description: 'Enter shell command to run, "exit" to stop the shell'] ]) def ret = sh(script: cmd, returnStatus: true) echo "[Shell] Return Code: $ret" } echo "[Shell] Bye!" } }
  • 18. TIPS & TRICKS ● Do organize in stages to reflect your pipeline flow, think visibility ● Do echo, echo, echo (yes, I already wrote it, it’s important) ● Do control the result status to reflect the actual result ● Do write your global library to express your DSL Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference Increase Visibility and Readability
  • 19. Any Questions? THANK YOU! Yinon Avraham yavraham@ebay.com @yinonavraham Copyright @ 2018 JFrog - All rights reserved | juc-il.jfrog.comUser Conference

Hinweis der Redaktion

  1. Questions: Who’s using Jenkins pipeline (i.e. Jenkinsfile)? Who’s using global shared libraries? Who’s using docker in their pipeline scripts?
  2. Some background – what was our trigger to do it
  3. Working with microservices Currently ~15 different services, each has ~9 instances Communicating sync (HTTP REST API) & async (Kafka) Working with various databases (various SQL, neo4j, etc.) Working with 3rd party services Each service is maintained in its own git repository We use git-flow – we have many active branches
  4. What we needed to have in order to achieve our plans
  5. Quite obvious, but still – this is not where we started… We are not there yet In this PPT we focus on the CI part
  6. Requirements: Build configuration changes together with the application code, and without affecting other branches Git-flow – give quick feedback for feature branches Needs to be quick and easy to see what failed and why Many services in many repositories, common build process. Concurrent builds should not affect one another, no need to statically maintain databases for each application / branch … As less manual Jenkins configuration as possible. It should be contained with the build configuration as much as possible. Answers: Simple: Jenkinsfile Simple: Multibranch Pipelines, trigger on push to GitHub Simple: The native Jenkins Pipeline UI is very good: which stage failed, quick access to console output, etc. Focus on: Jenkins Pipeline Shared Libraries Focus on: Use docker-compose to spin up “sidecar” services Focus on: Push as much configuration as possible to the Jenkinsfile (timestamps, parameters, pods, etc.)
  7. Some examples of how we implemented it Some tips and tricks we collected along the way
  8. This is somewhat simplified and hides implementation. Reuse: forcePublishParam, discardOldBuildsProperty DSL: withMavenDockerNode, failAsUnstable, withDockerEx Tip: echo, echo, echo Go to live Jenkins to show how a successful job looks like and how an echoed message looks like…
  9. Jenkins Master – Orchestrates and drives the builds Jenkins Slave – Executes the build steps Kafka “Sidecar” – an ad-hoc composition started per build, controlled by the build, isolated from other builds
  10. withDockerEx – Creates the dockerEx handle, closes it when finished (successfully or not) startKafkaSidecar – Starts the kafka composition, checks it is up, and returns its IP DockerEx keeps all started compositions in order to destroy them implicitly once done
  11. DockerExCompose – Give a nice fluent and familiar DSL. Underline it is just calling the docker-compose CLI. inspectGateway – Using docker network inspection CLI with its built-in formatting capabilities to extract the composition’s network gateway.
  12. Push as much job configuration to the global pipeline script or the project specific script – where it fits Use podTemplate to define the Jenkins slave image you use, instead of Jenkins Configuration Print information on your build environment – it might be quite handy when the build fails… Show example of the console output of printing tools version