DevEx Technical Test
DevEx Technical Test
Objective: Create a presentation following the below business objectives and guidelines.
Topic: Design a CI/CD pipeline that illustrates all the steps needed to build, test and deploy a Java or Python application. Make sure it is safe and
secure for production operation, to the extent that you are comfortable.
2
CI/CD pipeline that illustrates all the steps needed to build, test and deploy a Java application .
We need source code (i.e java code) in any of the SCM tools such as GitHub or GitLab etc
3
We need to install required Jenkins plugins such as GitHub Integration, Maven Integration , Docker
Commons, SonarQube Scanner for Jenkins, Kubernetes, Kubernetes CLI
We will get multiple items types (i.e. free style,pipeline,multi branch pipeline etc)
Select pipeline option then we need to provide details like GitHub repository url and credentials
As mentioned in slide5
We will write Jenkins file which will have the all stages to build , test and deploy the java
application . Example in slides 6 to 9.
We will create a IAM role and will give required permissions and will attach this role to Jenkins
server (or you can use access and secret key to authenticate AWS but this is not secure)
We will write docker file which is used to create a docker image as shown in slide 10
We will write deployment and service files to deploy docker image into k8s (slides 11 and 12)
4
5
pipeline {
agent any
triggers {
pollSCM '* * * * *'
}
tools {
maven "mvn"
jdk "java11"
}
environment{
scannerHome = tool 'SonarQube'
registry = "9402536.dkr.ecr.us-east-2.amazonaws.com/tide"
tag = "${BUILD_NUMBER}“
}
stages {
stage ('Run entire Build'){
stages{
stage('MVN package Build') {
steps {
sh 'mvn clean install'
}
}
stage('jacoco report coverage'){
steps{
jacoco()
}
}
6
stage('Junit Test execution and report generation') {
steps{
sh 'mvn test'
}
post{
always{
junit '**/target/surefire-reports/TEST-*.xml'
}
}
}
stage('build & SonarQube analysis') {
steps {
withSonarQubeEnv('SonarQube') {
sh "${scannerHome}/bin/sonar-scanner \
-Dsonar.projectKey=clp-service-staging \
-Dsonar.projectName=tide-service-staging \
-Dsonar.projectVersion=1.0.0 \
-Dsonar.sources=src \
-Dsonar.java.binaries=target/classes \
-Dsonar.sourceEncoding=UTF-8 \
-Dsonar.language=java \
-Dsonar.junit.reportPaths=target/surefire-reports \
-Dsonar.surefire.reportsPath=target/surefire-reports \
-Dsonar.coverage.jacoco.xmlReportPaths=target/jacoco-ut/jacoco.xml \
-Dsonar.java.coveragePlugin=jacoco \
-Dsonar.exclusions=**src/test"
}
}
}
7
stage('Build Docker Image') {
steps {
sh 'docker build -t $registry:latest_${BUILD_NUMBER} .'
}
}
stage('Push to Amazon ECR'){
steps {
sh 'aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin
9402536.dkr.ecr.us-east-2.amazonaws.com'
sh 'docker push $registry:latest_${BUILD_NUMBER}'
}
}
stage('Deployment Approval') {
agent none
steps {
emailext mimeType: 'text/html',
subject: "[Jenkins]${currentBuild.fullDisplayName}",
to: “[email protected]",
body: '''Please go to console output of ${BUILD_URL}input to approve or Reject.<br>'''
script {
def userinput = input id: 'Deploy', message: 'Deploy to staging?', submitter: ‘gopig'
}
}
}
8
stage('Apply Kubernetes files') {
steps {
withKubeConfig([credentialsId: 'Bridge-Token', serverUrl:
'https://A1010D6DDB72BC506A25531AA5E69022.gr7.us-east-2.eks.amazonaws.com']) {
sh 'curl -LO "https://storage.googleapis.com/kubernetes-release/release/v1.25.5/bin/linux/
amd64/kubectl"'
sh 'chmod u+x ./kubectl'
sh 'sed -i "s/BUILD_NUMBER/$tag/g" deployment.yaml'
sh './kubectl apply -f deployment.yaml'
}
}
}
}
post{
always{
emailext attachLog: 'true', body: '', subject: '$PROJECT_NAME - Build #
$BUILD_NUMBER - $BUILD_STATUS!', to: ‘[email protected]'
}
}
}
}
}
9
Dockerfile
FROM openjdk:11
EXPOSE 8084
WORKDIR /opt/tideplan
10
apiVersion: apps/v1
kind: Deployment
metadata:
name: tide-dev
namespace: development
labels:
app: tide-dev
tier: backend
spec:
selector:
matchLabels:
app: tide-dev
service: tide-svc-dev
replicas: 2
template:
metadata:
labels:
app: tide-dev
service: tide-svc-dev
spec:
containers:
- name: tide-dev
image: 9402536.dkr.ecr.us-east-2.amazonaws.com/tide:latest_BUILD_NUMBER
imagePullPolicy: Always
ports:
- name: http
containerPort: 8084
protocol: TCP
nodeSelector: 11
Environment: tide-dev
---
apiVersion: v1
kind: Service
metadata:
name: tide-svc-dev
namespace: development
labels:
service: tide-svc-dev
spec:
type: NodePort
selector:
app: tide-dev
service: tide-svc-dev
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
- port: 8084
targetPort: 8084
protocol: TCP
name: http
12