supercharged configuration as code · regenerate from existing job name import jenkins.model.* !...

24
Supercharged Configuration As Code Bulk Updates with Job DSL and System Groovy

Upload: others

Post on 23-Sep-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Supercharged Configuration As Code

Bulk Updates with Job DSL and System Groovy

Page 2: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Who Am I

• Alan Beale

Build Engineer @ Chicago Trading Company

!

Any opinions expressed are my own and do not represent the opinions of my employer

Page 3: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Observations about build jobs

• Jobs Change over Time

• Most jobs are like other jobs

Page 4: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Jobs Change Over Time

• Correctness Changes

• Bug Fixes

• Complexity Increase

Page 5: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Most Jobs are Similar

• Small number of themes with structured variation

Page 6: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

How do these observation help?

• Job DSL enables us to using coding techniques to create job configurations

• System groovy scripts enable use to automate repeated calls to jobs

Page 7: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Player Piano

Our metaphor for bulk job regeneration

Page 8: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

The Piano Roll

• Controls the sound of the piano

• Orchestrates the automation of job recreation

Page 9: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Job DSL for gradle buildjob {

name "git-gradle-simple-build"

scm {

git('/Users/alanbeale/sandbox/samples/java/basic',

'*/master' )

}

steps {

gradle ( "build", null, true )

}

}

Page 10: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Evolution Examplejob {

name "git-gradle-build-with-worspace-option"

scm {

git('/Users/alanbeale/sandbox/samples/java/basic',

‘*/master')

}

steps {

gradle ( "build", null, true

){ node -> //hudson.plugins.gradle.Gradle

node/useWorkspaceAsHome(true)

}

}

}

Page 11: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Add Gerrit Triggerjob {

! name "git-gradle-build-with-gerrit-trigger"

! scm {

git(

'/Users/alanbeale/sandbox/samples/java/basic',

'$GERRIT_BRANCH'

){ node ->

node/extensions {

'hudson.plugins.git.extensions.impl.BuildChooserSetting'{

buildChooser(buildChooserAttrs){

separator('#')

}

}

}

def remoteConfig = node/userRemoteConfigs/

'hudson.plugins.git.UserRemoteConfig'

remoteConfig << refspec('$GERRIT_REFSPEC')

}

! }

Page 12: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

continued triggers { gerrit { events { PatchsetCreated DraftPublished } project( "plain: /Users/alanbeale/sandbox/samples/java/basic", 'ant:**' ) } } steps { gradle ("build", null, true) { node -> //hudson.plugins.gradle.Gradle node/useWorkspaceAsHome(true) } } }

Page 13: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Repeated elements

• Job Name

• Git URL

• Gerrit Trigger Project

Page 14: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Towards Job Factory

• Factor out common operations

• Parameterize calling Job DSL

Page 15: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Create Utility class

• jobdsl.JobUtilities methods

• setupGradleGerritJobName() • setupGerritScm() • setupGerritTrigger() • setupGradleBuild()

Page 16: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

generator job DSLjob {

name "gradle-gerrit-job-generator"

parameters {

stringParam("PROJECT_NAME","sample/java/library")

}

steps {

dsl {

removeAction('IGNORE')

ignoreExisting(false)

text('''

import jobdsl.JobUtilities

import javaposse.jobdsl.dsl.Job

def gerritProjectName= "${PROJECT_NAME}"

def simpleJavaVerifyJob = job {}

JobUtilities.setupGradleGerritJobName(simpleJavaVerifyJob, gerritProjectName)

JobUtilities.setupGerritScm( simpleJavaVerifyJob, gerritProjectName)

JobUtilities.setupGerritTrigger( simpleJavaVerifyJob, gerritProjectName)

JobUtilities.setupGradleBuild(simpleJavaVerifyJob)

''')

Page 17: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Part 2 : System Groovy

Page 18: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Regeneration scriptimport jenkins.model.* !import hudson.model.* !def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator' def jobGenerator = jenkins.getItem(jobGeneratorName) def projectParamName ='PROJECT_NAME' def projectParamValue=‘sample/java/library' !if(jobGenerator){ boolean buildQueued = jobGenerator.scheduleBuild( 5, new Cause.UserIdCause(), new ParametersAction( new StringParameterValue(projectParamName, projectParamValue) ) ) }

!

Page 19: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Regenerate from existing job nameimport jenkins.model.* !import hudson.model.* !def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator' def jobGenerator = jenkins.getItem(jobGeneratorName) def projectParamName ='PROJECT_NAME' def jobs = jenkins.getItems() !def gerritJobs = jobs.findAll { job -> job.name.endsWith('gradle-gerrit') } !def projectNames =gerritJobs.collect { item -> item.triggers.values().find { it.class.simpleName =='GerritTrigger' }. gerritProjects[0].pattern } !if(jobGenerator){ projectNames.each { projectName -> boolean buildQueued = jobGenerator.scheduleBuild( 5, new Cause.UserIdCause(), new ParametersAction( new StringParameterValue( projectParamName,projectName) ) ) } }

Page 20: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Example of Job Themes

• Continuos Integration Jobs • Gerrit Verification Jobs • Release Jobs • Privileged SCM Task Automation

Page 21: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Summary

• Job DSL enables precise control

• Define parameterized Job Generator (the piano)

Page 22: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Summary

• System Groovy Jobs

• automates calling job generator in bulk

(piano roll)

Page 23: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator
Page 24: Supercharged Configuration As Code · Regenerate from existing job name import jenkins.model.* ! import hudson.model.* ! def jenkins = jenkins.model.Jenkins.instance def jobGeneratorName='gradle-gerrit-job-generator

Thank you

• Source Code at https://github.com/bealeaj1214/jenkins-juc-job-dsl-bulk-regeneration