3. About Me
Researcher / PhD Student
(Software-based Networks)
2011 - 2016
Core Team Member
2010 - 2013
Server Admin Team Member
since 2011
3
Co-Organizer DevOps Meetup Würzburg
since 2016
5. 5
Agile Development
• Sprints of ~1-4 weeks duration
• Result: Product that can be
shown/given to customer
• Return: Feedback
Image credits: Marekventur,
Wikimedia, CC-BY-SA-3.0
6. 6
Continuous Delivery
• Reduce cycle times (even more)
• “How long does it take to release a one-line change?”
• Potentially deliverable code with every commit
• Automated tests decide about acceptance
• You don’t have to release/deploy it, but you could
à Continuous Deployment: Deploy every successfully
tested commit automatically
7. 7
Pipelines
• Every check-in triggers
pipeline execution
• Feedback to the team in
every stage
• “Bring the pain forward”
• “Fail fast, fail often”
• Minimize execution time
• Always aware of
latest stable release
9. 9
CI/CD Tools
• On-premise
• Jenkins
• Thoughtworks Go
• Gitlab CI
• Pivotal Concourse
• Jetbrains TeamCity
• SaaS
• TravisCI
• CircleCI
• AppVeyor
• Codeship
• Visual Studio Team Services
10. 10
Why (I like) Jenkins
• Established open source project
• On premise installation
• Thousands of plugins
• Integrates with many tools/services
• Tailored to CI/CD
11. 11
History of CI/CD with Jenkins
• Downstream Jobs
• Job A triggers job B triggers job C triggers job D trig...
• If one job fails, fail all
• Build Pipeline View
13. 13
Configuration as Code
• Define jobs/pipelines as code
• Avoid point & click
• In version control
• Can live with the application
• Scales better
• Example: .travis.yml (from TravisCI)
• Similar to GitlabCI
language: php
services:
- redis-server
before_script:
- composer install
script:
- ./bin/phpunit -c …
notifications:
slack:
…
14. 14
Code-driven Approaches in Jenkins
• Jenkins Job Builder
• Python / YAML based, from the OpenStack project
• Job DSL plugin
• Groovy DSL!
(e.g. query Github API and create
jobs for all branches)
• Great thing!
• But creates single jobs
job('my-project-main') {
scm {
git('https://github.com/...')
}
triggers {
scm('H/15 * * * *')
}
publishers {
downstream('my-project-unit')
}
}
16. 16
Jenkins Pipeline Plugins
• Whole suite of plugins (20+), open-sourced a year ago
• Shipped with Jenkins 2.0
• Formerly commercially available by CloudBees, called Workflow
• Define pipeline as code (again Groovy DSL)
stage("Hello") {
...
}
stage("World") {
...
}
20. 20
Pipeline DSL Steps (3)
• Build another job:
• Will not go further into detail J
build("jobname")
build("jobname", wait: false, propagate: false)
build(job: 'jobname', parameters: [
[$class: 'StringParameterValue', name: 'target', value: target]
[$class: 'ListSubversionTagsParameterValue', name: 'release', tag: release],
[$class: 'BooleanParameterValue', name: 'update_composer', value:
update_composer.to_boolean()])
21. 21
Even More Pipeline Steps
• Plugins contribute additional steps
• Steps available in this Jenkins instance via
• Online reference: https://jenkins.io/doc/pipeline/steps/
23. 23
Parameters and Input
• Parametrized build (before build starts) 1
• Input step (during pipeline execution) 2
bonus points for lock, milestone, timeout..
1) see https://st-g.de/2016/12/parametrized-jenkins-pipelines
2) see http://stackoverflow.com/questions/42501553/jenkins-declarative-pipeline-how-to-read-choice-from-input-step
pipeline {
// agent, steps. etc.
parameters {
string(name: 'DEPLOY_ENV', defaultValue: 'TESTING',
description: 'The target environment')
input(message: 'Heyho', parameters: [string(..), ..])
24. 24
Pipeline DSL
• Specify custom environment variables (and access credentials)
• Variables provided by Jenkins
• Control flow (a tiny bit..)
environment {
AWS_ACCESS_KEY_ID = credentials('my-aws-key')
}
sh "echo $AWS_ACCESS_KEY_ID"
sh 'echo $BUILD_NUMBER'
echo env.BUILD_NUMBER
when { branch 'production' { sh 'rm –rf /' } }
25. 25
Full Example Parameterized Build
pipeline {
agent any
parameters {
string(name: 'DEPLOY_ENV', defaultValue: 'TESTING', description: 'Target environment')
choice(name: 'FRUIT', choices: 'applenbanananpizza', description: 'Pick a fruit')
}
stages {
stage('Something') {
steps {
echo "Will deploy to ${params.DEPLOY_ENV}"
writeFile(file: 'fruit.txt', text: params.FRUIT)
echo readFile('fruit.txt')
}
}
}
}
26. 26
Docker
• Run build jobs within Docker containers
• No need to install software on Jenkins master/slave
• Use multiple versions of the same tool
• Containers can be existing ones
or based on Dockerfile
• .. and Kubernetes
agent {
docker {
image 'maven:3-alpine'
}
stages { .. }
}
27. 27
Demo Time!
Picture by annca/ pixabay:
https://pixabay.com/en/popcorn-cinema-ticket-film-1433327/
29. 29
Declarative What?
• What you've seen now is the brand new stuff (pipeline-model-* v1.1)
• Formerly, there were "scripted pipelines"
• Groovy-based DSL
• Real code à real power
• Sometimes: real pain*
• Both approaches officially supported
* includes debugging, failure handling, script security / sandbox, CPS, …
30. 30
Scripted Pipeline Example
node {
stage("Foo") {
def data = new groovy.json.JsonSlurper().parseText(readFile('somefile.txt'))
sh "make ${data.options}"
}
stage("Bar") {
try {
sh "make"
} catch (err) {
slackSend message: "Oh dude, didn't workout. ${err}"
error "Things went wrong"
}
}
if (env.BRANCH_NAME == 'master') {
stage("Bar") {
echo "Deploy!!"
}
}
}
31. 31
Scripted Pipeline Execution
• node step allocates executor slot (“heavyweight executor”)
• As other Jenkins jobs
• Filter node by labels (i.e. node('php7'), node('master'))
• Required for heavy lifting
• Avoid many sequential allocations (slows down pipeline progress)
• Code outside of node
• Flyweight executor
• Running on master, "for free”
• Pipeline execution survives Jenkins restarts (CPS)
32. 32
Pipeline Syntax:
Declarative vs. Scripted
• Beginning
• Executor allocation
• Post-build steps, failure handling
• Flow control
see https://jenkins.io/doc/book/pipeline/syntax/
pipeline { .. } // everything else
agent(docker:'image')
steps { .. }
node('label') { sh .. } // or
docker.image('..').inside{ .. }
post { failure {} always {} } try { sh .. } catch { cry }
when { .. }
script { // groovy script }
// any groovy statement
(node can be used for declarative as well)
33. 33
More on Scripted Pipelines
..in older versions of this talk
https://st-g.de/speaking
35. 35
Pipeline Configuration
• Paste code into job config (fine for testing)
(job type: Pipeline)
• Create pipelines via JobDSL
• Commit it to your repo (job type: Multibranch)
• File called Jenkinsfile
• It evolves with the application
• It is versioned
• Everybody can read (and modify) it
• You can throw away your Jenkins master at any time
36. 36
Multibranch & Organization Folder Plugins
• Scans a complete GitHub/Bitbucket organization for Jenkinsfile
• Triggered by Webhook and/or runs periodically
• Automatically adds pipeline jobs per repo/branch/PR
37. 37
DRY: Jenkins Global Library
• Provides shared functionality available for all jobs
• Loaded from remote Git repos
• Specified in global configuration
or on folder-level
• Specified in Jenkinsfile
@Library("https://github.com/..")
node { deployToProd() }
@Library("mylib@v1.2")
node { deployToProd() }
node { deployToProd() }
38. 38
Snipped Editor & Docs
• Because first steps are hard..
• For scripted and declarative pipelines
• Auto-generated DSL documentation
(Pipeline Syntax → Step Reference)
41. 41
Chef CI/CD at TYPO3.org
• Code that runs the *.typo3.org infrastructure, chef-ci.typo3.org
• Objective: Chef cookbooks
• Server provisioning (installs packages, configures services)
• Code: github.com/TYPO3-cookbooks
42. 42
Many Cookbooks, Many Pipelines
• Scans our GitHub organization TYPO3-cookbooks
• Automatically adds/removes pipelines for branches and pull requests*
• Triggered via Webhooks
• Contents of Jenkinsfile: def pipe = new org.typo3.chefci.v1.Pipeline()
pipe.execute()
* Currently suspicious to arbitrary code execution
43. 43
Jenkins Global Library
• Pipelines implemented in Global Library
TYPO3-infrastructure/jenkins-pipeline-global-library-chefci
44. 44
Parallelize Integration Tests
• Run Test-Kitchen (integration test for Chef cookbooks)
• Run all instances in parallel (by Jenkins)
$ kitchen list
Instance Driver Provisioner [..] Last Action
default-debian-78 Docker ChefZero <Not Created>
default-debian-82 Docker ChefZero <Not Created>
physical-debian-78 Docker ChefZero <Not Created>
physical-debian-82 Docker ChefZero <Not Created>
production-debian-78 Docker ChefZero <Not Created>
production-debian-82 Docker ChefZero <Not Created>
51. 51
Summary
• Finally nice pipelines!
• The way to go with Jenkins
• Many Jenkins plugins already compatible
• Pipeline as code!
• Versioned
• Doesn't mess up Jenkins jobs
• Code sharing
• New UI stuff still freaking broken
• Endless possibilities - can be complex and painful*
• Chained pipelines? Yes, but..
*IMHO still better than YAML
52. 52
Further Reading
• Pipeline Documentation:
https://jenkins.io/doc/book/pipeline/
• Step documentation:
https://jenkins.io/doc/pipeline/steps/
• Pipeline shared libraries:
https://jenkins.io/doc/book/pipeline/shared-libraries/
• Parallel execution:
https://jenkins.io/blog/2016/06/16/parallel-test-executor-plugin/
• Extending pipeline DSL:
https://jenkins.io/blog/2016/04/21/dsl-plugins/
• Controlling the Flow with Stage, Lock, and Milestone:
https://jenkins.io/blog/2016/10/16/stage-lock-milestone/
• TYPO3's Chef CI:
https://chef-ci.typo3.org