Azure Devops + Coverlet + SonarQube shows 0% - .net-core

Good morning,
Sorry to bother you, I have a problem and I have no leads.
I have a pipeline on Azure DevOps where I use coverlet to generate a code coverage report when I use the command "dotnet test".
Indeed, the report is well generated.
At first, in the "Prepare analysis on SonarQube" step, I set the variable "sonar.cs.opencover.reportsPaths="$(Agent.TempDirectory)/coverage.opencover.xml".
And yet the end in my SonarQube there is 0% code coverage... I don't know what to do or any leads...
Thanks

I cannot reproduce above issue. And it is hard to troubleshoot since you did not share your configuration for dotnet test task or sonarqube prepare task.
I created a test project and the coverage was successfully published to my sonarqube server. You can refer to below my steps.
1, create sonarqube server and configure my projectName and projectKey (I use azure sonarqube container instance, check here for details).
2, configure sonarqube service connection in azure devops.
3, create build pipeline. I use yaml pipeline.
In Prepare Analysis Configuration task, I choose to Use standalone scanner, and Mode is Manually provide configure. And I set variable sonar.cs.opencover.reportsPaths="$(Agent.TempDirectory)/coverage.opencover.xml".
Below screenshot is the task's setting in classic ui view.
In my dotnet test task I set the arguments as below, and specifically output the coverage result to $(Agent.TempDirectory)/ folder.
arguments: '--configuration $(buildConfiguration) /p:CollectCoverage=true /p:CoverletOutput=$(Agent.TempDirectory)/ /p:CoverletOutputFormat=opencover'
Below is the full content of my azure-pipelines.yml file.
trigger: none
jobs:
- job: 'Tests'
pool:
vmImage: windows-latest
variables:
buildConfiguration: 'Release'
continueOnError: true
steps:
- task: SonarQubePrepare#4
displayName: 'Prepare analysis on SonarQube'
inputs:
SonarQube: sonarlevi
scannerMode: CLI
configMode: manual
cliProjectKey: myproject2
cliProjectName: myproject2
extraProperties: |
sonar.cs.opencover.reportsPaths="$(Agent.TempDirectory)/coverage.opencover.xml"
- task: DotNetCoreCLI#2
inputs:
command: restore
projects: '**\*.csproj'
- task: DotNetCoreCLI#2
inputs:
command: custom
custom: tool
arguments: install --tool-path . dotnet-reportgenerator-globaltool
displayName: Install ReportGenerator tool
- task: DotNetCoreCLI#2
displayName: Test .NET
inputs:
command: test
projects: '**\*Test*.csproj'
publishTestResults: false
arguments: '--configuration $(buildConfiguration) /p:CollectCoverage=true /p:CoverletOutput=$(Agent.TempDirectory)/ /p:CoverletOutputFormat=opencover'
condition: succeededOrFailed()
- task: SonarQubeAnalyze#4
displayName: 'Run Code Analysis'
- task: SonarQubePublish#4
displayName: 'Publish Quality Gate Result'

I did a lot of things to finally managed to get the coverage working but I think that the problem was the "ProjectGUID" missing in each .csproj of my solution making the projects ignored by SonarQube scanner.
I also upgraded from SonarQube 6.2 to 8.1 at the same time which may have solved the problem.
My steps remained unchanged to make this work.

Related

Is there a reason to prefer the `nobuild` and `configuration` inputs vs using arguments in the DotNetCoreCLI#2 Azure pipeline task?

The DotNetCoreCLI#2 task in Azure Pipelines has specific inputs that seem to translate to equivalent MSBuild arguments one would pass when manually running commands like dotnet test ...
When looking at samples in articles, I ALMOST NEVER see anyone using the task inputs, and always using arguments.
However, when I read the docs for that task, it seems to imply that the inputs are equivalent to using the respective arguments.
Also, when I run the pipeline with diagnostics enabled, and I inspect the line that issues the dotnet [command] in the build agent, it doesn't seem to be adding the equivalent arguments to the dotnet cli command when I only use the task inputs vs. manually adding the arguments.
Are these 2 equivalent and should I favor one over the other (if so, why)?
Example using task inputs:
- task: DotNetCoreCLI#2
displayName: 'Run All Tests'
inputs:
command: 'test'
projects: 'portal/tests/**/*.csproj'
testRunTitle: 'Merge CI Build: All Tests - #$(Build.BuildId)'
configuration: $(buildConfiguration) #<--------- THIS
nobuild: true #<--------- THIS
publishTestResults: true
Example using only arguments:
- task: DotNetCoreCLI#2
displayName: 'Run All Tests'
inputs:
command: 'test'
projects: 'portal/tests/**/*.csproj'
testRunTitle: 'Merge CI Build: All Tests - #$(Build.BuildId)'
publishTestResults: true
arguments: '--configuration $(buildConfiguration) --no-build'
[UPDATE with more details]
Here's what I see from the task execution in Azure pipelines when it executes the dotnet test command while using the task inputs, instead of the arguments:
/usr/bin/dotnet test /home/vsts/work/1/s/portal/tests/MyApp.UnitTests/MyApp.UnitTests.csproj --logger trx --results-directory /home/vsts/work/_temp

