Contributing¶
Build through make, never through a bare cargo¶
This is the trap that costs the most time
The Makefile resolves the toolchain directory from rust-toolchain.toml via
rustup which and puts it first on PATH. A bare cargo may be an older
Homebrew one, and then "green on my machine, red in CI" has an explanation
nobody enjoys finding.
Targets¶
| Command | What it does |
|---|---|
make build |
build the workspace and bugsaur → target/debug/bugsaur |
make check |
type-check only; binaries are not runnable afterwards |
make fmt |
check formatting; changes nothing |
make clippy |
clippy across the workspace with -D warnings |
make test |
the offline test suite, --no-fail-fast |
make test-one |
one target: PKG=<crate> [TEST=<file>] [NAME=<filter>] |
make fixture-rust |
build the Rust fixture |
make fixture-c / make fixture-cpp |
build the C and C++ fixtures |
make gui / make gui-rust |
build and launch the GUI on a fixture |
make gui-c / make gui-cpp |
build and launch the GUI on the C or C++ fixture |
make serve SOCKET=… |
run the backend without a window |
make clean |
remove Cargo build artifacts |
make help |
list every target |
Documentation site targets:
| Command | What it does |
|---|---|
make docs-deps |
create the docs virtualenv and install pinned dependencies |
make docs-build |
build the site with --strict |
make docs-serve |
serve the site locally with live reload |
make docs-check |
verify the EN and RU page sets match |
Running one test¶
Whole-workspace runs are slow, and a hanging test makes them useless:
Keeping the Cargo cache under control¶
target/ is disposable. In this workspace it can grow to tens of gigabytes:
debug symbols, incremental state and a separate set of artifacts for every
binary, integration test and feature combination accumulate there. Cargo does
not necessarily remove variants that are no longer useful.
After make clean, do not try to prewarm the cache with --all, --workspace
or --all-targets. In particular, do not run these merely to populate
target/:
Those commands compile targets that ordinary development may never use, including the GUI test harnesses and every integration and E2E test. They quickly recreate the disk usage that cleaning was meant to remove. Full workspace commands are still appropriate when their result is required, for example before a pull request or in CI; they are not cache-warming commands.
Let normal work rebuild only what it needs. To prepare the main application,
use the pinned toolchain and build just bugsaur:
RUSTC="$(rustup which rustc --toolchain 1.92.0)" \
rustup run 1.92.0 cargo build -p bugsaur --locked --offline
For type-checking or tests, keep the same narrow scope:
RUSTC="$(rustup which rustc --toolchain 1.92.0)" \
rustup run 1.92.0 cargo check -p bugsaur --locked --offline
make test-one PKG=bugsaur NAME=<test-filter>
cargo clean removes generated build artifacts, not downloaded crates in the
global Cargo cache. The first build is cold and may take a while; subsequent
builds recreate the useful incremental cache automatically.
Live adapter tests¶
Ignored by default because they need real toolchains installed:
make live-codelldb # real codelldb over TCP DAP
make live-codelldb-c # C, the same adapter, its own fixture
make live-codelldb-cpp # C++, STL containers in the variables pane
make live-dlv-100k # 100k-element collection pagination through Delve
make live-debugpy # Python, needs debugpy in the fixture venv
make live-php-docker # PHP/Xdebug in Docker
make live-test-rust # test-under-cursor, Rust
make live-test-php # test-under-cursor, PHP
For live-debugpy, the interpreter defaults to the fixture's venv, because
debugpy installs into an environment rather than into the system:
An existing environment can be pointed at with BUGSAUR_PYTHON.
Acceptance scripts:
make test-m8 # workspace gate, fake adapter, fixtures, live scenarios
make test-m10 # PHP / Xdebug acceptance
The offline rule¶
make build, make check and make test run with --locked --offline. A build
that silently reaches the network is a build that behaves differently on a
machine without one — and in CI.
CI¶
ci.yml runs the workspace gate on macOS and Linux both. One OS is not
enough: Unix sockets, 0600 permissions and connection-close behaviour differ,
and the whole IPC layer rests on them.
The toolchain is not installed explicitly — rustup on the runner reads
rust-toolchain.toml and installs the pinned version with rustfmt and
clippy. Pinning a stable action here caused CI to drift ahead of local
builds.
docs.yml is separate, and builds the documentation site. It does not depend on
the Rust toolchain and should not lengthen the test matrix.
Every ci.yml run also publishes size-optimised archives for Linux x86-64,
macOS Intel and macOS Apple Silicon in the run's Artifacts section. They
are short-lived builds for testing a commit, not the installation channel. A
pushed v* tag runs release.yml and publishes the same platform set under
GitHub Releases.
Before opening a pull request¶
If you touched documentation:
Both languages must stay in sync — docs-check fails on a page that exists in
one language only.
Where the design rationale lives¶
Decisions are recorded as ADRs rather than argued again in review. If a change contradicts one, the ADR is what to update.