A follow-up to #5060
This moves the `complexipy` and `complexipy-diff` Ninja actions out of
the base `check` actions so that they are not run on `./ninja check`.
## Linked issue
Closes#4986Closes#4985
## Summary
- Move the complexipy-diff check to Ninja so it can be run locally as
part of `./ninja check`.
- Fix
[SARIF](https://docs.github.com/en/code-security/reference/code-scanning/sarif-files/sarif-support)
results not being uploaded if the Complexipy check fails.
## Steps to reproduce (before)
complexipy-diff was only run on CI and pre-push automatically. It was
not covered by ninja check, which is not consistent with most tests and
tools.
## How to test (after)
- Run `./ninja check:complexipy-diff` and confirm it passes.
- Introduce some complex Python change (e.g. add some nested if
statements) so that the check fails now.
- Update your pre-commit config: `./out/extracted/uv/uv run pre-commit
install`.
## Linked issue
Closes#4815
## Summary
This adds [Complexipy](https://github.com/rohaquinlop/complexipy) for
detecting complex Python code:
- The `check:complexity` Ninja actions use a high threshold (50) for now
to avoid failing on existing complex code.
- `just complexipy-diff` is intended for linting new code in PR CI and
uses 15 as the threshold. See
https://rohaquinlop.github.io/complexipy/usage-guide/#ratchet-mode
## How to test
- Run `./ninja check:complexity` locally and confirm it passes.
- Test diff mode: `just complexipy-diff main`.
## Linked issue
Closes#4836
## Summary/motivation
Three related housekeeping changes to improve AI-agent and developer
ergonomics:
1. **justfile**: Expose `./run`, `./run.bat` (Windows),
`./tools/web-watch`,
`./tools/rebuild-web`, and `./tools/clean` as `just` recipes (`run`,
`run-optimized`, `web-watch`, `rebuild-web`, `clean`), consistent with
the
Project convention that all commands go through `just`.
2. **CLAUDE.md**: Add a "Running Anki" section documenting `just run`
and
`just web-watch`; tighten the opening note to explicitly mention
`./run`.
3. **AGENTS.md**: Add a symlink to `CLAUDE.md` so that OpenAI Codex and
other
Agents that look for `AGENTS.md` pick up the same project instructions.
## How to test
- `just run` launches Anki in dev mode (same as `./run`)
- `just run-optimized` launches with `RELEASE=1`
- `just web-watch` starts the file-watcher (macOS/Linux)
- `just clean` removes build outputs
- `AGENTS.md` resolves to the same content as `CLAUDE.md`
## Linked issue
Closes#4920
## Summary
Default to PowerShell 7+ to run just commands on Windows for more
consistent argument quoting rules.
## Steps to reproduce (before)
- Trigger the release workflow: `just release::build --ref main`.
- Inspect the logs of the `prepare` step on GitHub and notice that the
version has literal double quotes.
## How to test (after)
Repeat the same steps and confirm quotes are not passed literally.
## Linked issue
Closes#4863
## Summary / motivation
Adds Playwright as the e2e test framework so contributors can write
browser-based tests against a real headless Anki instance. There was no
automated way to exercise mediasrv pages, SvelteKit routes, or the
`/_anki/` RPC surface from a browser, this PR establishes that harness.
Key pieces:
- `qt/tests/launch_anki_for_e2e.py` — spawns a throwaway Anki instance
(temp `ANKI_BASE`, `QT_QPA_PLATFORM=offscreen`). Pre-seeds `prefs21.db`
so Anki skips the language picker and profile chooser and goes straight
to serving mediasrv.
- `playwright.config.ts` — points `webServer` at the launcher; polls
`/favicon.ico` as the readiness probe.
- `ts/tests/e2e/` — `fixtures.ts` base and a sanity spec that verifies
mediasrv is reachable and a SvelteKit page hydrates.
- `justfile` — `just test-e2e` recipe; Chromium installed to
`out/playwright-browsers/`.
- CI — e2e step in `check-linux`; failed-run artifacts uploaded for 7
days.
- `docs/e2e-testing.md` — contributor guide covering setup, managed vs
reuse-server modes, and writing new tests.
## How to test
Build the project once, then run the e2e suite in managed mode (no
separate `./run` needed — the launcher is started automatically):
```shell
just build
just test-e2e
```
## Before / after behavior (optional)
Before: no browser-level test harness existed.
After: `just test-e2e` drives a real headless Anki instance via
Playwright.
## Risk / compatibility / migration
No production code changed. New dev-only files and CI step only.
Chromium is installed to `out/playwright-browsers/` (gitignored) and
does not affect the regular build.
---------
Co-authored-by: Abdo <abdo@abdnh.net>
## Linked issue
Closes#4840
## Summary / motivation
Adds Vitest V8 coverage for TypeScript/Svelte tests via
`@vitest/coverage-v8`.
Introduces `just test-ts --coverage` and `just test-ts --coverage
--html`,
and wires TypeScript into the `just test --coverage` umbrella —
completing
coverage support across all three stacks (Python, Rust, TypeScript).
The threshold is set to 5% — intentionally low because the Vitest test
count is small relative to the TypeScript/Svelte source surface. It is
meant to be raised as more tests are added.
## How to test
```sh
# Existing behavior unchanged
just test-ts
# Terminal summary + enforces 5% line coverage threshold
just test-ts --coverage
# Terminal summary + HTML report under out/coverage/typescript/
just test-ts --coverage --html
# Full umbrella — all three stacks
just test --coverage
just test --coverage --html
```
### Checklist
- [x] I ran `./ninja check` or an equivalent relevant check locally.
### Details
- `@vitest/coverage-v8` pinned at `3.2.4` in `package.json`.
- Reports are written to `out/coverage/typescript/` via
`--coverage.reportsDirectory=../out/coverage/typescript` (relative to
the `ts/` working directory where vitest runs).
- V8 provider is preferred over Istanbul: faster and requires no Babel
transform for TypeScript projects.
- Coverage measures only code reachable through Vitest's module graph —
Svelte component rendering is not covered.
- The `yarn` justfile variable is added for platform-aware yarn
invocation (Windows vs Unix).
## Before / after behavior
Before: no `just test-ts`, no TypeScript coverage.
After: `just test-ts` runs Vitest via ninja; `just test-ts --coverage`
runs with V8 instrumentation.
`just test --coverage` now spans all three stacks.
---------
Co-authored-by: Abdo <abdo@abdnh.net>
## Linked issue
Closes#4839
## Summary / motivation
Adds `cargo-llvm-cov`-based test coverage for the full Rust workspace.
Introduces `just test-rust --coverage` and `just test-rust --coverage
--html`, and wires Rust into the `just test --coverage` umbrella.
`cargo-llvm-cov` is installed on demand into `out/bin/` to avoid
polluting the global cargo install. The `llvm-tools-preview` rustup
component is now installed in CI so the tool can instrument binaries.
## How to test (required)
```sh
# Existing behavior unchanged
just test-rust
# Terminal summary
just test-rust --coverage
# Terminal summary + HTML report under out/coverage/rust/html/
just test-rust --coverage --html
# Umbrella (Rust + Python)
just test --coverage
just test --coverage --html
```
Note: first run of `--coverage` will install `cargo-llvm-cov` into
`out/bin/` (~30s). Subsequent runs skip the install step.
### Checklist
- [x] I ran `./ninja check` or an equivalent relevant check locally.
### Details
- `cargo-llvm-cov` pinned at `0.8.4`, installed into `out/bin/` via
`cargo install --root out`.
- `--workspace --locked` measures all crates and respects the lockfile.
- `llvm-tools-preview` added to `setup-anki` action so CI can instrument
Rust binaries.
- Coverage runs are slower than plain `just test-rust` because
`cargo-llvm-cov` rebuilds with instrumentation — this is expected.
## Before / after behavior
Before: no `just test-rust`, no Rust coverage support.
After: `just test-rust` runs Rust tests via ninja; `just test-rust
--coverage` runs them with `cargo-llvm-cov`
---------
Co-authored-by: Abdo <abdo@abdnh.net>
## Linked issue
Closes#4838
## Summary/motivation
Adds `coverage.py`-based test coverage for both Python test suites
(`pylib` and `qt`). Introduces `just test-py --coverage` and `just
test-py --coverage --html`, plus the `just test --coverage`.
Coverage reports are written to `out/coverage/`.
## How to test
```sh
# Existing behavior unchanged
just test-py
# Terminal summary + enforces thresholds
just test-py --coverage
# Terminal summary + HTML reports under out/coverage/
just test-py --coverage --html
# Umbrella (Python only for now)
just test --coverage
just test --coverage --html
```
### Checklist (minimum)
- [x] I ran `./ninja check` or an equivalent relevant check locally.
### Details
- `coverage` dependency pinned to >=7.13.5 in pyproject.toml.
- The `coverage` umbrella recipe currently delegates to Python only for
now
## Before / after behavior
Before: no `just test-py`, no coverage support.
After: `just test-py` runs Python tests via ninja; `just test-py
--coverage`
runs them with `coverage.py` and enforces minimum line coverage.
---------
Co-authored-by: Abdo <abdo@abdnh.net>
Closes#4793
- Add `workflow_dispatch` trigger to CI (with macOS/Windows support)
- Allow prepare-release and release workflows from any branch
- Add `skip-ci-check` input for hotfix releases
- Add `just release::prepare` and `just ci` recipes
- Make `qt/release/build.sh` find uv in CI and local builds
- Change publish-testpypi environment from testpypi to release
- Add anki-release wheel build step
---------
Co-authored-by: Andrew Sanchez <andrewsanchez@users.noreply.github.com>
Co-authored-by: Fernando Lins <1887601+fernandolins@users.noreply.github.com>
migrates Anki Desktop packaging from the legacy
NSIS/uv-based installer to [BeeWare
Briefcase](https://briefcase.readthedocs.io/). This branch integrates
work from many related issues and PRs to deliver cross-platform native
installers (MSI on Windows, .app on macOS, PyInstaller on Linux) with
code signing, notarization, and file association support.
## Integrated PRs
- #4585 — Set up Briefcase
- #4596 — Add Briefcase icons
- #4598 — Handle Briefcase file associations
- #4601 — Add Briefcase app permissions
- #4609 — Customize Briefcase's MSI installer
- #4616 — Set up Briefcase code signing and notarization
- #4618 — Fix Briefcase packaging for x86 Macs
- #4623 — Customize Briefcase's Linux template
- #4627 — List required Debian packages for Briefcase installer
- #4630 — Update Briefcase's Windows template
- #4631 — Rewrite Linux install/uninstall scripts for PyInstaller
- #4638 — Use PyInstaller on Linux
- #4645 — Update installer docs
- #4654 — Disable Briefcase's universal builds for macOS
- #4672 — Deal with existing NSIS installations in MSI installer
- #4676 — Remove duplicate Briefcase icons
- #4677 — Tweak Linux scripts for new installer
- #4709 — Add anki-console.bat to Briefcase's Windows package
## Related Issues
- #4557 — Evaluate BeeWare Briefcase for Anki packaging and distribution
- #4678 — Support native Windows ARM64 builds for Briefcase
- #4688 — Linux installer: migrate to PyInstaller and rewrite install
scripts
- #4689 — Investigate startup performance with Briefcase
- #4690 — Specify required Linux system packages for Briefcase
- #4691 — Investigate Windows ARM64 support with Briefcase
- #4692 — Test on Linux ARM with Briefcase
- #4693 — Separate ARM and Intel macOS releases
- #4694 — Update developer documentation for Briefcase installer
- #4695 — Support upgrade/downgrade with the Briefcase installer
- #4696 — Update user documentation for new installer
- #4702 — Update Briefcase's Windows template with upstream security fix
and OS version check
- #4703 — Follow-up tweaks to Linux install/uninstall scripts
## Related PRs
- #4619 — Enable Windows ARM64 support
- #4632 — Release action
---------
Co-authored-by: Abdo <abdo@abdnh.net>
Co-authored-by: Andrew Sanchez <andrewsanchez@users.noreply.github.com>
Co-authored-by: Fernando Lins <1887601+fernandolins@users.noreply.github.com>