Devops Pipeline for multiple Azure Functions

I have a solution containing 2 Azure Functions.
In my build Pipeline I create 2 different zip and "seem" fine to me.
Then I use those zip in my release pipelines, everything seems fine (no error), but when I go in the azure portal, I don't see any function available.
While App Insights only gives me this : Loading functions metadata; 0 functions loaded.
What could be wrong?
build pipeline:
name: Azure Pipelines
steps:
- task: DotNetCoreCLI#2
displayName: 'dotnet build'
inputs:
projects: '**/*.csproj'
- task: DotNetCoreCLI#2
displayName: 'Func1 Publish Zip'
inputs:
command: publish
publishWebProjects: false
projects: '$(System.DefaultWorkingDirectory)/SolutionName/Function1/Function1.csproj'
arguments: '--output publish_output\Function1 --configuration Release'
modifyOutputPath: false
- task: PublishPipelineArtifact#1
displayName: 'Func1 Publish Artifact'
inputs:
targetPath: 'publish_output\Function1\'
artifact: Func1Artifact
- task: DotNetCoreCLI#2
displayName: 'Func2 Publish Zip'
inputs:
command: publish
publishWebProjects: false
projects: '$(System.DefaultWorkingDirectory)/SolutionName/Function2/Function2.csproj'
arguments: '--output publish_output\Function2 --configuration Release'
modifyOutputPath: false
- task: PublishPipelineArtifact#1
displayName: 'Func2 Publish Artifact'
inputs:
targetPath: 'publish_output\Func2\'
artifact: Func2Artifact
1 of the release pipeline :
steps:
- task: AzureFunctionApp#1
displayName: 'Deploy Function 1'
inputs:
azureSubscription: '$(Parameters.AzureSubscription)'
appType: '$(Parameters.AppType)'
appName: '$(Parameters.AppName)'
package: '$(System.DefaultWorkingDirectory)/xxx Build/Func1Artifact'
it is a continuation of this post :
Azure Devops Release pipeline(s) for multiple Azure Functions
EDIT:
log for deploy function:
2021-06-29T08:53:49.6084003Z ##[section]Starting: Deploy Func1 Function
2021-06-29T08:53:49.6208602Z
====
2021-06-29T08:53:49.6209159Z Task : Azure Functions
2021-06-29T08:53:49.6209483Z Description : Update a function app with
.NET, Python, JavaScript, PowerShell, Java based web applications
2021-06-29T08:53:49.6209969Z Version : 1.187.0
2021-06-29T08:53:49.6210422Z Author : Microsoft Corporation
2021-06-29T08:53:49.6211044Z Help :
https://aka.ms/azurefunctiontroubleshooting
2021-06-29T08:53:49.6211592Z
====
2021-06-29T08:53:50.6211817Z Got service connection details for Azure
App Service:'func1-dev'
2021-06-29T08:53:52.6469625Z Deleting App Service Application settings.
Data: ["WEBSITE_RUN_FROM_ZIP","WEBSITE_RUN_FROM_PACKAGE"]
2021-06-29T08:54:17.4575237Z Updated App Service Application settings
and Kudu Application settings.
2021-06-29T08:54:17.5343524Z Package deployment using ZIP Deploy
initiated.
2021-06-29T08:54:38.8090909Z Deploy logs can be viewed at https://func1-
dev.scm.azurewebsites.net/api/deployments/xxxx/log
2021-06-29T08:54:38.8091932Z Successfully deployed web package to App
Service.
2021-06-29T08:55:00.5393032Z Successfully added release annotation to
the Application Insight : func1-dev
2021-06-29T08:55:10.1885833Z Successfully updated deployment History at
https://func1-dev.scm.azurewebsites.net/api/deployments/xxx
2021-06-29T08:55:22.5301509Z App Service Application URL: http://func1-
dev.azurewebsites.net
2021-06-29T08:56:06.1898662Z ##[section]Finishing: Deploy Func1 Function

