Stand up a client test suite on Node's built-in runner (no vitest/jsdom — the targeted modules are plain ESM with no browser/DOM deps) and cover the meaningful client logic, not presentational components: - api/client.js: the fetch wrapper — always sends the session cookie, maps a non-2xx response to a thrown ApiError (body.message → statusText fallback), resolves an empty body to null, sets Content-Type for JSON but NOT for raw FormData uploads, and builds/encodes query strings + path params. - lib/shardEvents.js: describe() across event kinds (payload vs live frame, actor name→acct→"Someone" fallback, sale pluralization, champ.update branches) and the categoryOf table-consistency check. - data/regionBuckets.js: the presence roll-up, incl. the first-match-wins ordering and the "buckets always reconcile to the total" invariant. - lib/heroLayout.js: parseLayout's version/shape guard and heroBackground's default-vs-custom branch. - lib/format.js: the date/label formatters + relative-time buckets. Wiring so these actually count: - client/package.json gains a `test` script (node --test); - pr-checks.yml runs the client tests as a PR gate; - sonarqube.yml generates a client LCOV report and sonar-project.properties feeds it alongside the server report (SF paths resolve to client/src/...). 43 client tests; coverage on the tested modules: format/regionBuckets/ heroLayout 100%, api client 86%, shardEvents 80%. Co-Authored-By: Claude <noreply@anthropic.com>
86 lines
3.8 KiB
YAML
86 lines
3.8 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 build-images.yml (which ships images) — this one only
|
|
# feeds the dashboard.
|
|
#
|
|
# 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
|
|
# runic-gateway-website 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
|
|
|
|
# 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: Generate client test coverage (LCOV)
|
|
# The client's pure-logic modules (lib/, api/, data/) are plain ESM with no
|
|
# browser/DOM deps, so they run on the same built-in runner. Run from the
|
|
# repo root so the `SF:` paths come out as `client/src/...`. No `npm ci`:
|
|
# the tested modules import only relative files + Node built-ins.
|
|
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 \
|
|
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 }}
|