Jenkinsfile examples
A sample Jenkinsfile
file#
Examples
Jenkinsfile Pipeline Example 1
#!/usr/bin/env groovy
pipeline {
agent { label "linux && docker" }
environment {
AWS_ACCESS_KEY_ID = "${AWS_DEPLOY_USER_CREDENTIALS_USR}"
AWS_SECRET_ACCESS_KEY = "${AWS_DEPLOY_USER_CREDENTIALS_PSW}"
CONTAINER_REGISTERY = "${AWS_ACCOUNT_ID}"+".dkr.ecr."+"${AWS_DEFAULT_REGION}"+".amazonaws.com"
CONTAINER_REPO_NAME = "${APPLICATION_NAME}"
CONTAINER_IMAGE_TAG = "${GIT_COMMIT}"
CONTAINER_IMAGE_NAME = "${CONTAINER_REGISTERY}"+"/"+"${CONTAINER_REPO_NAME}"+":"+"${CONTAINER_IMAGE_NAME_TAG}"
CONTAINER_BUILD_TOOL = "docker"
}
options {
timeout(time: 20, unit: 'MINUTES')
}
stages {
stage('Pre-build') {
steps {
sh "aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | ${CONTAINER_BUILD_TOOL} login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
}
}
stage('Build container image') {
steps {
sh """
${CONTAINER_BUILD_TOOL} build --rm=true -t ${CONTAINER_IMAGE_NAME} .
"""
}
}
stage('Push container image to registery') {
steps {
sh """
${CONTAINER_BUILD_TOOL} push ${CONTAINER_IMAGE_NAME}
"""
}
}
stage("Deploy") {
steps {
node ("") {
script(){
// https://www.jenkins.io/doc/pipeline/steps/ssh-steps/#sshscript-ssh-steps-sshscript-execute-scriptfile-on-remote-node
withCredentials([sshUserPrivateKey(credentialsId: 'deploy_user', keyFileVariable: 'identity', passphraseVariable: '', usernameVariable: 'userName')]) {
def server = [:]
server.name = "staging-server"
server.host = "x.x.x.x"
server.allowAnyHosts = true
server.user = userName
server.identityFile = identity
sshCommand remote: server, command: "aws ecr get-login-password | docker login --username AWS --password-stdin ${CONTAINER_REGISTERY}"
sshCommand remote: server, command: "docker pull ${CONTAINER_IMAGE_NAME}"
sshCommand remote: server, command: "docker stop driverfly-backend || true"
sshCommand remote: server, command: "docker rm driverfly-backend || true"
sshCommand remote: server, command: "docker run -d -P --name driverfly-backend --restart always ${CONTAINER_IMAGE_NAME}"
}
}
}
}
}
}
post {
failure {
// updateGitlabCommitStatus name: 'build', state: 'failed'
slackSend(message: "Build has failed.")
slackSend(message: "${BUILD_URL}console", sendAsText: true)
}
success {
// updateGitlabCommitStatus name: 'build', state: 'success'
slackSend(message: "Build has run successfully.")
slackSend(message: "${BUILD_URL}console", sendAsText: true)
}
always {
// updateGitlabCommitStatus name: 'build', state: 'success'
slackSend(message: "Build has run successfully.")
slackSend(message: "${BUILD_URL}console", sendAsText: true)
}
}
}
Jenkinsfile Pipeline Example 2
#!/usr/bin/env groovy
@Library('jenkins-global-pipeline-libraries') _
// Jenkinsfile
VERSION = "0.0.7"
pipeline {
agent { label "linux && k8s-client" }
options {
timestamps()
timeout(time: 20, unit: 'MINUTES')
skipStagesAfterUnstable()
buildDiscarder(logRotator(numToKeepStr:'10'))
}
environment {
AWS_DEPLOY_USER_CREDENTIALS = credentials ('AWS_deploy_user')
AWS_ACCESS_KEY_ID = "${AWS_DEPLOY_USER_CREDENTIALS_USR}"
AWS_SECRET_ACCESS_KEY = "${AWS_DEPLOY_USER_CREDENTIALS_PSW}"
AWS_IMAGE_PULL_SECRET_NAME = "aws-image-pull-secret"
ENVIRONMENT = "staging"
KUBECONFIG_DEVELOPMENT = credentials ('KUBECONFIG_DEVELOPMENT')
KUBECONFIG_STAGING = credentials ('KUBECONFIG_STAGING')
KUBECONFIG_PRODUCTION = credentials ('KUBECONFIG_PRODUCTION')
KUBECONFIG_FILE_NAME = GET_KUBECONFIG_FILE_NAME_BASED_ON_ENVIRONMENT("${ENVIRONMENT}")
KUBE_NAMESPACE = GET_KUBE_NAMESPACE_BASED_ON_ENVIRONMENT("${ENVIRONMENT}")
CONTAINER_REPO_NAME = "${APPLICATION_NAME}"
GIT_COMMIT_SHORT = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()
CONTAINER_IMAGE_TAG = "${GIT_COMMIT_SHORT}"
CONTAINER_IMAGE_NAME = "${CONTAINER_REGISTERY}"+"/"+"${CONTAINER_REPO_NAME}"+":"+"${CONTAINER_IMAGE_TAG}"
KUBE_DEPLOYMENT_TEMPLATE = credentials ('KUBE_DEPLOYMENT_TEMPLATE')
KUBE_SERVICE_TEMPLATE = credentials ('KUBE_SERVICE_TEMPLATE');
KUBE_CONFIGMAP_TEMPLATE = credentials ("KUBE_CONFIGMAP_TEMPLATE_${APPLICATION_NAME}_${ENVIRONMENT}");
KUBE_INGRESS_TEMPLATE = credentials ('KUBE_INGRESS_TEMPLATE');
KUBE_HPA_TEMPLATE = credentials ('KUBE_HPA_TEMPLATE');
KUBE_VPA_TEMPLATE = credentials ('KUBE_VPA_TEMPLATE');
}
stages {
stage ('Env check') {
steps {
sh "printenv"
}
}
stage ('Start') {
steps {
sendNotifications 'STARTED'
}
}
stage ('SCM') {
steps {
script{
checkout scm
}
}
}
stage ('Container repository authentication') {
steps {
sh 'aws ecr get-login-password --region $AWS_DEFAULT_REGION | $CONTAINER_BUILD_TOOL login --username AWS --password-stdin $CONTAINER_REGISTERY'
}
}
stage ('Build container image') {
steps {
sh """
${env.CONTAINER_BUILD_TOOL} build --rm=true -t ${CONTAINER_IMAGE_NAME} .
"""
}
}
stage ('Push container image to registery') {
steps {
sh """
${env.CONTAINER_BUILD_TOOL} push ${CONTAINER_IMAGE_NAME}
"""
}
}
stage ("Deploy to k8s cluster") {
steps {
sh '''
#!/usr/bin/env bash
set -vx
mv $KUBECONFIG_FILE_NAME ~/.kube/config
KUBECONFIG="~/.kube/config"
TOKEN=$(aws ecr get-login-password --region $AWS_DEFAULT_REGION)
kubectl get secrets $AWS_IMAGE_PULL_SECRET_NAME && kubectl --insecure-skip-tls-verify=true delete secret --ignore-not-found $AWS_IMAGE_PULL_SECRET_NAME
kubectl get secrets $AWS_IMAGE_PULL_SECRET_NAME || kubectl --insecure-skip-tls-verify=true create secret docker-registry $AWS_IMAGE_PULL_SECRET_NAME \
--docker-server=$CONTAINER_REGISTERY \
--docker-username=AWS \
--docker-password="${TOKEN}" \
--docker-email="example@example.com" && kubectl --insecure-skip-tls-verify=true patch serviceaccount default -p '{"imagePullSecrets":[{"name":"'$AWS_IMAGE_PULL_SECRET_NAME'"}]}'
# Prepare k8s manifests
# Replace variables with values from environment
FILENAME="svc.yaml"
envsubst < $KUBE_SERVICE_TEMPLATE > $FILENAME
# Check if there is a difference between the manifest and the current state of the cluster
set +e
kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE diff -f $FILENAME
SVC_DIFF=$?
set -e
# Apply manifest
kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE --wait=true apply -f $FILENAME
# Replace variables with values from environment
FILENAME="ingress.yaml"
envsubst < $KUBE_INGRESS_TEMPLATE > $FILENAME
# Check if there is a difference between the manifest and the current state of the cluster
set +e
kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE diff -f $FILENAME
INGRESS_DIFF=$?
set -e
# Apply manifest
kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE --wait=true apply -f $FILENAME
# Replace variables with values from environment
FILENAME="configmap.yaml"
envsubst < $KUBE_CONFIGMAP_TEMPLATE > $FILENAME
# Check if there is a difference between the manifest and the current state of the cluster
set +e
kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE diff -f $FILENAME
CONFIGMAP_DIFF=$?
set -e
# Apply manifest
kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE --wait=true apply -f $FILENAME
# Replace variables with values from environment
FILENAME="deployment.yaml"
envsubst < $KUBE_DEPLOYMENT_TEMPLATE > $FILENAME
# Check if there is a difference between the manifest and the current state of the cluster
set +e
kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE diff -f $FILENAME
DEPLOYMENT_DIFF=$?
set -e
# Apply manifest
kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE --wait=true apply -f $FILENAME
# Replace variables with values from environment
FILENAME="hpa.yaml"
envsubst < $KUBE_HPA_TEMPLATE > $FILENAME
# Check if there is a difference between the manifest and the current state of the cluster
set +e
kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE diff -f $FILENAME
HPA_DIFF=$?
set -e
# Apply manifest
kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE --wait=true apply -f $FILENAME
# # Replace variables with values from environment
# FILENAME="vpa.yaml"
# envsubst < $KUBE_VPA_TEMPLATE > $FILENAME
# # Check if there is a difference between the manifest and the current state of the cluster
# set +e
# kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE diff -f $FILENAME
# VPA_DIFF=$?
# set -e
# # Apply manifest
# kubectl --insecure-skip-tls-verify=true -n $KUBE_NAMESPACE --wait=true apply -f $FILENAME
if [ $SVC_DIFF -eq 0 ] && [ $INGRESS_DIFF -eq 0 ] && [ $CONFIGMAP_DIFF -eq 0 ] && [ $DEPLOYMENT_DIFF -eq 0 ]; then
echo "No changes detected in the cluster"
else
echo "Changes detected in the cluster"
fi
# Check both deployment and configmap changes, trigger a rolling update if there is a change in configmap and no change in deployment.
if [ $DEPLOYMENT_DIFF -eq 0 ] && [ $CONFIGMAP_DIFF -ne 0]; then
echo "Configmap changed but deployment hasn't. Applying configmap, and trigger a rolling update."
kubectl rollout restart deployment/${APPLICATION_NAME}
fi
# Cleanup: Remove temporary files
rm deployment.yaml || true
rm svc.yaml || true
rm ingress.yaml || true
rm configmap.yaml || true
rm hpa.yaml || true
rm vpa.yaml || true
'''
}
}
}
post {
always {
// TODO: Get more detail if there is a failure, we can upload to Slack
sendNotifications "${currentBuild.result}"
}
}
}
def GET_KUBECONFIG_FILE_NAME_BASED_ON_ENVIRONMENT(String ENVIRONMENT) {
if(ENVIRONMENT.equals("development")) {
return "$KUBECONFIG_DEVELOPMENT";
} else if (ENVIRONMENT.equals("staging")) {
return "$KUBECONFIG_STAGING";
} else if (ENVIRONMENT.equals("production")) {
return "$KUBECONFIG_PRODUCTION";
} else {
return 0;
}
}
def GET_KUBE_NAMESPACE_BASED_ON_ENVIRONMENT(String ENVIRONMENT) {
if(ENVIRONMENT.equals("development")) {
return "default";
} else if (ENVIRONMENT.equals("staging")) {
return "default";
} else if (ENVIRONMENT.equals("production")) {
return "default";
} else {
return 0;
}
}
References & further reading#
Last update:
July 21, 2022
Created: July 13, 2022
Created: July 13, 2022