How to ignore some files when generating test coverage with VSTest and reportgenerator tools on Azure pipelines

I have a problem that I have failed to resolve.
I have a .NET core project that I want to run tests and publish the test coverage on Azure Pipelines.
The problem is: I'm using EF to generate Migrations files. I want to ignore these files from test
but I can't.
Anyone how to do add some arguments to the pipe-lines command to ignore these files? like --exclude Migrations/*.cs
Here is the job in my azure-pipelines.yaml
- job: Testing
steps:
- task: UseDotNet#2
displayName: 'Use .Net Core sdk 3.1.x'
inputs:
version: 3.1.x
- task: DotNetCoreCLI#2
inputs:
command: 'test'
projects: '$(build.sourcesDirectory)/tests/*Tests/*.csproj'
arguments: -c $(BuildConfiguration) --logger trx --collect:"XPlat Code Coverage" --settings:$(build.sourcesDirectory)/src/test.runsettings -- RunConfiguration.DisableAppDomain=true
displayName: 'run tests'
- task: DotNetCoreCLI#2
inputs:
command: custom
custom: tool
arguments: install --tool-path . dotnet-reportgenerator-globaltool
displayName: Install ReportGenerator tool
- script: ./reportgenerator -reports:$(Agent.TempDirectory)/**/coverage.cobertura.xml -targetdir:$(Build.SourcesDirectory)/coverlet/reports -reporttypes:"Cobertura"
displayName: Create reports
- task: PublishCodeCoverageResults#1
displayName: 'Publish code coverage'
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: $(Build.SourcesDirectory)/coverlet/reports/Cobertura.xml
You're probably looking for -classfilters or -filefilters.
https://github.com/danielpalme/ReportGenerator
I use -classfilter like this, where Foo.Bar.* and Foo.Baz.* is the namespace i want to exclude in the report:
variables:
...
classes-to-exclude-from-coverage: "-Foo.Bar.*;-Foo.Baz.*"
...
- script: ./reportgenerator -reports:$(Agent.TempDirectory)/**/coverage.cobertura.xml -targetdir:$(Build.SourcesDirectory)/coverlet/reports -reporttypes:"HtmlInline_AzurePipelines;Cobertura;Badges" -assemblyfilters:"-xunit*;" -classfilters:'$(classes-to-exclude-from-coverage)'
displayName: Create reports

Should I put my 2e2 tests before or after my WebAppDeployment in my pipeline?

I hope someone can help me
I am developing an api in dotnet, i am using azure devops and pipelines in yaml.
I have already done my 2e2 test of the api where I basically make real calls to the api that I am developing, in order to test a real user flow within the application.
My question is the following should:
1- Do the 2e2test task before the deployment to my webapp allowing me to know that there is a problem before it is deployed to the resource, but having the problem that I would not be testing with the changes of the present commit (since I would be testing with the previous one because I still I have not deployed the resource)
or
2-do the task 2e2test after the deployment to my webapp, allowing me the tests to be carried out with the changes I made in the commit reflected in the resource and in this way know that what I did gave a problem or not, but having the problem that As the resource was deployed, if there was a problem, it would already be contaminating my webapp.
the yaml I'm working on is:
# ASP.NET
# Build and test ASP.NET projects.
# Add steps that publish symbols, save build artifacts, deploy, and more:
# https://learn.microsoft.com/azure/devops/pipelines/apps/aspnet/build-aspnet-4
trigger:
- development
pool:
vmImage: 'windows-latest'
steps:
- task: DotNetCoreCLI#2
displayName: 'dotnet publish'
inputs:
command: publish
publishWebProjects: false
projects: '**/ChatbotService/*.csproj'
zipAfterPublish: true
modifyOutputPath: true
- task: DotNetCoreCLI#2
displayName: 'dotnet MockUnitTest'
inputs:
command: test
projects: '**/*Tests/MockUnitTest/*.csproj'
arguments: '--configuration $(buildConfiguration) --collect "Code coverage"'
- task: DotNetCoreCLI#2
displayName: 'dotnet E2ETest'
inputs:
command: test
projects: '**/*Tests/E2ETest/*.csproj'
arguments: '--configuration $(buildConfiguration) --collect "Code coverage"'
- task: AzureRmWebAppDeployment#4
inputs:
ConnectionType: 'AzureRM'
azureSubscription: 'bla blab bla'
appType: 'webApp'
WebAppName: 'webapp-chatbotservice-dev'
packageForLinux: '$(System.DefaultWorkingDirectory)/ChatbotService/**/*.zip'
AppSettings: '-ASPNETCORE_ENVIRONMENT Development'
You should deploy first and then run your e-2-e tests but not on production. On production you should run smoke tests which are kind of e-2-e tests which test crucial parts of your app without changing state of the app. (of course it makes sense to run them after deployment)
So it could be in high-level like this:
- build stage
- deploy to test env stage
- run e-2-e test
- deploy to prod env stage
- run smoke test
There is always a risk if you run test on not updated env as your test may verify part of app which are not deployed yet.

How to Make azure-pipeline.yml for CI for a R package?

I have been trying to get an Azure pipeline working for my companies internal R packages. I would like the pipeline to:
Check() the package
Run the tests in /testthat
Check code coverage with covr
We use Azure DevOps and use the Azure Repos within that. The few examples I find mainly focus on GitHub solutions. I have tried working with https://github.com/r-lib/r-azure-pipelines, however, with not a lot of knowledge on how to set up pipelines in the first place I find it very difficult to learn and move forward. I have also posted on RStudio Community here, however my current method does not run check(). I want to try to use all the test functionality that Azure DevOps supplies.
Having faced exactly the same challenges with getting Azure pipelines to work with R packages, in two separate organisations, thought I should take the time to share what I've learned along the way.
Please see brief write up and code at https://github.com/jamiegaida/AzurePipelineR
This builds on the great answer above by louish along with other sources. It also runs the lintr package via MegaLinter.
I needed to do something similar and found your RStudio Community post really useful in getting me started with this - thanks for posting. I have now managed to set up a pipeline which:
Checks the package using rcmdcheck (this also runs the testthat tests)
Runs code coverage with covr
Publishes the test results, code coverage report and the check.log file
First, you first need to make sure your testthat.R script runs test_check with the reporter argument specified like so:
test_check("mypackage", reporter = JunitReporter$new(file = "test-result.xml"))
Then the following .yml file should do the trick:
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
container:
image: 'rocker/tidyverse:latest'
variables:
_R_CHECK_FORCE_SUGGESTS_: false
MAKEFLAGS: "-j 2"
steps:
- bash: R -q -e 'writeLines(".libPaths(\"~/R-private\")", ".Rprofile"); dir.create("~/R-private", recursive = TRUE); print(Sys.getenv());'
displayName: "Preliminaries"
- bash: R -q -e 'install.packages(c("covr", "roxygen2", "testthat", "remotes", "rcmdcheck")); remotes::install_deps(dependencies = TRUE);'
displayName: 'Install Dependencies'
- bash: R -q -e "rcmdcheck::rcmdcheck(args = '--no-manual', error_on = 'warning', check_dir = 'check')"
displayName: 'Check Package'
- bash: R -q -e 'cov <- covr::package_coverage(); covr::to_cobertura(cov, "coverage.xml")'
displayName: 'Run Code Coverage'
condition: succeededOrFailed()
- task: UseDotNet#2
displayName: 'Use .NET Core sdk'
inputs:
packageType: sdk
version: 2.2.203
installationPath: $(Agent.ToolsDirectory)/dotnet
condition: succeededOrFailed()
- task: PublishCodeCoverageResults#1
displayName: 'Publish Code Coverage'
inputs:
codeCoverageTool: 'Cobertura'
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
condition: succeededOrFailed()
- task: PublishTestResults#2
displayName: 'Publish Test Results'
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '**/test-*.xml'
condition: succeededOrFailed()
- task: PublishBuildArtifacts#1
displayName: 'Publish Check log'
inputs:
pathToPublish: 'check/mypackage.Rcheck/00check.log'
artifactName: check
condition: succeededOrFailed()

Resources