Saltar al contenido principal
septiembre 3, 2020

Cómo configurar SonarCloud en un proyecto de Azure DevOps

Uno de los puntos fuertes que más me gusta de trabajar en Plain Concepts, es que nos orgullecemos de hacer las cosas bien siguiendo las mejores prácticas.  Lograr esto no siempre es sencillo, en muchos casos obliga a estar siempre aprendiendo, investigando y probando cual es la mejor manera de hacer las cosas en un sin fin de áreas distintas. Esto puede sonar abrumador, pero por suerte algunas veces existen herramientas que nos pueden ayudar mucho. Una de estas herramientas es Sonar.

¿Qué es Sonar?

Sonar es el nombre que se utilizaba para referirse a la herramienta SonarQube. Esta herramienta open source que nos permite hacer un análisis estático del código de un proyecto, detectando malas prácticas, posibles errores y bugs. Esta detección se basa en un conjunto de reglas configurables con las que la herramienta va a revisar y analizar todo el código de nuestro proyecto, generando un reporte final que puede ser consultado directamente en la web.

Aunque antiguamente Sonar solo hacía referencia a SonarQube, los tiempos avanzan y cada vez más cosas pasan de ‘on-prem’ a ‘cloud’ y sonar no es menos. Hoy en día al igual que SonarQube, está disponible su versión en la nube llamada SonarCloud, que es de las que hoy vengo a hablaros.

Aunque Sonar es un proyecto open source, eso no significa que sea gratis (lo aclaro por si las moscas). Pero lo interesante aquí es que, aunque no sea gratis, SonarQube tiene una versión Community y SonarCloud es gratuito para proyectos open source. Esto quiere decir que es posible probarlo de un modo u otro antes de decidir si es útil (que ya adelanto yo que sí lo es).

Dicho esto, y como hablar es fácil, vamos a ver cómo podemos añadir Sonar a nuestro proceso de integración continua en Azure DevOps utilizando SonarCloud (aunque el proceso es prácticamente igual si utilizasemos SonarQube).

Preparando el proyecto en SonarCloud

Lo primero que vamos a necesitar evidentemente para añadir SonarCloud, es tener una cuenta de SonarCloud. Para conseguirla, basta con ir a su página https://sonarcloud.io y en la parte superior derecha pulsar sobre el botón de ‘Log in’

SonarCloud LogIn

SonarCloud está integrado ya con varias plataformas de gestión de código fuente como Github o Azure DevOps (y más), por lo que vamos a usar una de esas cuentas para poder crear nuestra cuenta de SonarCloud. ¡Así de fácil!

Dentro de la propia web de SonarCloud, vamos a necesitar hacer 2 cosas:

  • Crear un token para Azure DevOps
  • Crear un proyecto que usar desde Azure Devops

Para la primera de las dos cosas, basta con ir a la parte superior derecha, donde está el icono de nuestro avatar, y pinchar sobre él. Esto va a mostrar un menú desplegable en el que tendremos que pulsar sobre ‘My Account’.

SonarCloud MyAccount

Una vez dentro, vamos a ir la pestaña ‘Security’ y vamos a asignar un nombre para el token de modo que lo podamos identificar posteriormente en caso de que necesitemos revocarlo. Una vez asignado el nombre vamos a pulsar sobre el botón ‘Generate’. Esto nos generará un token que debemos copiar y guardar ya que no vamos a poder verlo nunca más y nos va a hacer falta cuando estemos configurando Azure DevOps.

SonarCloud CreateToken

Lo siguiente que vamos a hacer es crear el proyecto de sonar sobre el que registraremos las métricas que se generen. Para esto simplemente vamos a ir al botón ‘+’ justo al lado de nuestro avatar y vamos a pulsar sobre ‘Analyze new project’:

SonarCloud NewProject

Desde aquí se nos muestra otra ventana donde podemos elegir el proyecto desde la organización de la cuenta que hayamos usado (GitHub, Bitbucket, Azure DevOps…). En caso de elegir directamente un repositorio de la lista, SonarCloud se encargará de gestionar todo lo necesario registrando los webhooks que hagan falta para funcionar.

