Files
Fernando Lins 587d6ec796 fix: run static SonarCloud analysis on fork PRs (#5596)
## Linked issue

Follow-up to #5498, which was closed in favor of a smaller and more
maintainable implementation.

## Summary / motivation

Run CI-based SonarCloud analysis for internal and fork pull requests
while keeping the Quality Gate informational.

The analysis matrix is:

| Event | Static analysis | Coverage in CI | Coverage in SonarCloud |
| --- | --- | --- | --- |
| Internal pull request | Yes | Yes | Yes |
| Push to `main` or `release/**` | Yes | Yes | Yes |
| Fork pull request | Yes | Yes | No |

Fork pull requests continue to run the full test coverage and
coverage-regression checks in the unprivileged CI workflow. Their
contributor-produced coverage reports are not passed to the privileged
SonarCloud workflow.

The fork scan reports static bugs, vulnerabilities, security hotspots,
and code smells. It:

- validates the PR state, repositories, branches, and tested SHA against
the GitHub API;
- checks out the exact revision tested by CI;
- replaces `sonar-project.properties` with the trusted default-branch
version;
- provides `SONAR_TOKEN` only to the scanner step;
- never builds, installs, or executes contributor code;
- keeps scanner-side Clippy and SCA disabled;
- clears coverage report paths and excludes coverage calculation for
forks.

Automatic Analysis remains disabled because it cannot be combined with
CI-based analysis and does not provide the required Rust and coverage
support.

This also configures Vitest to produce repository-relative LCOV paths
such as `SF:ts/lib/...`, allowing SonarCloud to resolve TypeScript files
when reports are downloaded into a separate checkout.

## How to test

### Checklist

- [x] I ran `just check` or an equivalent relevant check locally.
- [ ] I added or updated tests when the change is non-trivial or
behavior changed. The remaining behavior is specific to GitHub's
`workflow_run` environment and can only be exercised end-to-end after
the workflow is available on the default branch.

### Details

The following checks passed locally:

- `just test-ts --coverage`
- `just test-ts --coverage --html`
- `just fmt`
- `just check`
- YAML and JSON parsing
- `git diff --check`

Both TypeScript coverage runs passed all 67 tests. The generated LCOV
report was also checked to confirm that source paths are
repository-relative and begin with `SF:ts/`.

After this lands, end-to-end validation should cover:

1. A push to `main`, confirming that Python, TypeScript, and Rust
coverage reports are imported.
2. An internal PR, confirming static analysis and coverage.
3. A fork PR, confirming static analysis while the coverage download is
skipped and no coverage condition is evaluated.

## Before / after behavior

Before:

- fork PR analysis fails at the protected checkout;
- the `actions/checkout` version comments are outdated;
- TypeScript LCOV paths are relative to `ts/` and may not resolve in the
SonarCloud checkout.

After:

- internal PRs and trusted branch pushes receive static analysis and
coverage;
- fork PRs receive static analysis without importing
contributor-produced coverage;
- fork tests and coverage-regression checks continue to run in regular
CI;
- TypeScript LCOV paths resolve from the repository root;
- technical scanner failures remain visible without making the Sonar
Quality Gate a required merge check.

## Risk / compatibility / migration

The fork analysis runs in a privileged `workflow_run` and necessarily
asks the SonarScanner to parse untrusted source while it has access to a
project-scoped token.

The workflow limits this exposure by using GitHub-hosted runners,
read-only permissions, trusted scanner configuration, an exact tested
SHA, API-validated PR metadata, and no builds, dependency installation,
local Actions, caches, or fork-produced coverage artifacts.

This is intentionally a smaller trust boundary than the data-only
snapshot and custom coverage parser proposed in #5498. It prevents
direct execution of contributor code but does not eliminate potential
vulnerabilities in GitHub Actions or Sonar analyzers.

Automatic Analysis must remain disabled, `SONAR_TOKEN` should remain
restricted to this project, and the SonarCloud check must remain
non-required.
2026-09-14 15:30:42 -03:00
..
…
…