Configuração/Cobertura de Código com SonarCloud
Este guia tem como objetivo ajudar na configuração do SonarCloud em projetos multi-repo e monorepo, integrando-os com o GitHub Actions para rodar testes, gerar relatórios e enviá-los ao SonarCloud. Siga os passos abaixo para configurar corretamente em seu projeto.
1. Criando um Projeto no SonarCloud
- Acesse o SonarCloud e faça login pela sua conta do GitHub que está na organização da DigitalSys
- Clique em “+” no menu superior e selecione “Analyze new project”

- Certifique que em “organization” esteja selecionada a organização da DigitalSys e escolha o repositório que deseja analisar
- Se estiver configurando para um projeto monorepo, selecione a opção "Setup a <u>monorepo</u>" e escolha o repositório do seu projeto

- Após selecionar seu projeto, clique em “Set Up”
- Na página seguinte, escolha o critério para o que será considerado novo código para as próximas análises
- Selecione “Previous version” para que cada nova versão do código no GitHub seja analisada
- Por fim, crie seu projeto clicando em “Create Project”

2. Adicionando Token do SonarCloud ao GitHub
- Após Criar o projeto, selecione “With GitHub Actions” para o método de análise

- Na página seguinte copie o Sonar Token gerado

- No repositório do GitHub, vá para Settings > Secrets and variables > Actions

- No nome do Secret escreva
SONAR_TOKENe em secret cole o Token gerado pelo SonarCloud - Por fim, Clique em “Add secret” para criar o Secret

3. Configurando o SonarCloud no Projeto
- Voltando para a página do SonarCloud podemos acessar as informações do projeto no menu lateral clicando no botão “Information”
- Essa página contem as chaves de projeto e de organização

