SonarQube¶
Brimyr can ship coverage to SonarQube in the same run that gates the pull request. Set two inputs and the action installs a scanner for you:
- uses: magmamoose/brimyr@v1
with:
sonar_url: ${{ vars.MM_SONAR_URL }}
sonar_token: ${{ secrets.MM_SONAR_TOKEN }}
An empty sonar_url disables the whole leg, so passing an unset variable simply turns it
off. The project key defaults to the repo slug with / replaced by _, because Sonar
keys can't contain a slash.
This is a full analysis, not a coverage upload
Running the scanner performs SonarQube's own analysis: bugs, code smells, duplication and security hotspots arrive with the coverage whether or not you look at them. There is no coverage-only mode.
The gate never depends on it¶
Every failure here is a ::warning:: annotation and the run continues. A missing scanner,
a bad URL, an outage, an absent token: none of them change the exit code. The patch-coverage
gate is computed locally from the coverage file and never talks to SonarQube.
One scanner per ecosystem¶
| Ecosystem | Scanner | Coverage property |
|---|---|---|
| Python | sonar-scanner (after the tests) |
sonar.python.coverage.reportPaths |
| JavaScript / TypeScript | sonar-scanner (after the tests) |
sonar.javascript.lcov.reportPaths |
| Java | sonar-scanner (after the tests) |
sonar.coverage.jacoco.xmlReportPaths |
| .NET | dotnet sonarscanner, wrapping the build |
sonar.cs.cobertura.reportsPaths |
.NET is the one that can't follow the same shape. SonarSource documents that the
SonarScanner CLI doesn't support C# or VB.NET at all, because those issues come from Roslyn
analyzers that dotnet sonarscanner begin injects into the compilation, and end collects
what the build produced. So for .NET the scanner wraps the run:
dotnet sonarscanner begin /k:... /d:sonar.cs.cobertura.reportsPaths=**/TestResults/**/coverage.cobertura.xml
dotnet build --no-incremental --disable-build-servers
dotnet test --collect:"XPlat Code Coverage"
dotnet sonarscanner end
Brimyr does this automatically when it detects a .NET repo. Three consequences:
- The coverage path is declared at
begin, before any report exists, so it's a wildcard.endaccepts only three flags, and the wildcard is also what makes a multi-test-project solution work without naming GUID directories. --no-incrementalisn't optional. A cached build compiles nothing, the injected analyzers never run, andenduploads an empty analysis from a green job.- Setting
coverage_filedisables the wrap. With no build there's nothing forendto collect, so Brimyr skips rather than uploading an empty analysis.
When the .NET scanner runs, the plain sonar-scanner pass doesn't also run. The .NET scanner
analyses the whole tree, and a second pass on the same project key would overwrite it.
The .NET property is reportsPaths, plural
Unlike sonar.python.coverage.reportPaths and sonar.javascript.lcov.reportPaths.
Sonar isn't consistent here, and the singular form is silently ignored.
Java needs sonar.java.binaries¶
sonar-scanner over a Java repo fails with please provide compiled classes with
sonar.java.binaries. Brimyr can't infer the path, so rather than run a scan that can't
succeed it skips with a warning until you supply it:
with:
sonar_url: https://sonar.example.com
sonar_args: '-Dsonar.java.binaries=**/target/classes'
Sonar also documents that the CLI scanner shouldn't be used for Maven or Gradle projects at
all. mvn sonar:sonar gives a better analysis. The patch-coverage gate is unaffected either
way: it reads the JaCoCo reports directly.
What the scanner install does¶
The install step only runs when sonar_url is set, and it carries continue-on-error, so a
failure leaves no scanner on PATH and Brimyr reports skipped instead of failing your job.
- .NET repos get
dotnet tool install --global dotnet-sonarscanner. Already-installed isn't an error: it falls through toupdate, then to using what's there. - Everything else downloads the SonarScanner CLI and verifies it against SonarSource's
published
.sha256rather than a hash pinned in this repo, which would go stale the momentsonar_scanner_versionis bumped.
Community Build can't gate a pull request¶
Worth knowing before you plan around it. SonarQube Community Build analyses only the main branch. Pull request analysis and branch analysis start at Developer Edition.
You can still run a scan in a pull_request job, and sonar.qualitygate.wait=true will fail
that job on a red gate. But it isn't a pull request analysis: with no sonar.pullrequest.*
support the results are filed against the project's single main branch, so the gate is
evaluated against main's new code and the run overwrites main's stored state with PR code.
Using Sonar as the PR gate destroys the trend you're keeping Sonar for.
The Sonar way quality gate does include New code test coverage is greater than or equal to
80.0%, but "New Code" there means everything since the project's baseline, not the lines
this pull request changed. That gate also ignores coverage entirely until there are at least
20 new lines to cover.
Never pass branch parameters to Community Build
sonar.branch.name and sonar.pullrequest.* are a hard scanner error against Community
Build, not a silent no-op. Brimyr doesn't pass either, but sonar_args would let you.