Esto esta muy bien si queremos una integración rápida y sin complicaciones, pero una opción que para mí personalmente resulta mucho más interesante, es crear el proyecto manualmente. De hecho, es el modelo que vamos a seguir en esta entrada, aunque no está recomendada para usuarios sin conocimientos (pero nosotros vamos a dejar de serlo ahora mismo) por lo que vamos a hacer click sobre ‘Create a project manually’.

SonarCloud SelectSource

Tras esto, y ya para finalizar la configuración en SonarCloud, tenemos que elegir en que organización de SonarCloud queremos crear el proyecto (o crear una nueva en caso de que no queramos ponerlo en ninguna existente) y asignar una clave para el proyecto, que necesitaremos en Azure DevOps, y un nombre para el proyecto. Cuando acabemos, simplemente tenemos que pulsar ‘Set Up’ para crear el proyecto.

SonarCloud SetUp

Una vez hemos terminado, ya tenemos listo todo lo necesario. ¡Vamos a configurar la parte correspondiente de Azure DevOps!

Preparando el proyecto en Azure DevOps

Lo primero que vamos a tener que hacer para poder integrar fácilemente los procesos de SonarCloud en Azure DevOps, es instalar la tarea de SonarCloud en la organización. En caso de que estemos utilizando SonarQube, existen también una tarea especifica de SonarQube que podemos instalar en la organización y que se configura prácticamente igual.

Una vez que tenemos la tarea de SonarCloud instalada en nuestra organización, vamos a ir a las propiedades del proyecto de Azure DevOps y vamos a crear una conexión de servicio de tipo SonarCloud.

DevOps ServiceConnection

Esto nos mostrará un pequeño formulario donde vamos a introducir el token que generamos den SonarCloud, y le vamos a dar un nombre a la conexión. Tras esto, basta con pulsar se ‘Verify and save’ para validar la conexión y guardarla de modo que la podamos utilizar en los pipelines.

DevOps SonarConnection

Con estas dos cosas listas, vamos a crear nuestro pipeline para realizar un analisis con Sonar.

Analizando el proyecto con SonarCloud en el pipeline

Ya tenemos todo listo para poder hacer el análisis estático de SonarCloud de manera automática en nuestro pipeline de Azure DevOps, así que vamos a crear un pipeline.

Para esta entrada vamos a utilizar los pipelines de interfaz gráfica por ser más fácil de seguir para la gente que no está acostumbrada a utilizar los pipelines en YAML, pero de igual manera al final del artículo dejaré el YAML completo para quien como yo prefiera usarlo.

Basta con que, dentro del menú de pipelines, pulsemos sobre el botón de ‘Create Pipeline’.

DevOps NewPipeline

Esto nos lanzará un formulario para elegir el origen del código para hacer el pipeline, y en la parte inferior nos aparece un enlace para utilizar el editor clásico.

DevOps ClassicPipeline

Al seleccionar que queremos utilizar el editor clásico, una nueva ventana nos va a pedir que le indiquemos donde está el repositorio. Aquí depende de cada persona donde este hospedando el repositorio ya que recordemos que Azure Pipelines (el sistema de CI/CD de Azure DevOps) permite que el código fuente este fuera de Azure DevOps, como por ejemplo en Github, Bitbucket…

Una vez seleccionado el repositorio, podemos elegir entre diferentes plantillas ya prehechas para diferentes finalidades. Como en este ejemplo vamos a analizar un proyecto .Net Core, basta con poner en el buscador ‘sonar’ y ver si hay alguna plantilla para .Net Core (que ya adelanto que sí la hay).

DevOps SonarPipeline

Basta seleccionarla para que se creen las tareas necesarias para ejecutar un pipeline estándar de .Net Core con el análisis de sonar listo para configurarlo.

DevOps SonarTemplate

En cuanto a la selección del agente, aquí no hay ningún misterio, seleccionaremos el agente que más nos convenga según el lenguaje y plataforma para el que estemos compilando la solución. Después simplemente seleccionamos la tarea de preparación de SonarCloud (la que está señalada en la foto anterior) y le configuramos los 3 campos necesarios, que son la conexión de servicio que hemos creado previamente, la organización de SonarCloud donde este alojado el proyecto de sonar, y la clave que le indicamos al crear el proyecto en Sonar.

