diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 6169fa6..90abe87 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -57,6 +57,23 @@ on: description: 'Override when the repository does not install with a frozen pnpm lockfile.' type: string default: '' + coverage-artifact: + description: | + Name of an artifact an earlier job in this same run uploaded, holding the lcov files the + caller's `sonar-project.properties` names. Downloaded into `coverage/` INSTEAD of running + the tests again. + + Use it when reproducing the coverage run here would mean reproducing its whole + environment — theokit needs a sibling repository checked out and built, native bindings + rebuilt and bubblewrap installed before its suite loads. Re-deriving that recipe here + would be a second copy of it, free to drift from the first. + + It is also the more honest number: what Sonar reports is then literally what the caller's + own coverage gate measured, not a second run that could disagree with it. + + Mutually exclusive with `coverage-command`. + type: string + default: '' build-command: description: | Run before the coverage command. A workspace whose packages import each other through @@ -128,6 +145,21 @@ jobs: with: node-version: ${{ inputs.node-version }} + # Fail fast rather than letting one silently win: a caller that sets both holds a belief + # about which coverage the report describes, and half of that belief would be wrong. + - name: Refuse a caller that asks for coverage twice + if: inputs.coverage-command != '' && inputs.coverage-artifact != '' + run: | + echo "::error title=SonarQube Cloud::coverage-command and coverage-artifact are mutually exclusive." + exit 1 + + - name: Download the coverage the caller already measured + if: steps.token.outputs.present == 'true' && inputs.coverage-artifact != '' + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: ${{ inputs.coverage-artifact }} + path: coverage + - name: Install if: steps.token.outputs.present == 'true' && inputs.coverage-command != '' env: diff --git a/CHANGELOG.md b/CHANGELOG.md index 62cdab8..0d0f4eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 matrix of `['22.12', '22']`. The condition was never true, the step reported `skipped` on every run for two months, and a skipped step is indistinguishable from a passing one in the checks list. +- `sonar.yml` inputs `build-command` and `coverage-artifact`, both for the same defect: a scan that + passes while measuring nothing. `theokit-sdk`'s first run reported `No coverage information will + be saved because all LCOV files cannot be found` — its packages import each other through their + published entry points, so nine suites failed to load before `pnpm build` had run. + `build-command` runs first; `coverage-artifact` downloads coverage an earlier job already + uploaded, for callers whose suite needs an environment (a sibling repository built from source, + native bindings, bubblewrap) that reproducing here would only duplicate. The two coverage inputs + are mutually exclusive and the workflow refuses a caller that sets both. + ## [dep-check 0.9.1] - 2026-08-27 ### Fixed