Bom, hoje vamos conversar sobre jenkins e devops, vamos montar uma esteira (pipeline) utilizando os dois recursos do jenkins pipeline e free style, dentro do nosso pipeline vamos subir nossa imagem docker, puxar o código de um repositório github, realizar os testes utilizando o selenium, sonarqube, para este ambiente vamos utilizar o maven para compilação, tomcat será o nosso servidor web.
1.0 - configurar o ambiente, neste cenário teremos 2 ambientes o de teste e de produção vamos utilizar o contêiner (docker), e o docker-compose como orquestrador, logo abaixo nosso arquivo docker-compose.yml com as configurações do ambiente, basta salvar o arquivo na pasta e utilizar o comando docker up para subir o ambiente.
1.1 - instalar o chrome e o driver do selenium deve ser igual à versão instalada do chrome
1.2 - instalar o java SDK,e adicionar o SDK a PATH como variável do ambiente
1.3 - baixar e instalar MVN(Maven), e adicionar PATH como variável do ambiente
1.4 - subir o servidor tomcat e do jenkins
1.5 – subir servidor do ambiente de teste com as configurações do docker-compose
version: "3"
services:
pg-tasks:
container_name: pg-tasks
image: postgres:9.6
ports:
- 5433:5432
environment:
- POSTGRES_DB=tasks
- POSTGRES_PASSWORD=password
sonarqube:
container_name: sonar
image: sonarqube:7.9.2-community
ports:
- "9000:9000"
networks:
- sonarnet
environment:
- sonar.jdbc.url=jdbc:postgresql://pg-sonar:5432/sonar
depends_on:
- pg-sonar
volumes:
- sonarqube_conf:/opt/sonarqube/conf
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_bundled-plugins:/opt/sonarqube/lib/bundled-plugins
pg-sonar:
container_name: pg-sonar
image: postgres:9.6
networks:
- sonarnet
environment:
- POSTGRES_USER=sonar
- POSTGRES_PASSWORD=sonar
volumes:
- postgresql:/var/lib/postgresql
- postgresql_data:/var/lib/postgresql/data
selenium-hub:
image: selenium/hub:3.141.59-zinc
container_name: selenium-hub
networks:
- seleniumGrid
ports:
- "4444:4444"
chrome:
image: selenium/node-chrome:3.141.59-zinc
container_name: Chrome-1
networks:
- seleniumGrid
depends_on:
- selenium-hub
environment:
- HUB_HOST=selenium-hub
- HUB_PORT=4444
- NODE_MAX_INSTANCES=2
- NODE_MAX_SESSIONS=2
chrome2:
image: selenium/node-chrome:3.141.59-zinc
container_name: Chrome-2
networks:
- seleniumGrid
depends_on:
- selenium-hub
environment:
- HUB_HOST=selenium-hub
- HUB_PORT=4444
- NODE_MAX_INSTANCES=2
- NODE_MAX_SESSIONS=2
networks:
sonarnet:
seleniumGrid:
volumes:
sonarqube_conf:
sonarqube_data:
sonarqube_extensions:
sonarqube_bundled-plugins:
postgresql:
postgresql_data:
sonarqube:
container_name: sonar
image: sonarqube:7.9.2-community
ports:
- "9000:9000"
networks:
- sonarnet
environment:
- sonar.jdbc.url=jdbc:postgresql://pg-sonar:5432/sonar
depends_on:
- pg-sonar
volumes:
- sonarqube_conf:/opt/sonarqube/conf
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_bundled-plugins:/opt/sonarqube/lib/bundled-plugins
pg-sonar:
container_name: pg-sonar
image: postgres:9.6
networks:
- sonarnet
environment:
- POSTGRES_USER=sonar
- POSTGRES_PASSWORD=sonar
volumes:
- postgresql:/var/lib/postgresql
- postgresql_data:/var/lib/postgresql/data
networks:
sonarnet:
volumes:
sonarqube_conf:
sonarqube_data:
sonarqube_extensions:
sonarqube_bundled-plugins:
postgresql:
postgresql_data:
2.0 – iniciando os trabalhos com o jobs tipo free style como na imagem abaixo:
2.1 – inserir credencias e autenticação do git, sonarqube e tomcat.
3.0 – vamos realizar o nosso teste de qualidade e segurança do código usando o sonarqube https://www.sonarqube.org/
3.1 – integrando o sonarqube e quality gate na esteira do jenkins
4.0 – realizando teste funcional utilizando o selenium como nas imagens abaixo
5.0 – vamos agora construir o mesmo projeto porém utilizando o pipeline do jenkins
5.1 – inserir o código abaixo no pipeline
pipeline {
agent any
stages {
stage ('Build Backend') {
steps {
bat 'mvn clean package -DskipTests=true'
}
}
stage ('Unit Test') {
steps {
bat 'mvn test'
}
}
stage ('Sonar analysis') {
environment {
scannerHome = tool 'SONAR_SCANNER'
}
steps {
withSonarQubeEnv('SONAR_LOCAL') {
bat "${scannerHome}/bin/sonar-scanner -e -Dsonar.projectKey=DeploBack -Dsonar.host.url=http://127.0.0.1:9000 -Dsonar.login=ee946d1fb6cbc1a9cf240c8114506cbff3a08a41 -Dsonar.java.binaries=target -Dsonar.coverage.exclusions=**/.mvn/**,**/src/test/**,**/model/**,**Applicantion.java"
}
}
}
stage ('Quality Gate') {
options {
timeout(time: 5, unit: 'MINUTES')
retry(2)
}
steps {
sleep(10){
waitForQualityGate(abortPipeline: true)
}
}
}
stage ('Deploy Backend') {
steps {
deploy adapters: [tomcat8(credentialsId: 'TomcatLogin2', path: '', url: 'http://127.0.0.1:8001/')], contextPath: 'tasks-backend', war: 'target\\tasks-backend.war'
}
}
stage ('API Test') {
steps {
dir('api-test') {
git credentialsId: 'github_login', url: 'https://github.com/gugafer/tasks-api-test'
bat 'mvn test'
}
}
}
stage ('Deply Frontend') {
steps {
dir('frontend') {
git credentialsId: 'github_login', url: 'https://github.com/gugafer/tasks-frontend'
bat 'mvn clean package'
deploy adapters: [tomcat8(credentialsId: 'TomcatLogin2', path: '', url: 'http://127.0.0.1:8001/')], contextPath: 'tasks', war: 'target\\tasks.war'
}
}
}
stage ('Functional Test') {
steps {
dir('functional-test') {
git credentialsId: 'github_login', url: 'https://github.com/gugafer/tasks-functional-test'
bat 'mvn test'
}
}
}
stage ('Deploy Prod') {
steps {
bat 'docker-compose build'
bat 'docker-compose up -d'
}
}
stage ('Health check') {
steps {
sleep(20)
dir('functional-test') {
bat 'mvn verify'
}
}
}
}
post{
always{
junit allowEmptyResults: true, testResults: 'target/surefire-reports/*.xml, functional-test/target/surefire-reports/*.xml, functional-test/target/failsafe-reports/*.xml'
archiveArtifacts artifacts: 'target/tasks-backend.war, frontend/target/tasks.war', followSymlinks: false, onlyIfSuccessful: true
}
}
}
5.2 – inicializar o docker-compose de produção como abaixo:
version: "3"
services:
db:
container_name: pg-prod
image: postgres:9.6
networks:
- prod_net_back
environment:
- POSTGRES_PASSWORD=passwd
- POSTGRES_DB=tasks
volumes:
- prod_postgresql:/var/lib/postgresql
- prod_postgresql_data:/var/lib/postgresql/data
backend:
container_name: backend-prod
image: back_prod:build_${BUILD_NUMBER}
build:
context: .
args:
- WAR_FILE=target/tasks-backend.war
- CONTEXT=tasks-backend
networks:
- prod_net_back
- prod_net_front
#ports:
# - 9998:8080
environment:
- DATABASE_HOST=db
- DATABASE_PORT=5432
- DATABASE_USER=postgres
- DATABASE_PASSWD=passwd
- DATABASE_UPDATE=none
depends_on:
- db
frontend:
container_name: frontend-prod
image: front_prod:build_${BUILD_NUMBER}
build:
context: .
args:
- WAR_FILE=frontend/target/tasks.war
- CONTEXT=tasks
networks:
- prod_net_front
ports:
- 9999:8080
environment:
- BACKEND_HOST=backend
- BACKEND_PORT=8080
- APP_VERSION=build_${BUILD_NUMBER}
#depends_on:
# - backend
networks:
prod_net_front:
prod_net_back:
volumes:
prod_postgresql:
prod_postgresql_data:
5.3 – Por fim nossa esteira pronta, versionada e automatizada, veja nas imagens abaixo
#cloud #CI #CICD #jenkins #sonar #sonarcube #selenium #docker #dockercompose #devops #esteira #qualitygate #maven #java #tomcat #pipeline
Gustavo Ferreira
Arquiteto Cloud, DevOps, Site Reliability Engineering (SRE)
Membro do blog space one labs
Certificação Comptia Cloud+