Pipeline com SonarQubeCloud + Slack


Laboratório 3 – SonarQubeCloud + ESLint + Prettier e Slack
Análise estática com SonarQube/SonarCloud
Integração de ESLint + Prettier na pipeline
Bloquear PRs com cobertura < 50%
Notificações no Teams/Slack
Tópicos cobertos:
SAST
,Code Smells
,Cobertura de testes
,Notificações
Pré requisitos
Ter feito o laboratório Integração Contínua + ACR (https://joaochiroli.com.br/integracao-continua-acr) iremos usar a mesma estrutura
Criar uma conta no Slack (https://slack.com/)
Criar uma conta SonarQubeCloud integrada com sua pipeline (https://sonarcloud.io/login)
Basta ir dando next até aparecer a sessão com o token
Depois disso instale a extensão do SonarqubeCloud (https://marketplace.visualstudio.com/items?itemName=SonarSource.sonarcloud)
Depois copie o token que foi criado anteriormente → vá até o service connection no AzureDevops e efetue a configuração do SonarqubeCloud
1️⃣ Step 1: Ponto de partida azure-pipelines.yml
Iremos criar uma variável para
workingDirectory: '$(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0'
deixando assim a pipeline mais cleanE vamos comentar todo o stage 2 porque não iremos utiliza-lo agora
trigger:
branches:
include:
- main
pr:
branches:
include:
- main
variables:
workingDirectory: '$(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0'
stages:
# 1️⃣ Instala, Valida e Publica o Código
- stage: InstallAndValidate
displayName: Install And Validate
pool:
vmImage: 'ubuntu-latest'
jobs:
- job: InstallAndValidate
displayName: 'InstallAndValidate'
steps:
- checkout: self
displayName: 'Checkout code'
- task: UseNode@1
inputs:
version: '15.x'
displayName: 'Install Node.js'
- script: npm ci
workingDirectory: '$(workingDirectory)'
displayName: 'Install dependencies with ci'
- script: npm run lint
workingDirectory: '$(workingDirectory)'
displayName: 'Linter (ESLint)'
- script: |
npm install --save-dev prettier
npm run prettier
workingDirectory: '$(workingDirectory)'
displayName: 'Formatter (Prettier)'
continueOnError: 'true'
- script: npm test
workingDirectory: '$(workingDirectory)'
displayName: 'Run Tests with Coverage'
- task: PublishPipelineArtifact@1
inputs:
targetPath: '$(workingDirectory)'
artifact: 'validated-source'
publishLocation: 'pipeline'
displayName: 'Validated Source'
# # 2️⃣ Builda e publica a imagem no Acr
# - stage: BuildAndPackage
# displayName: Build And Package
# dependsOn: InstallAndValidate
# condition: succeeded()
# pool:
# vmImage: 'ubuntu-latest'
# jobs:
# - job: BuildAndPackage
# displayName: 'BuildAndPackage'
# steps:
# - task: DownloadPipelineArtifact@2
# inputs:
# artifactName: 'validated-source'
# targetPath: '$(Pipeline.Workspace)/validated-source'
# - task: AzureCLI@2
# inputs:
# azureSubscription: 'projeto-user-arm'
# scriptType: 'bash'
# scriptLocation: 'inlineScript'
# inlineScript: |
# az acr login --name acrplaygroundproject
# docker build -t acrplaygroundproject.azurecr.io/playgroundgapp:$(Build.BuildId) $(Pipeline.Workspace)/validated-source
# docker push acrplaygroundproject.azurecr.io/playgroundgapp:$(Build.BuildId)
# displayName: 'Build and Push Docker Image'
2️⃣Step 2: Adicionando o SonarQubeCloud na pipeline e alterando Dockerfile
Nessa step além de colocar o sonarqube na nossa pipeline iremos:
Comentar o ruin build
O Sonar pra funcionar corretamente é preciso acrescentar 3 tasks novas:
task:SonarCloudPrepare@3
precisa estar no começo da pipelinetask:SonarCloudAnalyze@3
etask:SonarCloudPublish@3
devem estar na fase final da pipeline
Vamos acresentar o parâmetro fetchDepth: 0 logo após do parâmetro steps:
jobs: - job: InstallAndValidate displayName: 'InstallAndValidate' steps: - checkout: self fetchDepth: 0 displayName: 'Checkout code'
Também vamos ajustar a task de testes para que, ao executá-lo, seja gerado um arquivo de cobertura (coverage). Esse arquivo será enviado ao SonarQube para análise dos dados. Além disso, definiremos um limiar mínimo (threshold) de cobertura para garantir a qualidade do código.
Nessa etapa também iremos alterar o Dockerfile que está na raiz do projeto, iremos fazer o build usando o Dockerfile e não na pipeline como foi feito nos últimos laboratórios, agora ele terá a seguinte estrutura:
FROM node:15 AS builder WORKDIR /app COPY . . RUN npm ci --ignore-scripts && npm run build FROM node:15 WORKDIR /app COPY --from=builder /app . RUN npm ci --ignore-scripts --omit=dev EXPOSE 3000 CMD ["npm", "start"]
Como ficou o
azure-pipelines.yml
:```yaml trigger: branches: include:
main
pr: branches: include:
main
variables: workingDirectory: '$(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0'
stages:
1️⃣ Instala, Valida e Publica o Código
stage: InstallAndValidate displayName: Install And Validate pool: vmImage: 'ubuntu-latest' jobs:
job: InstallAndValidate displayName: 'InstallAndValidate' steps:
checkout: self fetchDepth: 0 displayName: 'Checkout code'
task: UseNode@1 inputs: version: '15.x' displayName: 'Install Node.js'
task: SonarCloudPrepare@3 inputs: SonarQube: 'projeto-user-sonar' organization: 'joaochiroli123' scannerMode: 'cli' configMode: 'manual' cliProjectKey: 'joaochiroli123_Projeto-Pessoal' cliProjectName: 'Projeto Pessoal' cliSources: '.' extraProperties: | extraProperties: | sonar.qualitygate.wait=true
sonar.javascript.lcov.reportPaths=$(workingDirectory)/coverage/lcov.infoscript: npm ci workingDirectory: '$(workingDirectory)' displayName: 'Install dependencies with ci'
script: npm run lint workingDirectory: '$(workingDirectory)' displayName: 'Linter (ESLint)'
script: | npm install --save-dev prettier npm run prettier workingDirectory: '$(workingDirectory)' displayName: 'Formatter (Prettier)' continueOnError: 'true'
- script: npm test -- --coverage --watchAll=false --coverageThreshold='{"global":{"lines":50}}' workingDirectory: '$(workingDirectory)' displayName: 'Run Tests with Coverage' env: CI: true
- task: PublishCodeCoverageResults@2 inputs: codeCoverageTool: 'Clover' summaryFileLocation: '$(workingDirectory)/coverage/clover.xml' reportDirectory: '$(workingDirectory)/coverage'
- task: SonarCloudAnalyze@3 inputs: jdkversion: 'JAVA_HOME_17_X64'
task: SonarCloudPublish@3 inputs: pollingTimeoutSec: '300'
task: PublishPipelineArtifact@1 inputs: targetPath: '$(workingDirectory)' artifact: 'validated-source' publishLocation: 'pipeline' displayName: 'Validated Source' ```
- Após a execução da pipeline podemos verficar no SonarQube que algumas métricas já começam a aparecer
3️⃣Step 3: Integração com Slack
Após criação da sua conta → Vá em canais e crie um projeto
No canto superior direito vá até os 3 pontos → clique em editar configurações
Ao abrir Editar configurações → Clique em integrações → Adicionar Apps e procure por Azure Devops Pipelines
Agora você precisa interagir com o bot usando
/azrepos signin
para fazer a conexão entre sua pipeline e o slackSelecione
sign in
→ copie o código que vai aparecer pra você → use este código ementer code
Agora é preciso fazer um ajuste nas politicas da organização do Azure Devops para que essa integração realmente funcione então siga os passos abaixo:
Entre na sua organização (
https://dev.azure.com/{yourorganization}
).Selecione Organization settings.
Deixe as configurações seguindo esta estrutura:
Agora basta executar sua pipeline que seu slack vai começar a receber as notificações:
4️⃣Step 4: Pipeline final azure-pipelines.yml
trigger:
branches:
include:
- main
pr:
branches:
include:
- main
variables:
workingDirectory: '$(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0'
stages:
# 1️⃣ Instala, Valida e Publica o Código
- stage: InstallAndValidate
displayName: Install And Validate
pool:
vmImage: 'ubuntu-latest'
jobs:
- job: InstallAndValidate
displayName: 'InstallAndValidate'
steps:
- checkout: self
fetchDepth: 0
displayName: 'Checkout code'
- task: UseNode@1
inputs:
version: '15.x'
displayName: 'Install Node.js'
- task: SonarCloudPrepare@3
inputs:
SonarQube: 'projeto-user-sonar'
organization: 'joaochiroli123'
scannerMode: 'cli'
configMode: 'manual'
cliProjectKey: 'joaochiroli123_Projeto-Pessoal'
cliProjectName: 'Projeto Pessoal'
cliSources: '.'
extraProperties: |
extraProperties: |
sonar.qualitygate.wait=true
sonar.javascript.lcov.reportPaths=$(workingDirectory)/coverage/lcov.info
- script: npm ci
workingDirectory: '$(workingDirectory)'
displayName: 'Install dependencies with ci'
- script: npm run lint
workingDirectory: '$(workingDirectory)'
displayName: 'Linter (ESLint)'
- script: |
npm install --save-dev prettier
npm run prettier
workingDirectory: '$(workingDirectory)'
displayName: 'Formatter (Prettier)'
continueOnError: 'true'
- script: npm test -- --coverage --watchAll=false --coverageThreshold='{"global":{"lines":50}}'
workingDirectory: '$(workingDirectory)'
displayName: 'Run Tests with Coverage'
env:
CI: true
- task: PublishCodeCoverageResults@2
inputs:
codeCoverageTool: 'Clover'
summaryFileLocation: '$(workingDirectory)/coverage/clover.xml'
reportDirectory: '$(workingDirectory)/coverage'
- task: SonarCloudAnalyze@3
inputs:
jdkversion: 'JAVA_HOME_17_X64'
- task: SonarCloudPublish@3
inputs:
pollingTimeoutSec: '300'
- task: PublishPipelineArtifact@1
inputs:
targetPath: '$(workingDirectory)'
artifact: 'validated-source'
publishLocation: 'pipeline'
displayName: 'Validated Source'
# 2️⃣ Builda e publica a imagem no Acr
- stage: BuildAndPackage
displayName: Build And Package
dependsOn: InstallAndValidate
condition: succeeded()
pool:
vmImage: 'ubuntu-latest'
jobs:
- job: BuildAndPackage
displayName: 'BuildAndPackage'
steps:
- task: DownloadPipelineArtifact@2
inputs:
artifactName: 'validated-source'
targetPath: '$(Pipeline.Workspace)/validated-source'
- task: AzureCLI@2
inputs:
azureSubscription: 'projeto-user-arm'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
az acr login --name acrplaygroundproject
docker build -t acrplaygroundproject.azurecr.io/playgroundgapp:$(Build.BuildId) $(Pipeline.Workspace)/validated-source
docker push acrplaygroundproject.azurecr.io/playgroundgapp:$(Build.BuildId)
displayName: 'Build and Push Docker Image'
Subscribe to my newsletter
Read articles from João Chiroli directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
