Skip to content

ci(rust): run the Rust workspace, which no workflow has ever built - #177

Closed
EtienneLescot wants to merge 2 commits into
release/1.8.0from
ci/rust-workspace
Closed

ci(rust): run the Rust workspace, which no workflow has ever built#177
EtienneLescot wants to merge 2 commits into
release/1.8.0from
ci/rust-workspace

Conversation

@EtienneLescot

@EtienneLescot EtienneLescot commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

The gap

No workflow invokes cargo. crates/compositor is production code the app links, crates/compositor-view-napi is the addon it ships, and neither has ever been compiled by CI. The 76 unit tests in the workspace run only when someone remembers to run them locally, and nothing catches a crate that stops building.

This surfaced reviewing #161, which added unit tests as an acceptance criterion — tests that no automated system would ever have run.

Why it wasn't just "add a job"

A runner cannot compile the workspace as things stand. FFMPEG_DIR in crates/.cargo/config.toml points at a gitignored tree: bindgen needs its include/, the linker needs its lib/, and nothing has ever provisioned either. The steps were folklore — hand-place the archive, or junction poc-d3d/thirdparty and hope.

So fetch-ffmpeg.mjs now keeps that tree. It already downloads the shared build, verifies its pinned SHA-256, and asserts the licence is LGPL — then extracted include/ and lib/ and deleted them with the temp dir, keeping only the DLLs. Landing them at FFMPEG_DIR reuses the existing pin, digest and licence check instead of adding a second download path to keep in sync, and it fixes the clean-checkout build for contributors too, not just for CI.

Two details worth a look in review:

  • The destination is parsed out of the cargo config, the same way pinnedFfmpegDir() in compositorViewService.ts reads it for the runtime PATH — a rename can't silently desynchronise them.
  • It copies over the tree rather than replacing it. crates/thirdparty is commonly a junction into poc-d3d/thirdparty, and a recursive delete would follow the junction and take the real tree with it.

The job

windows-latest by necessity — the compositor is D3D11 and links the windows crate, so there is nothing to run on ubuntu.

  • Runs from crates/ rather than passing --manifest-path: cargo resolves .cargo/config.toml against the working directory, and from the root the build gets neither FFMPEG_DIR nor LIBCLANG_PATH.
  • --workspace because default-members = ["poc-d3d"] means a bare cargo test skips the library and the addon.
  • --all-targets because it excludes doctests, and it has to: bindgen copies ffmpeg's C doxygen comments verbatim into out/ffi.rs, so rustdoc finds 13 "examples" that are C and fails to compile them as Rust. They are generated, and there is nothing in them to fix.

Deliberately not included

  • cargo fmt --check fails today on files nobody touched here (audio.rs among them).
  • clippy on FFI-heavy code, against a generated binding that already emits 13 warnings, is a backlog rather than a gate.

Both are ratchets worth adding once someone has cleared them — the same shape as the existing typecheck-tests job. The gate that pays for itself now is "it builds and the tests pass".

Verification

Locally, with the junction removed so the runner's cold state was reproduced: fetch-ffmpeg.mjs materialised the tree at crates/thirdparty, cargo clean -p openscreen-compositor forced bindgen to re-run against it, and cargo test --workspace --all-targets passed 76/76. Re-running the script is a no-op.

Beyond that, this PR verifies itself — the job below is the change.

Expect the first run to be slow (cold Swatinem/rust-cache, and Windows runners are not fast); subsequent runs hit the cache.

No GitHub workflow invokes cargo. crates/compositor is production code the
app links, crates/compositor-view-napi is the addon it ships, and neither
has ever been compiled by CI - the 76 unit tests in the workspace only run
when someone remembers to run them locally, and nothing catches a crate
that stops building.

A runner cannot compile the workspace at all as things stand. FFMPEG_DIR in
crates/.cargo/config.toml points at a tree that is gitignored: bindgen
needs its include/ and the linker needs its lib/, and neither has ever been
provisioned by anything. The steps were folklore - hand-place the archive,
or symlink poc-d3d/thirdparty and hope.

So fetch-ffmpeg.mjs now keeps that tree. It already downloads the shared
build, verifies its pinned SHA-256 and asserts the licence is LGPL; it
extracted include/ and lib/ and then deleted them with the temp dir,
keeping only the DLLs. Landing them at FFMPEG_DIR reuses the pin, the
digest and the licence check rather than adding a second download path to
keep in sync, and it fixes the clean-checkout build for people too, not
only for CI. The destination is read out of the cargo config the same way
compositorViewService.ts reads it for the runtime PATH, so a rename cannot
silently desynchronise them. It copies over the tree rather than replacing
it: crates/thirdparty is commonly a junction into poc-d3d/thirdparty, and
a recursive delete would follow it and take the real tree with it.

The job is windows-latest by necessity - the compositor is D3D11 and links
the windows crate, so there is nothing to run on ubuntu. It runs from
crates/ rather than passing --manifest-path, because cargo resolves
.cargo/config.toml against the working directory and would otherwise get
neither FFMPEG_DIR nor LIBCLANG_PATH. --workspace because
default-members = ["poc-d3d"] means a bare cargo test skips the library and
the addon. --all-targets because it excludes doctests, and it must: bindgen
copies ffmpeg's C doxygen comments into out/ffi.rs verbatim, so rustdoc
finds 13 "examples" that are C, and fails them. They are generated and
there is nothing in them to fix.

Not included, deliberately. cargo fmt --check fails today on files nobody
touched in this change (audio.rs among them), and clippy on FFI-heavy code
with a 13-warning generated binding is a backlog, not a gate. Both are
ratchets to add once someone has cleared them; the gate that pays for
itself now is "it builds and the tests pass".

Verified locally with the junction removed, so the runner's cold state:
fetch-ffmpeg.mjs materialised the tree at crates/thirdparty, cargo clean
-p openscreen-compositor forced bindgen to re-run against it, and
cargo test --workspace --all-targets passed 76/76. Re-running the script
is a no-op.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d6682a3-cd10-463f-a49d-e65987fc51b1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/rust-workspace

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@EtienneLescot
EtienneLescot deleted the branch release/1.8.0 August 1, 2026 00:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant