- ALM used - Azure DevOps
- CI system used - Azure DevOps
- Languages of the repository - .Net
Hello, I’m struggling with an issue for some time now, code coverage on PRs and on main branch is not working anymore as it used to. For example, there are times when some PRs with multiple new lines get code coverage but only for a few files, seems like there are files that have been excluded from analysis even though the settings remained the same, this has been happening since May and I noticed even a dramatic drop in overall detected lines of code for our project, see attached screenshots.
Screenshots related to PR with 0 CC
- task: SonarCloudPrepare@2
displayName: Prepare SonarCloud
inputs:
SonarCloud: SonarCloud
organization: my_org
scannerMode: MSBuild
projectKey: my_org_project-api
projectName: project-api
projectVersion: $(Build.BuildNumber)
cliSources: $(Build.SourcesDirectory)/src/api/
configMode: manual
extraProperties: |
sonar.verbose=true
sonar.cs.vstest.reportsPaths=$(System.DefaultWorkingDirectory)/src/api/**/*.trx
sonar.cs.vscoveragexml.reportsPaths=$(System.DefaultWorkingDirectory)/src/api/merged.coverage.xml
sonar.exclusions=**/*.js,**/*.map,**/*.css,**/*.xml,**/*.json,**/*.ruleset,**/SonarQube/*,**/Migrations/*,**/wwwroot/*,**/packages/**/*,**/*.dll,**/obj/**/*,**/com.strategikon.maestro.domain/Config/**,**/com.strategikon.maestro.test/**/*,**/com.strategikon.maestro.unittests/**/*,**/*tests.cs
sonar.coverage.exclusions=**/*.js,**/*.map,**/*.css,**/*.json,**/*.ruleset,**/SonarQube/*,**/Migrations/*,**/wwwroot/*,**/packages/**/*,**/*.dll,**/obj/**/*,**/com.strategikon.maestro.domain/Config/**,**/com.strategikon.maestro.test/**/*,**/com.strategikon.maestro.unittests/**/*,**/*tests.cs
$(sonarTargetBranch)
$(sonarPrBranch)
$(sonarPrProvider)
$(sonarPrVstsToken)
${{ parameters.testDir }}
condition: and(succeeded(), eq(variables['detectapi.APIBUILD'], 'true'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.Reason'], 'PullRequest'), or(eq(variables['Build.Reason'], 'Manual'), eq(variables['RunSonarScan'], 'true'))),eq(variables.ShouldRunTestsAndScans,'true'))
continueOnError: true
- task: DotNetCoreCLI@2
displayName: Restore NuGet Packages for sln
env:
NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages
inputs:
command: restore
projects: |
$(SolutionAll)
verbosityRestore: Minimal
includeNuGetOrg: true
condition: and(succeeded(), eq(variables['detectapi.APIBUILD'], 'true'))
- task: DotNetCoreCLI@2
displayName: Build solutions
inputs:
projects: |
$(SolutionAll)
arguments: -c $(BuildConfiguration) --no-restore /p:Version=$(BUILD.FILE_VERSION) -v m /nologo
condition: and(succeeded(), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsVision.trx" -f xml -o "vision.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/vision/com.strategikon.vision.tests
displayName: Run Vision unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsApi.trx" -f xml -o "api.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/com.strategikon.maestro.unittests
displayName: Run API unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestWebServerResultsApi.trx" -f xml -o "web.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/com.strategikon.maestro.webserver.unittests
displayName: Run API unit tests via web server
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestSharedComponentsTests.trx" -f xml -o "web.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/Commons/com.strategikon.shared.test
displayName: Run tests for shared component
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsComment.trx" -f xml -o "comment.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/PlatformServices/Comment/com.strategikon.Comment.tests
displayName: Run Comment unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsList.trx" -f xml -o "list.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/PlatformServices/List/com.strategikon.list.tests
displayName: Run List unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsIdentity.trx" -f xml -o "identity.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/PlatformServices/Identity/Tests/com.strategikon.identity.tests
displayName: Run Identity unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsIdentity.trx" -f xml -o "platformcommon.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/PlatformServices/com.strategikon.common.tests
displayName: Run Platform common unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsNotification.trx" -f xml -o "notification.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/PlatformServices/Notification/com.strategikon.Notification.tests
displayName: Run Notification unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsIssueTracker.trx" -f xml -o "issuetracker.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/PlatformServices/IssueTracker/com.strategikon.issuetracker.tests
displayName: Run Issue Tracker unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsAttachment.trx" -f xml -o "attachment.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/PlatformServices/Attachment/com.strategikon.Attachment.tests
displayName: Run Attachment unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsEtl.trx" -f xml -o "etl.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/com.strategikon.etl.unittests
displayName: Run ETL unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsFormula.trx" -f xml -o "formula.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/Commons/Formula/com.strategikon.Formula.tests
displayName: Run Formula unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsPortfolio.trx" -f xml -o "portfolio.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/Maestro/Portfolio/Portfolio.tests
displayName: Run Portfolio unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsCustomAssumptions.trx" -f xml -o "customassumptions.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/Maestro/Portfolio/Portfolio.CustomAssumptions.tests
displayName: Run CustomAssumptions unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsQuestion.trx" -f xml -o "question.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/PlatformServices/Question/com.strategikon.Question.tests
displayName: Run Question unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsAudit.trx" -f xml -o "audit.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/PlatformServices/Audit/com.strategikon.audit.tests
displayName: Run Audit unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/UnitTestResultsRouting.trx" -f xml -o "routing.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/PlatformServices/Routing/Tests/com.strategikon.routing.tests
displayName: Run Routing unit tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test -c $(BuildConfiguration) --blame-hang-timeout 40m --blame-hang-dump-type full --no-restore --no-build -v:normal --nologo --logger trx;LogFileName=$(System.DefaultWorkingDirectory)/src/api/IntegrationTestResults.trx" -f xml -o "integration.coverage.xml"
workingDirectory: $(System.DefaultWorkingDirectory)/src/api/com.strategikon.maestro.test
displayName: Run API integration (DB) tests
condition: and(succeeded(),eq(variables.ShouldRunTestsAndScans,'true'), eq(variables['detectapi.APIBUILD'], 'true'))
continueOnError: true
- task: DotNetCoreCLI@2
displayName: 'Merge code coverage files'
inputs:
command: custom
custom: coverage
arguments: 'merge *.coverage.xml --recursive --output "$(System.DefaultWorkingDirectory)/src/api/merged.coverage.xml" --output-format xml'
condition: and(succeeded(), eq(variables['detectapi.APIBUILD'], 'true'), eq(variables['RunSonarScan'], 'true'),eq(variables.ShouldRunTestsAndScans,'true'))
- task: SonarCloudAnalyze@2
displayName: Perform analysis on SonarCloud
condition: and(succeeded(), eq(variables['detectapi.APIBUILD'], 'true'), eq(variables['RunSonarScan'], 'true'),eq(variables.ShouldRunTestsAndScans,'true'))
continueOnError: true
- task: SonarCloudPublish@2
displayName: Publishing SonarCloud scan results
inputs:
pollingTimeoutSec: 300
condition: and(succeeded(), eq(variables['detectapi.APIBUILD'], 'true'), eq(variables['RunSonarScan'], 'true'),eq(variables.ShouldRunTestsAndScans,'true'))
continueOnError: true
Before these issues we used to restore & build each sln file individually, not the sln that contains all, also we were not merging code coverage files as well, these were some changes done to test if there will be any other outcome. As you can see we’re running the analysis in verbose, so I have full logs. Followed this guide How to find logs about importing code coverage related to the logs but I find anything useful. If anyone has a suggestion I can provide more logs as now I don’t really know what logs will be useful