- Essas chaves devem estar presente em um arquivo
sonar-project.propertiesna raiz do seu projeto, da seguinte forma
sonar.projectKey=DigitalsysTecnologia_exemplo
sonar.organization=digitalsys
- Caso o projeto analisado seja monorepo, além do arquivo de propriedades da raiz, cada módulo deve conter seu próprio
sonar-project.properties, alterando entre eles o sonar.projectKey para o informado no seu repositório próprio do SonarCloud - No arquivo de propriedades do SonarCloud também podem ser definidas algumas configurações, as mais utilizadas são:
<colgroup><col style="width: 262px;"></col><col style="width: 356px;"></col><col style="width: 417px;"></col></colgroup> COMANDO
DESCRIÇÃO
EXEMPLO
sonar.projectKey
Identificador único do projeto no SonarCloud
sonar.projectKey=my_project_key
sonar.organization
Nome da organização no SonarCloud
sonar.organization=my_organization
sonar.sources
Diretório(s) onde o código-fonte está localizado. Pode ser múltiplo, separado por vírgulas
sonar.sources=src
sonar.tests
Diretório(s) onde os testes estão localizados. Pode ser múltiplo, separado por vírgulas
sonar.tests=tests
sonar.language
Linguagem de programação principal do projeto
sonar.language=java
sonar.exclusions
Arquivos ou diretórios a serem excluídos da análise
sonar.exclusions=**/*.xml
sonar.inclusions
Especifica quais arquivos ou diretórios incluir na análise, se for diferente dos padrões
sonar.inclusions=src/**/*.java
sonar.tests.inclusions
Especifica quais arquivos de teste incluir na análise
sonar.tests.inclusions=tests/**/*.java
sonar.test.exclusions
Arquivos ou diretórios de teste a serem excluídos da análise
sonar.test.exclusions=tests/helpers/**
sonar.coverage.exclusions
Arquivos ou diretórios a serem excluídos da análise de cobertura de código
sonar.coverage.exclusions=src/main/resources
sonar.go.coverage.reportPaths
Caminho para o arquivo do relatório de cobertura de testes para projetos em Golang
sonar.go.coverage.reportPaths=reports/*coverage*.out
sonar.python.coverage.reportPaths
Caminho para o arquivo do relatório de cobertura de testes para projetos em Python
sonar.python.coverage.reportPaths=reports/*coverage*.out
Mais comandos podem ser encontrados na Documentação do SonarCloud
Exemplo de arquivo sonar-project.properties comum
sonar.projectKey=DigitalsysTecnologia_exemplo
sonar.organization=digitalsys
sonar.qualitygate.wait=true
sonar.sources=.
sonar.python.coverage.reportPaths=reports/coverage.xml
sonar.coverage.exclusions=**/tests/**,Dockerfile
4. Configurando Workflow do GitHub Actions
- No repositório do projeto, crie um arquivo “.github/workflows/”
- Dentro dessa pasta, crie um arquivo YAML, por exemplo,
ci.yml - Nesse arquivo podemos definir ações que serão executadas pelo GitHub em definidas mudanças no repositório
Primeiro, podemos definir o nome do nosso workflow e quando ele será executado
name: Main Workflow
on:
push:
branches:
- '**'
pull_request:
types: [opened, synchronize, reopened]
Com esse código definimos um workflow chamado “Main Workflow” que será executado sempre que houver um push em qualquer branch do projeto e sempre que um pull request for aberto, sincronizado ou reaberto
Agora podemos criar as ações que serão executadas nos momentos definidos na primeira parte do código. Em nosso caso precisamos:
- Gerar o relatório de cobertura de testes;
- Enviar para análise do SonarCloud;
Para cada ação precisamos especificar os passos do zero, então para gerar o relatório de testes precisamos iniciar o projeto como se estivéssemos o executando pela primeira vez, o exemplo abaixo apresenta os passos necessários para rodar um projeto em Python, dês de configurar a versão do Python que será utilizada até o comando para se gerar o arquivo do relatório pelo GitHub Actions
jobs:
run-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r ./requirements.txt
- name: Run tests
run: |
pytest tests --cov=./ --cov-report=xml:reports/coverage.xml
- name: Store test reports
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: ./reports/coverage.xml
retention-days: 1
if-no-files-found: error
Nesse código estamos criando um “job” chamado run-tests, nele começamos baixando uma versão compatível com o projeto do Python e baixamos suas dependências. No exemplo foi gerado a cobertura de testes pelo pytest, utilizando a flag --cov-report=xml:reports/coverage.xml, que está armazenando o arquivo de relatório em reports/coverage.xml
Por fim, utilizamos o “actions/upload-artifact” para armazenar o relatório, o tornando acessível para os próximos jobs
Agora podemos criar um novo job, com o objetivo de enviar o relatório gerado para a análise do SonarCloud
sonar-scan:
needs: run-tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download coverage artifact
uses: actions/download-artifact@v4
with:
name: coverage-report
path: ./reports/
- name: SonarCloud Scan
uses: sonarsource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
É importante definir que esse job possui dependência no anterior (needs: run-tests), pois se não eles irão ser executados em paralelo, porém precisamos esperar o artefato da primeira ação ser gerado
Com isso, podemos baixar o relatório utilizando o “actions/download-artifact” e especificando o caminho de destino do arquivo. Nota: O caminho de destino para o relatório deve ser o mesmo especificado no sonar-project.properties
Por fim, podemos usar o módulo do actions do sonarcloud “sonarsource/sonarcloud-github-action@master” para realizar a análise e enviar o relatório automaticamente. É importante passar como variável o GITHUB_TOKEN e o SONAR_TOKEN, o Token do SonarCloud foi adicionado as secrets no passo 2., já o Token do GitHub é setado automaticamente pelo próprio GitHub nas secrets do repositório, para acessar uma secret pelo YAML de workflow do Actions basta utilizar ${{ secrets.SECRET_NAME }}
Pronto, na próxima vez que for feito um push ou um pull request as análises de código e cobertura de testes deve estar presente no repositório do projeto no SonarCloud
Exemplo completo do arquivo ci.yml, para um projeto Python
name: Main Workflow
on:
push:
branches:
- '**'
pull_request:
types: [opened, synchronize, reopened]
jobs:
run-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r ./requirements.txt
- name: Run tests
run: |
pytest tests --cov=./ --cov-report=xml:reports/coverage.xml
- name: Store test reports
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: ./reports/coverage.xml
retention-days: 1
if-no-files-found: error
sonar-scan:
needs: run-tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download coverage artifact
uses: actions/download-artifact@v4
with:
name: coverage-report
path: ./reports/
- name: SonarCloud Scan
uses: sonarsource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}