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>
104 lines
4.9 KiB
YAML
104 lines
4.9 KiB
YAML
# Run SonarQube static analysis against the code that just landed on `main` and
|
|
# report the results to the self-hosted SonarQube server for review. This is
|
|
# intentionally NON-BLOCKING: it triggers on push to main (i.e. AFTER merge),
|
|
# not on pull_request, so it never gates a PR. It complements pr-checks.yml
|
|
# (which gates PRs) and release.yml (which publishes the bundle) — this one only
|
|
# feeds the dashboard.
|
|
#
|
|
# Mirrors RunicGateway/website's sonarqube.yml, for the same reason pr-checks.yml
|
|
# does: this module is two npm packages shaped like that repo's `server/` and
|
|
# `client/`, and it is loaded into that repo's process. Until now it was the one
|
|
# part of the platform that had never been scanned — 75 files that arrived in the
|
|
# Phase 3 extraction with core's Sonar history left behind in core's project.
|
|
#
|
|
# Prerequisites (one-time, in the Gitea UI — Repo → Settings → Actions):
|
|
# • Secret SONAR_TOKEN — a SonarQube "Analysis" token generated at
|
|
# My Account → Security in SonarQube for the
|
|
# Module-uo project (or a global one).
|
|
# • Variable SONAR_HOST_URL — the SonarQube base URL on your LAN, e.g.
|
|
# http://192.168.0.56:9000
|
|
# (kept as a variable, not committed, so the internal address stays out of git.)
|
|
#
|
|
# The runner (self-hosted `ubuntu-latest`, same as the other workflows) must be
|
|
# able to reach SONAR_HOST_URL on your network. Nothing here waits on the
|
|
# SonarQube Quality Gate, so a failing gate does not fail this job — check the
|
|
# dashboard when you want to.
|
|
|
|
name: SonarQube
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
# Allow re-running the analysis on demand from the Actions tab.
|
|
workflow_dispatch: {}
|
|
|
|
concurrency:
|
|
group: sonarqube-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
analysis:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check out (full history for accurate new-code + blame)
|
|
uses: actions/checkout@v4
|
|
with:
|
|
# SonarQube uses git history to attribute issues to authors and to
|
|
# compute "new code". A shallow clone degrades both.
|
|
fetch-depth: 0
|
|
|
|
# Node 22, where pr-checks.yml pins 20: the built-in `lcov` coverage
|
|
# reporter this job depends on needs >= 22. The version that matters for
|
|
# correctness is the one in pr-checks.yml, which matches the core process
|
|
# this module is loaded into; nothing here ships.
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
|
|
- name: Install deps for both halves
|
|
run: |
|
|
npm ci --prefix server
|
|
npm ci --prefix client
|
|
|
|
# The chunk has to exist before the client suite runs: build.test.js and
|
|
# registration.test.js read `client/dist/entry.js`, and both SKIP when
|
|
# there is no build. Run the other way round they skip silently and this
|
|
# job reports coverage for a suite that quietly asked less than it looks
|
|
# like it did — the same ordering pr-checks.yml calls load-bearing.
|
|
- name: Build the client chunk
|
|
run: npm run build --prefix client
|
|
|
|
# SonarQube runs static analysis only — it never executes the test suite,
|
|
# so we must produce the coverage report ourselves and hand it to the
|
|
# scanner (see sonar.javascript.lcov.reportPaths in sonar-project.properties).
|
|
#
|
|
# Both suites are invoked from the REPO ROOT rather than with `--prefix`,
|
|
# so the LCOV `SF:` paths come out repo-root-relative (`server/router/...`,
|
|
# `client/src/...`) and resolve against sonar.sources. That is also why the
|
|
# server suite's `--require` is spelled out here instead of reusing
|
|
# `npm test --prefix server`, whose path is relative to `server/`.
|
|
- name: Generate server test coverage (LCOV)
|
|
run: |
|
|
mkdir -p server/coverage
|
|
node --test --experimental-test-coverage \
|
|
--require ./server/test/_setup.js \
|
|
--test-reporter=spec --test-reporter-destination=stdout \
|
|
--test-reporter=lcov --test-reporter-destination=server/coverage/lcov.info \
|
|
--test-reporter=./scripts/sonar-test-reporter.mjs --test-reporter-destination=server/coverage/test-execution.xml \
|
|
server/test/*.test.js
|
|
|
|
- name: Generate client test coverage (LCOV)
|
|
run: |
|
|
mkdir -p client/coverage
|
|
node --test --experimental-test-coverage \
|
|
--test-reporter=spec --test-reporter-destination=stdout \
|
|
--test-reporter=lcov --test-reporter-destination=client/coverage/lcov.info \
|
|
--test-reporter=./scripts/sonar-test-reporter.mjs --test-reporter-destination=client/coverage/test-execution.xml \
|
|
client/test/*.test.js
|
|
|
|
- name: Run SonarQube scan
|
|
uses: sonarsource/sonarqube-scan-action@v4
|
|
env:
|
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
|
SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }}
|