docs(ci): document the SonarQube static-analysis setup #27
59
ci/SONARQUBE.md
Normal file
59
ci/SONARQUBE.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# SonarQube static analysis
|
||||||
|
|
||||||
|
Each code repo in the Runic Gateway org reports static-analysis results to the
|
||||||
|
self-hosted **SonarQube** server for review. Analysis is **non-blocking**: it
|
||||||
|
runs on push to `main` (i.e. *after* merge), never on pull requests, so it never
|
||||||
|
gates a PR. It complements each repo's PR gate and release pipeline — it only
|
||||||
|
feeds the dashboard.
|
||||||
|
|
||||||
|
## Server
|
||||||
|
|
||||||
|
- **URL:** `https://sonar.whitlocktech.com`
|
||||||
|
- Each repo is a separate SonarQube project, keyed as below.
|
||||||
|
|
||||||
|
## Projects
|
||||||
|
|
||||||
|
| Repo | Project key | Sources analysed | Language |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `website` | `runic-gateway-website` | `server/src`, `client/src`, `bot/src` | JS/TS |
|
||||||
|
| `link` | `runic-gateway-link` | `sidecar/src` | Rust |
|
||||||
|
| `Android-app` | `runic-gateway-android-app` | `app/src/main` | Kotlin |
|
||||||
|
|
||||||
|
## How it's wired
|
||||||
|
|
||||||
|
Each repo carries two files, identical in shape across repos:
|
||||||
|
|
||||||
|
- **`sonar-project.properties`** (repo root) — declares the project key, sources,
|
||||||
|
tests, and exclusions. The Sonar scanner reads this.
|
||||||
|
- **`.gitea/workflows/sonarqube.yml`** — a `SonarQube` workflow that, on push to
|
||||||
|
`main` (and via manual `workflow_dispatch`), checks out with full history
|
||||||
|
(`fetch-depth: 0`, needed for accurate blame + "new code") and runs
|
||||||
|
`sonarsource/sonarqube-scan-action@v4`.
|
||||||
|
|
||||||
|
The scan is **source-based** — it does not build the project or run a language
|
||||||
|
toolchain, so the workflows are lightweight (checkout + scan only). Richer
|
||||||
|
signals (Rust Clippy, Android Lint, JaCoCo coverage) are left as documented,
|
||||||
|
commented-out enrichment in each repo's `sonar-project.properties`; enable them
|
||||||
|
per repo when wanted.
|
||||||
|
|
||||||
|
## One-time setup per repo (Gitea UI → Repo → Settings → Actions)
|
||||||
|
|
||||||
|
Both are consumed by the scan action via `env:` in the workflow:
|
||||||
|
|
||||||
|
- **Secret `SONAR_TOKEN`** — a SonarQube *Analysis* token (My Account →
|
||||||
|
Security in SonarQube; project-scoped or global).
|
||||||
|
- **Variable `SONAR_HOST_URL`** — the SonarQube base URL reachable from the
|
||||||
|
self-hosted runner. Kept as a **variable, not committed**, so the internal
|
||||||
|
address stays out of git.
|
||||||
|
|
||||||
|
The self-hosted `ubuntu-latest` runner must be able to reach `SONAR_HOST_URL` on
|
||||||
|
the network. Nothing waits on the SonarQube Quality Gate, so a failing gate does
|
||||||
|
not fail the job — check the dashboard.
|
||||||
|
|
||||||
|
## Adding a new repo
|
||||||
|
|
||||||
|
1. Create the project in SonarQube; note its key.
|
||||||
|
2. Add `sonar-project.properties` (copy an existing repo's, adjust key + sources).
|
||||||
|
3. Add `.gitea/workflows/sonarqube.yml` (copy verbatim — it's language-agnostic).
|
||||||
|
4. Set the `SONAR_TOKEN` secret and `SONAR_HOST_URL` variable in the repo's
|
||||||
|
Gitea Actions settings.
|
||||||
Reference in New Issue
Block a user