Note: There is a followup post available: Please visit From plain Groovy to Jenkins Job DSL: A Quantum Jump.
I've seen lot's of Jenkins build servers overloaded with build jobs of very different projects. Wouldn't it be cool to have a Build Server for every project? That would be a lot of work you say? Stuck with Jenkins 1 because you do not dare to migrate all those important build jobs nobody knows how to configure when they break during migration to Jenkins 2?
There are a lot of build services available but sometimes you have constraints that doesn't allow to build in the wild... In the days of Docker it's easy to fire up a standard Jenkins Image in seconds:
$ docker run -p 8080:8080 jenkins
That's it your fresh empty build server is up and running. Often this is the time where the repetitive work begins: Adding plugins, jobs, ... Don't panic!
This is the point where we started to create our own Jenkins images.
Prepare some ingredients up-front:
* a custom config.xml
(optional)
* a list of plugins we want to use
* deploy keys to access a private GitHub repository
* and a list of initial jobs we want preconfigured
The overall result is the following Dockerfile
:
FROM jenkins:2.19.1
COPY config.xml /var/jenkins_home/
RUN /usr/local/bin/install-plugins.sh git:3.0.0 workflow-aggregator:2.4 docker-custom-build-environment:1.6.5
COPY add-credentials.groovy /var/jenkins_home/init.groovy.d/
COPY create-initial-jobs.groovy /var/jenkins_home/init.groovy.d/
Let's look at the Groovy scripts in more detail as they do the hard work in this setup: add-credentials.groovy
and create-initial-jobs.groovy
.
This groovy script adds the prepared GitHub deploy key to our Jenkins:
import jenkins.model.*
import com.cloudbees.plugins.credentials.*
import com.cloudbees.plugins.credentials.common.*
import com.cloudbees.plugins.credentials.domains.*
import com.cloudbees.jenkins.plugins.sshcredentials.impl.*
import hudson.plugins.sshslaves.*
global_domain = Domain.global()
credentials_store = Jenkins.instance.getExtensionList(
'com.cloudbees.plugins.credentials.SystemCredentialsProvider'
)[0].getStore()
credentials = new BasicSSHUserPrivateKey(
CredentialsScope.GLOBAL,
'planets-homepage_id_rsa',
'planets-homepage_id_rsa',
new BasicSSHUserPrivateKey.DirectEntryPrivateKeySource("""-----BEGIN RSA PRIVATE KEY-----
<GitHub deploy key>
-----END RSA PRIVATE KEY-----"""),
"",
""
)
credentials_store.addCredentials(global_domain, credentials)
With the help of this script we create an initial job:
import jenkins.model.Jenkins
import org.jenkinsci.plugins.workflow.job.WorkflowJob
import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition
import hudson.plugins.git.GitSCM
WorkflowJob job = Jenkins.instance.createProject(WorkflowJob, 'planets-homepage')
def definition = new CpsScmFlowDefinition(new GitSCM('git@github.com:<path-to>/planets-homepage.git'), 'Jenkinsfile')
definition.scm.userRemoteConfigs[0].credentialsId = 'planets-homepage_id_rsa'
job.definition = definition
Within our repository there is a magic Jenkinsfile
containing further instructions how to build/test and deploy our application:
node {
stage 'Checkout' {
checkout scm
}
stage 'Build' {
sh './gradlew build'
}
...
}
With such a setup in place you can get your code reliably to production in minutes...
For more information see Pipeline as Code with Jenkins