Up to this point, the Jenkinsfile
that we have created has grown and provides an overview of some important declarative pipeline concepts, but it does not do a whole lot. In this lab we will explore how pipeline templates, provided by the CloudBees CI Pipeline Template Catalog feature, are able to accelerate your continuous integration by providing ready-to-go, full featured pipelines.
Pipeline Template Catalogs provide version controlled, parameterized templates for Multibranch and stand-alone Pipeline jobs. In this lab we will use a template from a Pipeline Template Catalog to create another Multibranch Pipeline project for your copy of the insurance-frontend
repository. However, the Jenkinsfile
will be pulled from your pipeline-template-catalog
repository instead of from your insurance-frontend
repository. But the source code that the pipeline template executes upon will still be checked out from your insurance-frontend
repository.
Creating a new job from a catalog template is as simple as filling in a few template specific parameters or by adding a simple yaml based job configuration to your controller’s configuration as code bundle. After that, you will have an organization tested Pipeline for the insurance-frontend application with all the same benefits as a non-templatized Multibranch pipeline project. Also, note, that although everyone is using a template from their copy of the pipeline-template-catalog
repository, we could just as easily have everyone use a template from the same repository.
The Repository Owner parameter will match the GitHub Organization that you are using for the workshop; not what is in the screenshot above.
insurance-frontend
repository, creating a Pipeline job for each branch where there is a marker file that matches Dockerfile
(or in this case, the main
branch). template.yaml
file that is stored alongside a Jenkinsfile
within a subfolder of the Pipeline Template Catalog required top-level templates
folder. The name of the subfolder will be used as an internal identifier of the template so it is recommended to keep it all lowercase with no spaces. Navigate to the template.yaml
file under /templates/container-build
in your copy of the pipeline-template-catalog
repository and you will see a file similar to the one below:version: 1
type: pipeline-template
name: Container Build
templateType: MULTIBRANCH
description: Builds a top-level Dockerfile from the specified repository.
parameters:
- name: repoOwner
type: string
displayName: Repository Owner
defaultValue: REPLACE_GITHUB_ORG
- name: repository
type: string
displayName: Repository
defaultValue: insurance-frontend
- name: githubCredentialId
displayName: GitHub Credential ID
type: CREDENTIALS
defaultValue: cloudbees-ci-pipeline-workshop-github-app
multibranch:
branchSource:
github:
id: container-image-build
credentialsId: ${githubCredentialId}
repoOwner: ${repoOwner}
repository: ${repository}
traits:
- gitHubBranchDiscovery:
strategyId: 1
- gitHubPullRequestDiscovery:
strategyId: 1
markerFile: Dockerfile
REPLACE_GITHUB_ORG
defaultValue
for the repoOwner
parameter has been replaced with the name of your workshop GitHub Organization in your copy of the template.yaml
file for your container-build
template. Note also that the templateType
is MULTIBRANCH
and there is a markerFile
configured with the value of Dockerfile
.stages
are executed for the main
branch job. Navigate to the Jenkinsfile
in the same container-build
subfolder (under the templates
folder) of your copy of the pipeline-template-catalog
repository, and you will discover why. The contents should match the screenshot below:
Some of the highlights include:
agent none
as we don’t want to spin up an agent if the when
conditions are not satisfied.skipDefaultCheckout
option is set to true
to disable the automatic checkout of source code in every Declarative Pipeline stage
, since we only need to checkout the source code in one stage
.stages
of the pipeline, even nested stages
.when
condition is defined that will only allow the Staging PR nested stages
to be executed when the branch
being processed is a GitHub pull request. This is why no stages
were executed for the main
branch.containerBuildPushGeneric
Pipeline Shared Library global variable that provides a common, repeatable method for building and pushing Docker images. (In this case we are building and pushing container images with a tool called Kaniko which allows building and pushing container images from a Kubernetes pod
without Docker installed.)checkout scm
is called so the containerBuildPushGeneric
global variable step will have access to the Dockerfile
and application code of your insurance-frontend
repository. We must explicitly call this as we disabled the Declarative Pipeline default checkout in the global options
block above.insurance-frontend
repository. Navigate to the main
branch of your copy of the insurance-frontend
repository and click on the Jenkinsfile
.Jenkinsfile
since we will now be using the Jenkinsfile
from the Container Build catalog template. Click on the trashcan icon at the top of the file, again ensuring that you are on the main
branch. Dockerfile
that will build the insurance-frontend
application from the source code checked out from your copy of the insurance-frontend
repository and then creates a runtime container image that is pushed to a Google Cloud Artifact Registry via the containerBuildPushGeneric
Pipeline Shared Library global variable step. IMPORTANT: Do not merge the pull request!In this section we are going to provide a brief overview of CloudBees Previews - a standalone feature of CloudBees CI that is currently in preview. Although this is not Jenkins pipeline specific, it does allows us to easily provide preview environments for a GitHub pull request without any additional pipeline code. In previous versions of this workshop we used the following Jenkins pipeline shared library step to providing a staging environment for GitHub pull requests:
def call(String name,
String imageTag,
String namespace = "staging",
Closure body) {
def label = "helm-${UUID.randomUUID().toString()}"
def podYaml = libraryResource 'podtemplates/helm.yml'
podTemplate(name: 'helm', inheritFrom: 'default-jnlp', label: label, yaml: podYaml, podRetention: never(), activeDeadlineSeconds:1) {
node(label) {
body()
stagingUrl = "https://${name}.${env.DEPLOYMENT_ENV}.workshop.cb-sa.io"
gitHubDeploy(REPO_OWNER, REPO_NAME, "", "staging", GITHUB_CREDENTIAL_ID, "true", "false")
env.NAME=name
env.IMAGE_TAG=imageTag
env.NAMESPACE=namespace
container('helm') {
withCredentials([string(credentialsId: 'fm-key', variable: 'FM_KEY')]) {
sh '''
helm upgrade --install -f ./chart/values.yaml --set image.tag=$IMAGE_TAG --set fmToken=$FM_KEY --namespace=$NAMESPACE $NAME ./chart
'''
}
}
gitHubDeployStatus(REPO_OWNER, REPO_NAME, stagingUrl, 'success', GITHUB_CREDENTIAL_ID)
//only add comment for PRs - CHANGE_ID isn't populated for commits to regular branches
if (env.CHANGE_ID) {
def config = [message:"${env.DEPLOYMENT_ENV} environment deloyed by CloudBees CI and is available at: ${stagingUrl}"]
gitHubComment(config)
}
}
}
}
In addition to the additional pipeline code, we also had to manage the configuration and cleanup of environments in the Kubernetes cluster we are using for the workshop. CloudBees Previews eliminates the need for both.
insurance-frontend
repository. Make sure you are on the Conversation tab, scroll down to the comments, enter /preview and click the Comment button.