chore(ci): scan this repo with SonarQube (phase 4, slice 0)
All checks were successful
PR Checks / client-build (pull_request) Successful in 14s
PR Checks / frozen-manifest (pull_request) Successful in 34s
PR Checks / server-tests (pull_request) Successful in 8m50s

Until now this was the one part of the platform that had never been scanned.
The 75 files here arrived in the Phase 3 extraction and left their Sonar
history behind in core's project, so a whole module's worth of shipped code
has no dashboard at all.

Adds sonar-project.properties (project key Module-uo) and a sonarqube.yml
mirroring website's: push to main, never a PR gate, nothing waiting on the
quality gate.

Two things differ from core's config, both because this repo is shaped
differently:

  - There is no src/ to point sonar.sources at — the server half keeps
    boot.js/core.js/index.js at server/ root beside its subdirectories — so
    the whole tree is included and the non-source parts are excluded. That
    direction is deliberate: a new top-level server directory is scanned by
    default rather than silently unscanned.
  - server/scripts and client/scripts are IN. checkImports.js and
    checkExternals.js are the enforcement of MODULE_API.md 5.1 and 3.6, they
    carry their own test suites, and both have already shipped defects a
    reviewer missed. Build code that decides whether a release is allowed out
    is not throwaway code.

The workflow builds the client chunk before running either suite, for the
reason pr-checks.yml already calls load-bearing: build.test.js and
registration.test.js read dist/entry.js and SKIP without it, so the other
order reports coverage for a suite that quietly asked less than it looks like
it did.

Both suites run from the repo root rather than with --prefix, so the LCOV SF:
paths come out repo-root-relative and resolve against sonar.sources. That is
why the server suite's --require is spelled out here instead of reusing
`npm test --prefix server`, whose path is relative to server/.

Verified locally: 385 server test cases across 57 covered files and 40 client
cases, both LCOV and Generic Test Execution XML well-formed with
repo-root-relative paths.

Needs one-time setup in the Gitea UI before it can run — secret SONAR_TOKEN
and variable SONAR_HOST_URL, same as the other repos.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-12 02:36:11 -05:00
parent e81b61d044
commit 62c8ee68b4
4 changed files with 234 additions and 0 deletions

54
sonar-project.properties Normal file
View File

@@ -0,0 +1,54 @@
# SonarQube analysis config for module-uo.
# Consumed by the scanner in .gitea/workflows/sonarqube.yml on push to main.
# The project key must match the one created in SonarQube (dashboard URL
# ?id=Module-uo).
sonar.projectKey=Module-uo
sonar.projectName=Module-uo
# Analysed application code.
#
# Unlike core's repo there is no `src/` directory to point at: the server half
# keeps its code at `server/` root (boot.js, core.js, index.js) beside its
# subdirectories, so the whole tree is included and the non-source parts are
# excluded below. That direction is deliberate — a new top-level server
# directory is scanned by default rather than silently unscanned, which is the
# safer way for this list to be wrong.
#
# `client/scripts` and `server/scripts` are in, not out: checkExternals.js and
# checkImports.js *are* the enforcement of MODULE_API.md §3.6 and §5.1, they
# each carry their own test suite, and both have already shipped defects that a
# reviewer missed (see MODULE_SYSTEM.md §2.7.1). Build code that decides whether
# a release is allowed out is not throwaway code.
sonar.sources=server,client/src,client/scripts
# Test code is analysed separately from sources so coverage/metrics attribute
# correctly. Both halves run on Node's built-in test runner (no browser/DOM):
# the server suite is CommonJS behind test/_setup.js, the client's is ESM.
sonar.tests=server/test,client/test
sonar.test.inclusions=server/test/**/*.test.js,client/test/**/*.test.js
# Coverage. The sonarqube.yml workflow runs both suites with Node's built-in
# test-coverage and writes an LCOV report for each BEFORE the scan runs; without
# them the dashboard shows 0% (the scanner never executes tests itself). Both
# suites are invoked from the repo root so the `SF:` paths come out
# repo-root-relative (server/..., client/src/...) and the scanner resolves them
# against the project base dir.
sonar.javascript.lcov.reportPaths=server/coverage/lcov.info,client/coverage/lcov.info
# Test execution ("Unit Tests" measure). A SEPARATE report from coverage: the
# lcov files above only populate Coverage, so without this the dashboard shows a
# coverage % but an empty "Unit Tests" tile. Written by scripts/sonar-test-reporter.mjs,
# a copy of core's — a pure leaf build helper, which is the side of the vendoring
# line that may be copied (MODULE_SYSTEM.md §2.7.1).
sonar.testExecutionReportPaths=server/coverage/test-execution.xml,client/coverage/test-execution.xml
# Never analyse dependencies, build output, generated artifacts, or fixtures.
#
# `client/dist` is the built chunk (gitignored, but the workflow builds it before
# scanning because client/test/{build,registration}.test.js import it).
# `server/swagger/doc.js` and the two committed generated artifacts at the repo
# root are inputs to and outputs of swagger-autogen, not hand-written code.
sonar.exclusions=**/node_modules/**,server/test/**,client/test/**,client/dist/**,server/swagger/**,server/data/**,server/coverage/**,client/coverage/**,**/*.min.js
sonar.sourceEncoding=UTF-8