DevOps SonarTask

Una vez que hemos configurado esas dos cosas, simplemente debemos guardar el pipeline y ejecutarlo. Si todo ha ido bien, cuando volvamos a la página del proyecto en SonarCloud, podremos comprobar que ha cambiado al recibir las nuevas métricas y empieza a mostrar resultados sobre la calidad del código.

DevOps SonarOverview

Añadir la cobertura de código al informe de SonarCloud

Ya tenemos lista la automatización del análisis de calidad de código y esto de por sí ya es extremadamente útil puesto que vamos a poder detectar diferentes problemas con la calidad del mismo. Sin ir más lejos, en la imagen anterior se puede comprobar como SonarCloud ha detectado dos puntos donde en el código hay algo raro (lo he hecho a propósito, lo juro), y así nos los está indicando.

Pese a eso, el dato de cobertura de código sigue estando a 0% pese a que mi proyecto tiene más. Esto es porque sonar por si mismo no genera este dato pese a que lo puede mostrar y utilizar. Para poder verlo es necesario hacer unas pequeñas modificaciones en el código y en el pipeline de modo que se genere el informe de cobertura y se envíe a SonarCloud.

Lo primero que necesitamos es lo más sencillo de todo, añadir el paquete NuGet coverlet.msbuild a los proyectos de pruebas. Una vez hecho eso, vamos a tener que editar ligeramente la tarea de ejecución de las pruebas para que haciendo uso de ese paquete NuGet, genere el informe. Para eso, en la tarea de ‘test’ añadiremos ‘/p:CollectCoverage=true /p:CoverletOutputFormat=opencover –logger trx‘ a los argumentos. Esto lo que va a hacer es decirle al paquete NuGet que recolecte la cobertura y que la guarde con formato opencover.

DevOps TestTask

Por último, en la tarea de preparación de SonarCloud, vamos a tener que indicarle a Sonar como recoger la cobertura que hemos generado añadiendo en la sección avanzada.

extraProperties: |
sonar.exclusions=**/obj/**,**/*.dll
sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/**/coverage.opencover.xml
sonar.cs.vstest.reportsPaths=$(Agent.TempDirectory)/*.trx

DevOps SonarTaskAdvanced

Una vez que hemos hecho estos pequeños cambios, basta con que ejecutemos el pipeline para tener disponible un informe en el que ahora sí, recogemos la ejecución de las pruebas y su cobertura.

SonarCloud Overview2

Lo prometido es deuda, así que ahí va también el YAML:

pool:
  vmImage: 'windows-latest'
  demands: java
  
steps:
- task: UseDotNet@2
  inputs:
    packageType: 'sdk'
    version: '3.1.301'
- task: DotNetCoreCLI@2
  displayName: Restore
  inputs:
    command: 'restore'
    projects: '**/*.sln'    

- task: SonarSource.sonarcloud.14d9cde6-c1da-4d55-aa01-2965cd301255.SonarCloudPrepare@1
  displayName: 'Prepare analysis on SonarCloud'
  inputs:
    SonarCloud: SonarCloud
    organization: 'jorturfer-github'
    projectKey: 'sonar-plain'
    extraProperties: |
     sonar.exclusions=**/obj/**,**/*.dll
     sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/**/coverage.opencover.xml
     sonar.cs.vstest.reportsPaths=$(Agent.TempDirectory)/*.trx

- task: DotNetCoreCLI@2
  displayName: Build
  inputs:
    projects: '**/*.sln'
    arguments: '--configuration Release'

- task: DotNetCoreCLI@2
  displayName: Test
  inputs:
    command: test
    projects: '**/*.sln'
    arguments: '--configuration Release /p:CollectCoverage=true /p:CoverletOutputFormat=opencover --logger trx'

- task: SonarSource.sonarcloud.ce096e50-6155-4de8-8800-4221aaeed4a1.SonarCloudAnalyze@1
  displayName: 'Run Code Analysis'

- task: SonarSource.sonarcloud.38b27399-a642-40af-bb7d-9971f69712e8.SonarCloudPublish@1
  displayName: 'Publish Quality Gate Result'

jorge turrado
Autor
Jorge Turrado Ferrero
Software Development Engineer