Commit Graph
6 Commits
Author SHA1 Message Date
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
Fernando Lins 392fdecbb3 docs: add unit testing guidelines (#5522)
## Linked issue

Closes #5521

## Summary / motivation

Adds an Anki-focused unit testing guide for maintainers, contributors,
and coding assistants.

The guide:

- Defines principles for focused, deterministic, and maintainable tests.
- Covers happy paths, error paths, boundaries, regressions, and
test-first development.
- Provides guidance for Python, Python/Qt, Rust, and
Svelte/TypeScript/JavaScript.
- Clarifies the appropriate scope for UI tests and discourages testing
styling or volatile presentation details.
- Links the guide from the shared `CLAUDE.md`/`AGENTS.md` instructions.
2026-09-09 17:03:26 -03:00
Fernando Lins a7f3ffb63a PoC: evaluate SonarCloud as a code quality and coverage tool (#4996)
## Linked issue

Closes #4995

## Summary / motivation

Bedges available:

[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=ankitects_anki&metric=coverage)](https://sonarcloud.io/summary/new_code?id=ankitects_anki)
[![Duplicated Lines
(%)](https://sonarcloud.io/api/project_badges/measure?project=ankitects_anki&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=ankitects_anki)
[![Code
Smells](https://sonarcloud.io/api/project_badges/measure?project=ankitects_anki&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=ankitects_anki)

[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=ankitects_anki&metric=bugs)](https://sonarcloud.io/summary/new_code?id=ankitects_anki)
[![Quality Gate
Status](https://sonarcloud.io/api/project_badges/measure?project=ankitects_anki&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=ankitects_anki)

[![Reliability](https://sonarcloud.io/api/project_badges/measure?project=ankitects_anki&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=ankitects_anki)

[![Security](https://sonarcloud.io/api/project_badges/measure?project=ankitects_anki&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=ankitects_anki)


**[SONAR
DASHBOARD](https://sonarcloud.io/project/overview?id=ankitects_anki)**

Integrates SonarCloud into the CI pipeline as a proof of concept to
evaluate whether
it surfaces actionable quality and security insights for this codebase.

Changes:
- Added `sonar-project.properties` configuring sources (`pylib`, `qt`,
`ts`, `rslib`)
  and coverage report paths
- Extended `tools/coverage/coverage-py` (and `.bat`) to emit
`coverage.xml` (Cobertura)
- Extended `tools/coverage/coverage-ts` (and `.bat`) to emit `lcov.info`
via the V8 provider
- Extended `tools/coverage/coverage-rust` (and `.bat`) to emit
`lcov.info` via
  `cargo-llvm-cov report`
- Added a `SonarCloud Scan` step to the `check-linux` CI job, running
after all
  checks pass and before the build cache is saved

## How to test

### Details

**1. Install sonar-scanner**
```bash
brew install sonar-scanner
```

**2. Generate and configure a token**

Go to [sonarcloud.io](https://sonarcloud.io/) → My Account → Security →
Generate Token
Copy the generated token and export it in your shell:
```
export SONAR_TOKEN=your_token_here
```

**3. Generate coverage reports**
```
just test --coverage
```
Expected output files:

 - out/coverage/python-pylib/coverage.xml
 - out/coverage/python-qt/coverage.xml
 - out/coverage/typescript/lcov.info
 - out/coverage/rust/lcov.info

**4. Run the scanner manually**
```
sonar-scanner
```
Results will appear in the SonarCloud dashboard

To test coverage generation locally:
```bash
just coverage
# verify files exist:
# out/coverage/python-pylib/coverage.xml
# out/coverage/python-qt/coverage.xml
# out/coverage/typescript/lcov.info
# out/coverage/rust/lcov.info
```
2026-08-26 15:48:45 -03:00
Abdo d407e47556 chore: Update Python test coverage threshold (#5299)
Decrease Python test coverage threshold after code removal in #5153

CI failure:
https://github.com/ankitects/anki/actions/runs/31246523150/job/93075937350
2026-08-10 14:47:59 -03:00
Luc McgradyandAbdo 7cf1d29896 docs: Replace docs/ with symlinks (#5031)
<!--
Title (for the Pull Request title field at the top):
Use a short prefix so the change type is obvious. You do not need to
repeat it in the body below.

Examples:
- fix: — bugfix
- feat: — feature
- refactor: — internal change without user-facing feature
- docs: — documentation only
- chore: — tooling, CI, deps, build housekeeping
- test: — tests only
-->

## Linked issue (required)

<!-- Fixes #123 / Closes #123 / Refs #123 -->
closes #5001

This PR replaces the contents of `docs/` with symlinks to
`docs-site/developers/`

A caveat of this is that the metadata appears at the top of the file
instead of the title.
<img width="885" height="275" alt="image"
src="https://github.com/user-attachments/assets/430f9a71-e5a5-4412-983a-e4cfd7dc4714"
/>

We could either:
- Use ninja to copy the files from docs-site/developers and convert it
from .mdx to .md (Might be a problem with the symlink approach if mdx is
added to the contributor file later)
- Leave placeholder "For contribution instructions see: (link to
mintlify site)"s in the folder, which would have to wait until the
domain of the site is set. (Probably the best solution).

---------

Co-authored-by: Abdo <abdo@abdnh.net>
2026-08-04 22:01:31 +03:00
Fernando LinsandAbdo c1b824258e feat: add test coverage docs (#4844)
## Linked issue

Refs #4838 #4839 #4840

## Summary / motivation

Adds a contributor-facing guide for the test coverage setup introduced
across the three coverage PRs, and updates CLAUDE.md to reflect that
`just` is now the single entry point for all build, test, lint, and
format commands.

## How to test

- Read `docs/testing-coverage.md` — verify it covers all three stacks,
  thresholds, and the known gaps section.
- Run `just docs` and open `out/docs/html/index.html` to confirm
  `testing-coverage` appears in the sidebar under Contributing.
- Read `CLAUDE.md` — verify `./ninja` / `./tools` references are gone
  and `just test-rust`, `just test-py`, `just test-ts` are mentioned.

### Details

- `docs/testing-coverage.md`: documents tools, thresholds, per-stack
  entry points, and known gaps for all three coverage stacks.
- `docs/index.md`: wired `testing-coverage` into the Sphinx toctree
  after `contributing`.
- `CLAUDE.md`: replaced raw `./ninja` / `./tools` invocations with
  `just` equivalents; added top-level note directing contributors to
  `just --list`; added `just test-rust`, `just test-py`, `just test-ts`
  to the Quick iteration section.

---------

Co-authored-by: Abdo <abdo@abdnh.net>
2026-05-20 16:21:23 -03:00