# 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 }}