One-Click Jenkins Setup

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