Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 0 additions & 114 deletions .github/workflows/sonar.yml

This file was deleted.

21 changes: 10 additions & 11 deletions .sonarcloud.properties
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Scope for SonarCloud AUTOMATIC ANALYSIS only.
# Scope for SonarCloud AUTOMATIC ANALYSIS — the only analysis this project runs.
#
# The CI scan in .github/workflows/sonar.yml is the real analysis (it builds the projects and uploads
# coverage) and carries its own /d:sonar.* settings; automatic analysis has to be switched off for that
# scan to be accepted, at which point this file is simply ignored. It is kept because automatic
# analysis is still the active mode (`sonar.autoscan.enabled=true` on the project), so today this file
# — not the workflow — is what actually scopes the published results. Keep the two exclusion lists
# identical; anything only in the workflow has no effect until the mode is switched.
# There is deliberately no scanner workflow. A CI scan (`dotnet sonarscanner`) cannot coexist with
# automatic analysis: `sonarscanner end` is rejected with "You are running CI analysis while Automatic
# Analysis is enabled", which is a server-side project setting no file in this repo can change. The
# workflow that used to live at .github/workflows/sonar.yml therefore failed on every run it ever made
# and published nothing, so it was removed. See R-9 in docs/arc42/11-risks-and-technical-debt.md for
# what that costs (no coverage metric, no compiled analysis) and how to reverse the decision.
#
# docs/ is the vendored `lego-ble-wireless-protocol-docs` submodule: third-party LEGO protocol
# documentation (HTML/JS) that we neither own nor maintain.
Expand All @@ -15,8 +15,7 @@
# references are unresolved. Every member that reads an [ObservableProperty]-generated property, and
# every IValueConverter implementation, therefore looks like it uses no instance state — 57 bogus
# S2325 "make it static" findings (uncompilable if applied), plus S8970 "nullable warnings are
# disabled here" although Directory.Build.props sets <Nullable>enable</Nullable>. The app is not
# analysable in either mode — the CI scan can't build its five heads on a Linux runner either, and
# excludes the same path — so exclude it rather than leave unfixable findings open.
# Only the .cs is excluded: the WasmScripts JS and any XML still get analysed.
# disabled here" although Directory.Build.props sets <Nullable>enable</Nullable>. Excluding the app is
# the only way to close findings that cannot be fixed in code.
# Only the .cs is excluded, so the WasmScripts JS and any XML still get analysed.
sonar.exclusions=docs/**,Source/Trackify/**/*.cs
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
| Category | Badge |
| --- | --- |
| CI | [![CI](https://github.com/Ktechen/Trackify/actions/workflows/ci.yml/badge.svg)](https://github.com/Ktechen/Trackify/actions/workflows/ci.yml) |
| CodeQL | [![CodeQL](https://github.com/Ktechen/Trackify/actions/workflows/codeql.yml/badge.svg)](https://github.com/Ktechen/Trackify/security/code-scanning) |
| CodeQL | [![CodeQL](https://img.shields.io/badge/CodeQL-default%20setup-2088FF?logo=github)](https://github.com/Ktechen/Trackify/security/code-scanning) |
| Android APK | [![Android APK](https://github.com/Ktechen/Trackify/actions/workflows/android-apk.yml/badge.svg)](https://github.com/Ktechen/Trackify/actions/workflows/android-apk.yml) |
| CLI linux-arm64 | [![CLI linux-arm64](https://github.com/Ktechen/Trackify/actions/workflows/cli-arm64.yml/badge.svg)](https://github.com/Ktechen/Trackify/actions/workflows/cli-arm64.yml) |
| License | [![License](https://img.shields.io/github/license/Ktechen/Trackify)](LICENSE) |
Expand All @@ -20,7 +20,6 @@
| Maintainability Rating | [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=Ktechen_Trackify&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=Ktechen_Trackify) |
| Technical Debt | [![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=Ktechen_Trackify&metric=sqale_index)](https://sonarcloud.io/summary/new_code?id=Ktechen_Trackify) |
| Duplicated Lines | [![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=Ktechen_Trackify&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=Ktechen_Trackify) |
| Coverage | [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=Ktechen_Trackify&metric=coverage)](https://sonarcloud.io/summary/new_code?id=Ktechen_Trackify) |

A Clean Architecture solution with **two front-ends over one shared core**: an [Uno Platform](https://platform.uno)
app (App / HMI / Web) and a [Spectre.Console](https://spectreconsole.net) CLI for a Raspberry Pi / Linux server.
Expand Down
2 changes: 1 addition & 1 deletion docs/arc42/02-architecture-constraints.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ technology choices, then the rules the project imposes on itself.
| OC-1 | **Single maintainer, hobby cadence.** Anything that only works because someone remembers it will break; conventions must be machine-checked. |
| OC-2 | **CI runs on hosted GitHub runners.** The Uno app's five heads cannot be restored on one runner, so `ci.yml` gates the shared core + CLI + tests only; the Android head is covered by `android-apk.yml`. |
| OC-3 | **Hardware verification is manual.** BLE cannot run in CI or in an agent environment — real behaviour is confirmed on a phone and on a Raspberry Pi. |
| OC-4 | **SonarCloud + CodeQL** run on every PR. `docs/**` (the vendored LEGO submodule) is excluded — third-party HTML/JS the project neither owns nor fixes. |
| OC-4 | **SonarCloud + CodeQL** run on every PR, both configured outside the workflow files. Excluded from Sonar: `docs/**` (the vendored LEGO submodule — third-party HTML/JS the project neither owns nor fixes) and `Source/Trackify/**/*.cs` (the Uno app, which the build-less analysis cannot judge — [R-9](11-risks-and-technical-debt.md)). |
| OC-5 | The vendored LEGO protocol documentation is a **git submodule**; it is read-only reference material. |

## 2.4 Self-imposed conventions (enforced by the build)
Expand Down
2 changes: 1 addition & 1 deletion docs/arc42/04-solution-strategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ restart and no UI changes.
| Any warning at all | `TreatWarningsAsErrors` + `EnforceCodeStyleInBuild` |
| Package version drift | Central Package Management (`Directory.Packages.props`) |
| Uno version drift | `Uno.Sdk` pinned in `global.json`, not in package props |
| Bugs, coverage, security rating | SonarCloud (`sonar.yml`) + CodeQL, per PR |
| Bugs, security rating | SonarCloud automatic analysis + CodeQL, per PR (no coverage — see [R-9](11-risks-and-technical-debt.md)) |

What *cannot* be enforced automatically is stated as a convention in
[§2.4–2.5](02-architecture-constraints.md#24-self-imposed-conventions-enforced-by-the-build) and
Expand Down
30 changes: 19 additions & 11 deletions docs/arc42/07-deployment-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ confirm that a failure really is the non-root switch.
> `docker:S6471` as a scanner `/d:` parameter. It silently did nothing — issue exclusions are
> multi-value *server-side* settings that only apply when configured in the SonarCloud UI. The
> parameter was live for the analysis of `9299be9` and the issue still came back `OPEN`. Fixing the
> finding at the source was the durable answer.
> finding at the source was the durable answer. In hindsight it was doubly doomed: the scanner
> workflow carrying that parameter never published an analysis at all ([R-9](11-risks-and-technical-debt.md)),
> so nothing it passed could have taken effect either way. The scanner has since been removed.

## 7.4 Server mode (client/server)

Expand Down Expand Up @@ -180,8 +182,8 @@ for a **trusted home LAN** and must not be exposed to the internet — see
```mermaid
graph LR
PR["PR → master"] --> CI["ci.yml<br/>ubuntu-latest"]
PR --> SON["sonar.yml<br/>scan + coverage"]
PR --> CQL["codeql.yml"]
PR --> SON["SonarCloud<br/>automatic analysis"]
PR --> CQL["CodeQL<br/>default setup"]
TAG["tag v*"] --> APK["android-apk.yml<br/>windows-latest"]
TAG --> ARM["cli-arm64.yml<br/>self-contained linux-arm64"]

Expand All @@ -195,19 +197,25 @@ graph LR
| Workflow | Trigger | Runner | Does |
|---|---|---|---|
| `ci.yml` | PR / push to `master` | ubuntu-latest | Builds the CLI + shared core, runs the tests. **The pre-merge gate** |
| `sonar.yml` | PR / push to `master` | ubuntu-latest | SonarCloud scan with coverage (OpenCover via coverlet). Deliberately separate from the gate so a Sonar outage cannot block a merge; skipped for fork PRs, which never receive `SONAR_TOKEN` |
| `codeql.yml` | PR / push | — | Security code scanning |
| `android-apk.yml` | tag `v*` / manual | windows-latest | JDK 17 + `android` workload, `-f net10.0-android` → `trackify-apk` |
| `cli-arm64.yml` | tag `v*` / manual | ubuntu-latest | `-f net10.0 -r linux-arm64 --self-contained` → `trackify-cli-linux-arm64` |

Two analyses run **without a workflow file in this repo**, so they have no `.yml` to read:

| Analysis | Configured by | Notes |
|---|---|---|
| SonarCloud | [`.sonarcloud.properties`](../../.sonarcloud.properties) + the GitHub app | **Automatic analysis** — never builds, so it reports no coverage and analyses C# without a compilation. A scanner workflow cannot coexist with it → [R-9](11-risks-and-technical-debt.md) |
| CodeQL | GitHub **default setup** (`dynamic/github-code-scanning/codeql`) | Runs `csharp`, `javascript-typescript` and `actions`. Configured in the repo's Security settings, not in version control |

All workflows provision the .NET 8, 9 and 10 SDKs; `global.json` pins `9.0.100` with
`rollForward: latestMajor`, so the newest installed major is used.

**The Uno app is intentionally not built by `ci.yml`.** Its five heads trigger workload imports and
OS-locked TFMs (iOS needs macOS, Windows needs Windows) during *restore*, even with `-f <head>` — so
gating one head reliably would need a per-OS + workload matrix. The Android head is covered by
`android-apk.yml`; the remaining heads are verified locally. The same limitation scopes the
SonarCloud analysis to the shared core + CLI + tests. → [§11](11-risks-and-technical-debt.md)
`android-apk.yml`; the remaining heads are verified locally. The app is out of the SonarCloud scope
too, for a related but distinct reason: automatic analysis never builds anything, so its C# findings
on the app are noise rather than results. → [§11](11-risks-and-technical-debt.md)

**Local verification** (what a change is expected to pass before it is pushed):

Expand All @@ -222,10 +230,10 @@ Buildable heads outside macOS: `net10.0-android`, `net10.0-desktop`, `net10.0-br
`net10.0-windows10.0.19041.0`. Real BLE behaviour is confirmed on a device and on a Pi — it cannot be
exercised in CI.

**Checking SonarCloud's C# rules locally.** The scan needs a `SONAR_TOKEN` and only runs in CI, so a
fix to a Sonar finding is otherwise unverifiable before pushing — and while
[R-9](11-risks-and-technical-debt.md) stands, the published findings are not trustworthy anyway. The
same rules can be run offline by injecting the analyzer package without touching any repo file: write
**Checking SonarCloud's C# rules locally — the authoritative check.** Because the hosted analysis
never compiles the code ([R-9](11-risks-and-technical-debt.md)), its C# findings cannot be trusted and
a fix cannot be confirmed there. Run the same rules offline instead, by injecting the analyzer package
without touching any repo file: write

```xml
<Project><ItemGroup>
Expand Down
4 changes: 3 additions & 1 deletion docs/arc42/09-architecture-decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ Windows) — **even with `-f <head>`**, because restore imports workloads for al

**Decision.** `ci.yml` gates the shared core + CLI + tests on ubuntu-latest. The Android head is built
by `android-apk.yml` on windows-latest for tags. The other heads are verified locally by developers.
The same limitation scopes the SonarCloud analysis.
The app is also outside the SonarCloud scope, for a related but separate reason
([R-9](11-risks-and-technical-debt.md)): the analysis never builds, so its findings on the app are
artefacts of the missing compilation rather than results.

**Consequences.** The gate is fast and reliable on a single runner. The gap is real and accepted: a
change that breaks only the desktop, WASM or iOS head **can merge**. Mitigation is the documented
Expand Down
4 changes: 2 additions & 2 deletions docs/arc42/10-quality-requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ suspect.
| Build health, warnings, code style | `TreatWarningsAsErrors` + `EnforceCodeStyleInBuild` | every build |
| Layer integrity | NetArchTest architecture tests | `ci.yml` |
| Logic correctness | xUnit tests foldered by layer | `ci.yml` |
| Coverage, bugs, security & maintainability rating | SonarCloud (coverlet → OpenCover) | `sonar.yml`, badges in the README |
| Security patterns | CodeQL | `codeql.yml` |
| Bugs, security & maintainability rating | SonarCloud automatic analysis | `.sonarcloud.properties`, badges in the README |
| Security patterns | CodeQL | GitHub default setup (no workflow file) |
| Control latency, BLE behaviour, UI rendering | **Manual, on real hardware** | phone + Raspberry Pi |

The last row is the honest gap: the top-priority quality goal (control responsiveness) has **no
Expand Down
Loading
Loading