CI/CD as code
at drivetime
A look into how and why we do builds at DriveTime
using DSL plugin and a custom build framework
What is CI/CD?
Summary:
- Code goes into SCM
- ???
- Applications run in prod
Specifics:
- Builds
- Tests (Unit, Integration, e2e)
- Reporting
- Deployments
- Preferably all automated (tiny robots)
Problems associated
with CI/CD
- Things that should be easy are hard
- No consistencies
- No disaster recovery
- No way to rollback
- No way to share work
- No way to test work
- No way to migrate
- Nice-to-have's are rarely done
CI/CD as code fixes all this
- Things that should be easy are hard
Changing from tfs to github can be 1 line of code
- No consistencies,
No way to share work
Reusable base classes, interfaces, methods and frameworks solve this
- No disaster recovery,
No way to rollback
SCM does this for free!
CI/CD as code fixes all this
- No way to test work
We unit test code all the time
-
No way to migrate
Migrating code can be done quickly: abstractions, testing, and code re-use enables this
- Nice-to-have's are rarely done
Do it once in a method or base class and
now everyone can use it regardless of how difficult it once was
now everyone can use it regardless of how difficult it once was
How do you get CI/CD as code?
First a little bit about how Jenkins works
Next, Jenkins DSL plugin! It's all groovy, man

How does the DSL plugin work?
Jenkins job: Seed build

Comes from the DSL plugin, it runs groovy code that creates:
- Folders
- Views
- Jobs
- Other seed builds
It can be confusing
Groovy code runs from your seed job
That code creates jobs by generating XML
There isn't any code running when your builds run
Misc things that DSL does
From your seed build

From your generated build

It's very flexible


Additional flexibility

You can ignore, disable or delete removed items
and we typically disable
This doesn't look very reusable
job("Your folder/example build name") {
scm {
git {
remote {
github repo
refspec '+refs/pull/*:refs/remotes/origin/pr/*'
}
branch '${sha1}'
} }
triggers {
githubPullRequest {
admin 'sheehan'
triggerPhrase 'OK to test'
onlyTriggerPhrase true
} }
steps {
grails {
useWrapper true
targets(['test-app', 'war'])
} } }
That's because it's not
This is all code, we can do whatever we want
new SeedBuildDefinition(
jobName: 'OnlineAutoSales Seed',
scmConnector: new GitHubConnector(repoName: 'Builds.OnlineAutoSales'),
groovyFileToRun: 'jobs.groovy'
),
new SeedBuildDefinition(
jobName: 'DevOps Seed',
scmConnector: new GitHubConnector(repoName: 'Builds.DevOps'),
groovyFileToRun: 'devops_seed.groovy'
),
new SeedBuildDefinition(
jobName: 'BPM Seed',
scmConnector: new GitHubConnector(repoName: 'Builds.BPM'),
groovyFileToRun: 'jobs.groovy'
)
Different ways of doing stuff
Generic
new NpmPackagePublisher(
jobName: 'UX/UI.Components',
descriptionText: readFileFromWorkspace('dt-components/description.html'),
scmConnector: new GitHubConnector(
repoName: 'Ui.Components',
buildPullRequests: true),
failedBuildEmailAddresses: AllYourEmailsInAVariable,
azurePublishProfiles: Arrays.asList(
'dt-components/drivetime-components-dev.PublishSettings')
),
Specific
new FinancingBuild(
jobName: rootLocation + '/Financing/Financing-Main'
)
Some additional generic stuff
How you can get started
- Watch a couple of videos if you want (33m and 34m)
- Read the documentation
- Create your own seed in the root seed
- Create your own job from your seed
- If it's generic, move it up to the root
Anything else I should know?
Yeah... we're doing this a little POC'y
But it will get better with time!
And we'll add tests!
Thanks for coming!!
CI/CD as Code at DriveTime
By Allen Rice
CI/CD as Code at DriveTime
- 950