ci(sonarqube): generate and report server test coverage
All checks were successful
PR Checks / bot-install (pull_request) Successful in 18s
PR Checks / server-tests (pull_request) Successful in 44s
PR Checks / client-build (pull_request) Successful in 9m24s

SonarQube reported 0% coverage because the analysis workflow never ran
the test suite — the scanner does static analysis only and was handed no
coverage report, and sonar-project.properties defined no report path.

Generate an LCOV report in sonarqube.yml before the scan using Node's
built-in test coverage (run from the repo root so SF: paths are
server/src/... and resolve against the project base dir), and point
the scanner at it via sonar.javascript.lcov.reportPaths. Node's lcov
coverage reporter needs Node >= 22, so the coverage job pins node 22.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-20 23:46:44 -05:00
parent c73273f1bc
commit e515fc0c9d
3 changed files with 37 additions and 1 deletions

View File

@@ -41,6 +41,31 @@ jobs:
# compute "new code". A shallow clone degrades both.
fetch-depth: 0
# SonarQube runs static analysis only — it never executes the test suite,
# so we must produce a coverage report ourselves and hand it to the
# scanner (see sonar.javascript.lcov.reportPaths in sonar-project.properties).
# Node's built-in `lcov` coverage reporter needs Node >= 22.
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: server/package-lock.json
- name: Install server deps
run: npm ci --prefix server
- name: Generate server test coverage (LCOV)
# Run from the repo root (not `--prefix server`) so the LCOV `SF:` paths
# are emitted as `server/src/...`, matching sonar.sources and letting the
# scanner resolve them against the project base dir. The server tests stub
# their models and point the DB pool at a dead port, so no MariaDB is needed.
run: |
mkdir -p server/coverage
node --test --experimental-test-coverage \
--test-reporter=spec --test-reporter-destination=stdout \
--test-reporter=lcov --test-reporter-destination=server/coverage/lcov.info \
server/test/*.test.js
- name: Run SonarQube scan
uses: sonarsource/sonarqube-scan-action@v4
env:

4
.gitignore vendored
View File

@@ -6,6 +6,10 @@ server/node_modules/
# build output
client/dist/
# test coverage (generated in CI for SonarQube)
server/coverage/
coverage/
# env / secrets
.env
*.env

View File

@@ -14,7 +14,14 @@ sonar.sources=server/src,client/src,bot/src
sonar.tests=server/test
sonar.test.inclusions=server/test/**/*.test.js
# Coverage. The sonarqube.yml workflow runs the server suite with Node's built-in
# test-coverage and writes an LCOV report here BEFORE the scan runs; without it
# the dashboard shows 0% (the scanner never executes tests itself). The SF: paths
# in the report are repo-root-relative (server/src/...) so the scanner resolves
# them against the project base dir.
sonar.javascript.lcov.reportPaths=server/coverage/lcov.info
# Never analyse dependencies, build output, generated specs, or runtime dirs.
sonar.exclusions=**/node_modules/**,client/dist/**,client/public/**,server/swagger/**,server/logs/**,server/uploads/**,**/*.min.js
sonar.exclusions=**/node_modules/**,client/dist/**,client/public/**,server/swagger/**,server/logs/**,server/uploads/**,server/coverage/**,**/*.min.js
sonar.sourceEncoding=UTF-8