From f61a00c2c4697d45914bf7dd149ed3dd7fc847c0 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Thu, 13 Aug 2026 13:21:22 +0000 Subject: [PATCH] refactor: park the MAVLink 2 bridge out of the tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A domain-specific protocol bridge — one MAVLink dialect, one autopilot ecosystem, ~2 months old at the freeze — is a poor thing to commit to semver for the life of 1.x. Moves it to external/dora-mavlink2/, staged for its own repository, and drops it from the workspace. Unlike the memory-pool extraction this is not an entanglement warning: MAVLink touched dora only through the public node API. Removing it changed no dora source file outside the workspace manifest and the smoke harness, so reinstating it needs a repo and a release, not a new seam. Moves bridge, bridge-node, and both example dirs; drops 5 workspace members, the `dora-mavlink2-bridge` and `mavlink` workspace deps, and the `mavlink2-bridge-cxx` example target; removes 4 smoke tests and the smoke-all.sh entries. The parked crates are listed under `[workspace] exclude` so cargo ignores them. external/dora-mavlink2/README.md records the dependency spec, the fixed-port (udp:14550) smoke caveat, and the `deny.toml` / `_typos.toml` entries deliberately left behind. Co-Authored-By: Claude Opus 5 (1M context) --- CLAUDE.md | 2 - Cargo.lock | 177 ------------------ Cargo.toml | 20 +- README.md | 11 -- external/dora-mavlink2/README.md | 80 ++++++++ .../dora-mavlink2/bridge-node}/Cargo.toml | 0 .../dora-mavlink2/bridge-node}/src/main.rs | 0 .../bridge-node}/tests/tcp_loopback.rs | 0 .../bridge-node}/tests/udp_loopback.rs | 0 .../dora-mavlink2/bridge}/Cargo.toml | 0 .../bridge}/src/arrow_convert.rs | 0 .../dora-mavlink2/bridge}/src/error.rs | 0 .../dora-mavlink2/bridge}/src/lib.rs | 0 .../dora-mavlink2/bridge}/src/transport.rs | 0 .../bridge}/tests/arrow_malformed.rs | 0 .../bridge}/tests/arrow_roundtrip.rs | 0 .../dora-mavlink2/bridge}/tests/builds.rs | 0 .../dora-mavlink2/bridge}/tests/transport.rs | 0 .../examples-sitl-mission}/README.md | 0 .../examples-sitl-mission}/dataflow.yml | 0 .../examples-sitl-mission}/dataflow_long.yml | 0 .../examples-sitl-mission}/dataflow_rover.yml | 0 .../examples-sitl-mission}/mission.py | 0 .../examples-sitl-mission}/mission_long.py | 0 .../examples-sitl-mission}/mission_rover.py | 0 .../examples-sitl-mission}/requirements.txt | 0 .../scripts/forward_to_qgc.py | 0 .../scripts/start_mavlink_long.sh | 0 .../scripts/start_rover.sh | 0 .../scripts/start_sitl.sh | 0 .../dora-mavlink2/examples}/README.md | 0 .../dora-mavlink2/examples}/dataflow-cxx.yml | 0 .../examples}/dataflow-python.yml | 0 .../dora-mavlink2/examples}/dataflow-rust.yml | 0 .../examples}/heartbeat-emitter/Cargo.toml | 0 .../examples}/heartbeat-emitter/src/main.rs | 0 .../examples}/mavlink-sim/Cargo.toml | 0 .../examples}/mavlink-sim/src/main.rs | 0 .../dora-mavlink2/examples}/requirements.txt | 0 .../dora-mavlink2/examples}/run-cxx.rs | 0 .../examples}/telemetry-printer-cxx/main.cc | 0 .../telemetry-printer-rust/Cargo.toml | 0 .../telemetry-printer-rust/src/main.rs | 0 .../examples}/telemetry_printer.py | 0 scripts/smoke-all.sh | 37 ---- tests/example-smoke.rs | 84 --------- 46 files changed, 89 insertions(+), 322 deletions(-) create mode 100644 external/dora-mavlink2/README.md rename {binaries/mavlink2-bridge-node => external/dora-mavlink2/bridge-node}/Cargo.toml (100%) rename {binaries/mavlink2-bridge-node => external/dora-mavlink2/bridge-node}/src/main.rs (100%) rename {binaries/mavlink2-bridge-node => external/dora-mavlink2/bridge-node}/tests/tcp_loopback.rs (100%) rename {binaries/mavlink2-bridge-node => external/dora-mavlink2/bridge-node}/tests/udp_loopback.rs (100%) rename {libraries/extensions/mavlink2-bridge => external/dora-mavlink2/bridge}/Cargo.toml (100%) rename {libraries/extensions/mavlink2-bridge => external/dora-mavlink2/bridge}/src/arrow_convert.rs (100%) rename {libraries/extensions/mavlink2-bridge => external/dora-mavlink2/bridge}/src/error.rs (100%) rename {libraries/extensions/mavlink2-bridge => external/dora-mavlink2/bridge}/src/lib.rs (100%) rename {libraries/extensions/mavlink2-bridge => external/dora-mavlink2/bridge}/src/transport.rs (100%) rename {libraries/extensions/mavlink2-bridge => external/dora-mavlink2/bridge}/tests/arrow_malformed.rs (100%) rename {libraries/extensions/mavlink2-bridge => external/dora-mavlink2/bridge}/tests/arrow_roundtrip.rs (100%) rename {libraries/extensions/mavlink2-bridge => external/dora-mavlink2/bridge}/tests/builds.rs (100%) rename {libraries/extensions/mavlink2-bridge => external/dora-mavlink2/bridge}/tests/transport.rs (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/README.md (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/dataflow.yml (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/dataflow_long.yml (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/dataflow_rover.yml (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/mission.py (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/mission_long.py (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/mission_rover.py (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/requirements.txt (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/scripts/forward_to_qgc.py (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/scripts/start_mavlink_long.sh (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/scripts/start_rover.sh (100%) rename {examples/mavlink2-bridge-sitl-mission => external/dora-mavlink2/examples-sitl-mission}/scripts/start_sitl.sh (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/README.md (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/dataflow-cxx.yml (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/dataflow-python.yml (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/dataflow-rust.yml (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/heartbeat-emitter/Cargo.toml (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/heartbeat-emitter/src/main.rs (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/mavlink-sim/Cargo.toml (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/mavlink-sim/src/main.rs (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/requirements.txt (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/run-cxx.rs (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/telemetry-printer-cxx/main.cc (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/telemetry-printer-rust/Cargo.toml (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/telemetry-printer-rust/src/main.rs (100%) rename {examples/mavlink2-bridge => external/dora-mavlink2/examples}/telemetry_printer.py (100%) diff --git a/CLAUDE.md b/CLAUDE.md index d5cdb3bf24..1ffabc4a51 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -66,8 +66,6 @@ dora run examples/python-dataflow/dataflow.yml --uv --stop-after 10s | `apis/rust/node` | dora-node-api | Rust API for writing custom nodes | | `apis/rust/operator` | dora-operator-api | Rust API for writing in-process operators | | `apis/python/node` | dora-node-api-python | Python node API (PyO3) | -| `libraries/extensions/mavlink2-bridge` | dora-mavlink2-bridge | MAVLink 2 ↔ Apache Arrow conversion (common dialect) | -| `binaries/mavlink2-bridge-node` | dora-mavlink2-bridge-node | Daemon-spawnable MAVLink 2 bridge (TCP/UDP/serial) | ## Architecture diff --git a/Cargo.lock b/Cargo.lock index 23aa084771..89204ba4a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1294,12 +1294,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc-any" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46db9f663dfb869b80fcf59e32d7a80fc6c464a4f6328f3f06a00f5e36d05f8c" - [[package]] name = "crc32fast" version = "1.5.0" @@ -2209,38 +2203,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "dora-mavlink2-bridge" -version = "1.0.0-rc.4" -dependencies = [ - "arrow", - "eyre", - "mavlink", - "num-traits", - "serde", - "thiserror 2.0.20", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "dora-mavlink2-bridge-node" -version = "1.0.0-rc.4" -dependencies = [ - "arrow", - "dora-mavlink2-bridge", - "dora-node-api", - "eyre", - "mavlink", - "serde", - "serde_yaml", - "tempfile", - "tracing", - "tracing-subscriber", - "url", -] - [[package]] name = "dora-memory-pool" version = "1.0.0-rc.4" @@ -3868,16 +3830,6 @@ dependencies = [ "rustversion", ] -[[package]] -name = "io-kit-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" -dependencies = [ - "core-foundation-sys", - "mach2", -] - [[package]] name = "iovec" version = "0.1.4" @@ -4462,15 +4414,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "mach2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" -dependencies = [ - "libc", -] - [[package]] name = "macro_rules_attribute" version = "0.1.3" @@ -4502,81 +4445,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" -[[package]] -name = "mavlink" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef539c358c31f69d47816dac709eebbcb733166ae1bcdeeb4463383c042e3e7c" -dependencies = [ - "bitflags 2.13.1", - "mavlink-bindgen", - "mavlink-core", - "num-derive", - "num-traits", - "serde", - "serde_arrays", -] - -[[package]] -name = "mavlink-bindgen" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "055c957f9fe541226e5b6f0a8aef09b81b9ac865bfc2d083bd6440ed1692602f" -dependencies = [ - "crc-any", - "proc-macro2", - "quick-xml 0.39.4", - "quote", - "regex", - "thiserror 2.0.20", -] - -[[package]] -name = "mavlink-core" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b31cc9f930c7edce0c1933659d405a330a28346cdf087bd283a56a6d72eb3d85" -dependencies = [ - "byteorder", - "crc-any", - "serde", - "serde_arrays", - "serialport", -] - -[[package]] -name = "mavlink2-bridge-example-heartbeat-emitter" -version = "1.0.0-rc.4" -dependencies = [ - "arrow", - "dora-mavlink2-bridge", - "dora-node-api", - "eyre", - "tracing", -] - -[[package]] -name = "mavlink2-bridge-example-mavlink-sim" -version = "1.0.0-rc.4" -dependencies = [ - "dora-mavlink2-bridge", - "dora-node-api", - "eyre", - "mavlink", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "mavlink2-bridge-example-telemetry-printer-rust" -version = "1.0.0-rc.4" -dependencies = [ - "arrow", - "dora-mavlink2-bridge", - "dora-node-api", - "eyre", -] - [[package]] name = "md5" version = "0.8.1" @@ -5941,15 +5809,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "quick-xml" -version = "0.39.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" -dependencies = [ - "memchr", -] - [[package]] name = "quick-xml" version = "0.41.0" @@ -6974,15 +6833,6 @@ dependencies = [ "shellexpand 2.1.2", ] -[[package]] -name = "serde_arrays" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a16b99c5ea4fe3daccd14853ad260ec00ea043b2708d1fd1da3106dcd8d9df" -dependencies = [ - "serde", -] - [[package]] name = "serde_assert" version = "0.8.0" @@ -7126,24 +6976,6 @@ dependencies = [ "unsafe-libyaml", ] -[[package]] -name = "serialport" -version = "4.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4d91116f97173694f1642263b2ff837f80d933aa837e2314969f6728f661df3" -dependencies = [ - "bitflags 2.13.1", - "cfg-if 1.0.4", - "core-foundation", - "core-foundation-sys", - "io-kit-sys", - "mach2", - "nix 0.26.4", - "scopeguard", - "unescaper", - "windows-sys 0.52.0", -] - [[package]] name = "service-example-client" version = "1.0.0-rc.4" @@ -8414,15 +8246,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" -[[package]] -name = "unescaper" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7285e83a80ce76f5e7bce79fa41f68d78ba62d1003cf27bf748ab24413808cf4" -dependencies = [ - "thiserror 2.0.20", -] - [[package]] name = "unicode-ident" version = "1.0.24" diff --git a/Cargo.toml b/Cargo.toml index e5bfa72d4a..80a9f6afa6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ members = [ "binaries/runtime-api", "binaries/runtime-shared-lib", "binaries/runtime-python", - "binaries/mavlink2-bridge-node", "binaries/ros2-bridge-node", "examples/rust-dataflow/node", "examples/rust-dataflow/status-node", @@ -52,9 +51,6 @@ members = [ "examples/validated-pipeline/sink", "examples/error-propagation/producer", "examples/error-propagation/consumer", - "examples/mavlink2-bridge/heartbeat-emitter", - "examples/mavlink2-bridge/mavlink-sim", - "examples/mavlink2-bridge/telemetry-printer-rust", "libraries/arrow-convert", "libraries/log-utils", "libraries/coordinator-store", @@ -66,7 +62,6 @@ members = [ "binaries/record-node", "libraries/extensions/download", "libraries/extensions/telemetry/*", - "libraries/extensions/mavlink2-bridge", "libraries/extensions/memory-pool", "libraries/extensions/ros2-bridge", "libraries/extensions/ros2-bridge/msg-gen", @@ -91,6 +86,15 @@ members = [ "tests/fault_tolerance/timer_tick_recorder_node", "xtask", ] +# Parked for extraction into its own repository — not built by dora. +# See external/dora-mavlink2/README.md. +exclude = [ + "external/dora-mavlink2/bridge", + "external/dora-mavlink2/bridge-node", + "external/dora-mavlink2/examples/heartbeat-emitter", + "external/dora-mavlink2/examples/mavlink-sim", + "external/dora-mavlink2/examples/telemetry-printer-rust", +] [workspace.package] edition = "2024" @@ -133,7 +137,6 @@ dora-coordinator = { version = "1.0.0-rc.4", path = "binaries/coordinator" } dora-ros2-bridge = { version = "1.0.0-rc.4", path = "libraries/extensions/ros2-bridge" } dora-ros2-bridge-msg-gen = { version = "1.0.0-rc.4", path = "libraries/extensions/ros2-bridge/msg-gen" } dora-ros2-bridge-python = { path = "libraries/extensions/ros2-bridge/python" } -dora-mavlink2-bridge = { version = "1.0.0-rc.4", path = "libraries/extensions/mavlink2-bridge" } dora-memory-pool = { version = "1.0.0-rc.4", path = "libraries/extensions/memory-pool" } dora-message = { version = "1.0.0-rc.4", path = "libraries/message" } # Declared here so `dora-ros2-bridge` and `dora-ros2-bridge-arrow` cannot drift @@ -190,7 +193,6 @@ bincode = "1.3.3" flume = "0.12.0" tempfile = "3.27.0" proptest = "1.11" -mavlink = { version = "0.18", default-features = false, features = ["std", "serde", "dialect-common", "transport-tcp", "transport-udp", "transport-direct-serial"] } serialport = "4.9" url = "2.5" @@ -265,10 +267,6 @@ path = "examples/c++-arrow-dataflow/run.rs" name = "cxx-service-action" path = "examples/c++-service-action/run.rs" -[[example]] -name = "mavlink2-bridge-cxx" -path = "examples/mavlink2-bridge/run-cxx.rs" - [[example]] name = "python-dataflow" path = "examples/python-dataflow/run.rs" diff --git a/README.md b/README.md index 802fe4db45..0a8b3bddf1 100644 --- a/README.md +++ b/README.md @@ -417,7 +417,6 @@ binaries/ daemon/ # Node manager + IPC runtime/ # In-process operator runtime ros2-bridge-node/ # ROS2 bridge binary - mavlink2-bridge-node/ # MAVLink 2 bridge binary record-node/ # Dataflow message recorder replay-node/ # Recorded message replayer libraries/ @@ -430,7 +429,6 @@ libraries/ extensions/ telemetry/ # OpenTelemetry tracing + metrics ros2-bridge/ # ROS2 interop (bridge, msg-gen, arrow, python) - mavlink2-bridge/ # MAVLink 2 interop (Arrow ↔ MAVLink, TCP/UDP/serial) download/ # Download utilities apis/ rust/node/ # Rust node API (dora-node-api) @@ -557,15 +555,6 @@ See [docs/patterns.md](docs/patterns.md) for the full guide. | [ros2-bridge/yaml-bridge-action](examples/ros2-bridge/yaml-bridge-action) | YAML ROS2 action client | | [ros2-bridge/yaml-bridge-action-server](examples/ros2-bridge/yaml-bridge-action-server) | YAML ROS2 action server | -### MAVLink 2 integration - -| Example | Description | -|---------|-------------| -| [mavlink2-bridge (Rust)](examples/mavlink2-bridge/dataflow-rust.yml) | MAVLink 2 ↔ dora bridge, Rust telemetry consumer | -| [mavlink2-bridge (Python)](examples/mavlink2-bridge/dataflow-python.yml) | Same bridge, Python telemetry consumer (`--uv`) | -| [mavlink2-bridge (C++)](examples/mavlink2-bridge/dataflow-cxx.yml) | Same bridge, C++ telemetry consumer (`cargo run --example mavlink2-bridge-cxx`) | -| [mavlink2-bridge-sitl-mission](examples/mavlink2-bridge-sitl-mission) | Closed-loop ArduCopter SITL: arm + takeoff + hover + land driven from a Python dora node (Ubuntu / macOS, local-only) | - ## Development **Rust edition 2024; MSRV and default workspace package metadata are diff --git a/external/dora-mavlink2/README.md b/external/dora-mavlink2/README.md new file mode 100644 index 0000000000..204d41b51c --- /dev/null +++ b/external/dora-mavlink2/README.md @@ -0,0 +1,80 @@ +# dora-mavlink2 — parked MAVLink 2 bridge + +MAVLink 2 ↔ Apache Arrow conversion (common dialect) plus a daemon-spawnable +bridge node speaking TCP, UDP, and direct serial. **Extracted from +`dora-rs/dora` before the 1.0 release and parked here.** It is not built by a +dora build and dora 1.0 ships no MAVLink support. + +This directory is staged for lifting into its own repository. Nothing here is +compiled by the workspace — the crates are listed in the root `Cargo.toml` +`[workspace] exclude`, not `members`. + +--- + +## Why this was parked, and why it is easy to unpark + +Unlike the memory-pool extraction, this one is **not** a warning about +entanglement. MAVLink was already well-isolated: it touched dora only through +the public node API, and removing it from the tree changed no dora source file +outside the workspace manifest and the smoke-test harness. + +It was parked for scope, not for design. At 1.0 dora commits to semver on +everything it publishes, and a domain-specific protocol bridge — one MAVLink +dialect, one autopilot ecosystem, roughly two months old at the freeze — is a +poor thing to freeze. Shipping it on its own version line lets it move at the +pace of the flight-controller ecosystem instead of dora's. + +**So the seam already exists.** Reinstating this does not require designing +one; it requires a repository, a release, and a dependency edge pointing the +other way. + +## Layout + +| Path | Former location | Crate | +|---|---|---| +| `bridge/` | `libraries/extensions/mavlink2-bridge` | `dora-mavlink2-bridge` | +| `bridge-node/` | `binaries/mavlink2-bridge-node` | `dora-mavlink2-bridge-node` | +| `examples/` | `examples/mavlink2-bridge` | 3 example node crates + 3 dataflow YAMLs | +| `examples-sitl-mission/` | `examples/mavlink2-bridge-sitl-mission` | ArduCopter SITL mission (no crates) | + +## What it depended on + +- `dora-node-api` — the public node API, nothing internal. +- `mavlink 0.18` with `std`, `serde`, `dialect-common`, and the + `transport-{tcp,udp,direct-serial}` features. This dependency was removed + from the root `[workspace.dependencies]`; the extracted crates must declare + it themselves. +- `arrow` — via `dora-node-api`'s re-export. + +## To stand this up as its own repository + +1. `git subtree split` (or `git filter-repo`) this directory to preserve the + history of all four subtrees. +2. Turn the four directories into a workspace: add a root `Cargo.toml` with + `members = ["bridge", "bridge-node", "examples/*"]`, and move the `mavlink` + dependency spec above into its `[workspace.dependencies]`. +3. Replace `dora-node-api = { workspace = true }` with a crates.io version + requirement — `dora-node-api = "1"` once dora 1.0 is published. +4. Port the smoke coverage. The four smoke tests deleted from + `tests/example-smoke.rs` (`smoke_mavlink2_bridge_rust`, + `smoke_local_mavlink2_bridge_rust`, and the two `_python` variants) and the + `scripts/smoke-all.sh` entries are the starting point; both used the UDP + simulator rather than a real autopilot, so they are CI-portable as-is. +5. Keep the fixed-port caveat in mind: the bridge binds `udp:14550`, so the + smoke harness needs the orphan-reaping `pkill` that was removed from + `scripts/smoke-all.sh`, or successive runs fail with "Address already in + use". + +## Known loose ends carried over + +- `deny.toml` and `.cargo/audit.toml` still carry a `RUSTSEC-2026-0194` + (`quick-xml` quadratic attribute check) ignore whose justification names + `mavlink-bindgen` as one of two build-time sources. With MAVLink gone the + remaining source is `self_update`; the ignore entry is still needed but its + comment now over-explains. Not worth churning until the ignore expires + (review date 2026-09). +- `_typos.toml` retains an allow-list entry introduced for flight-controller + vocabulary in the MAVLink example. Harmless, and cheap to keep in case the + bridge returns. +- The SITL mission example was never in CI (it needs an external ArduPilot + SITL on `udp:14550`) and remains manual-only. diff --git a/binaries/mavlink2-bridge-node/Cargo.toml b/external/dora-mavlink2/bridge-node/Cargo.toml similarity index 100% rename from binaries/mavlink2-bridge-node/Cargo.toml rename to external/dora-mavlink2/bridge-node/Cargo.toml diff --git a/binaries/mavlink2-bridge-node/src/main.rs b/external/dora-mavlink2/bridge-node/src/main.rs similarity index 100% rename from binaries/mavlink2-bridge-node/src/main.rs rename to external/dora-mavlink2/bridge-node/src/main.rs diff --git a/binaries/mavlink2-bridge-node/tests/tcp_loopback.rs b/external/dora-mavlink2/bridge-node/tests/tcp_loopback.rs similarity index 100% rename from binaries/mavlink2-bridge-node/tests/tcp_loopback.rs rename to external/dora-mavlink2/bridge-node/tests/tcp_loopback.rs diff --git a/binaries/mavlink2-bridge-node/tests/udp_loopback.rs b/external/dora-mavlink2/bridge-node/tests/udp_loopback.rs similarity index 100% rename from binaries/mavlink2-bridge-node/tests/udp_loopback.rs rename to external/dora-mavlink2/bridge-node/tests/udp_loopback.rs diff --git a/libraries/extensions/mavlink2-bridge/Cargo.toml b/external/dora-mavlink2/bridge/Cargo.toml similarity index 100% rename from libraries/extensions/mavlink2-bridge/Cargo.toml rename to external/dora-mavlink2/bridge/Cargo.toml diff --git a/libraries/extensions/mavlink2-bridge/src/arrow_convert.rs b/external/dora-mavlink2/bridge/src/arrow_convert.rs similarity index 100% rename from libraries/extensions/mavlink2-bridge/src/arrow_convert.rs rename to external/dora-mavlink2/bridge/src/arrow_convert.rs diff --git a/libraries/extensions/mavlink2-bridge/src/error.rs b/external/dora-mavlink2/bridge/src/error.rs similarity index 100% rename from libraries/extensions/mavlink2-bridge/src/error.rs rename to external/dora-mavlink2/bridge/src/error.rs diff --git a/libraries/extensions/mavlink2-bridge/src/lib.rs b/external/dora-mavlink2/bridge/src/lib.rs similarity index 100% rename from libraries/extensions/mavlink2-bridge/src/lib.rs rename to external/dora-mavlink2/bridge/src/lib.rs diff --git a/libraries/extensions/mavlink2-bridge/src/transport.rs b/external/dora-mavlink2/bridge/src/transport.rs similarity index 100% rename from libraries/extensions/mavlink2-bridge/src/transport.rs rename to external/dora-mavlink2/bridge/src/transport.rs diff --git a/libraries/extensions/mavlink2-bridge/tests/arrow_malformed.rs b/external/dora-mavlink2/bridge/tests/arrow_malformed.rs similarity index 100% rename from libraries/extensions/mavlink2-bridge/tests/arrow_malformed.rs rename to external/dora-mavlink2/bridge/tests/arrow_malformed.rs diff --git a/libraries/extensions/mavlink2-bridge/tests/arrow_roundtrip.rs b/external/dora-mavlink2/bridge/tests/arrow_roundtrip.rs similarity index 100% rename from libraries/extensions/mavlink2-bridge/tests/arrow_roundtrip.rs rename to external/dora-mavlink2/bridge/tests/arrow_roundtrip.rs diff --git a/libraries/extensions/mavlink2-bridge/tests/builds.rs b/external/dora-mavlink2/bridge/tests/builds.rs similarity index 100% rename from libraries/extensions/mavlink2-bridge/tests/builds.rs rename to external/dora-mavlink2/bridge/tests/builds.rs diff --git a/libraries/extensions/mavlink2-bridge/tests/transport.rs b/external/dora-mavlink2/bridge/tests/transport.rs similarity index 100% rename from libraries/extensions/mavlink2-bridge/tests/transport.rs rename to external/dora-mavlink2/bridge/tests/transport.rs diff --git a/examples/mavlink2-bridge-sitl-mission/README.md b/external/dora-mavlink2/examples-sitl-mission/README.md similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/README.md rename to external/dora-mavlink2/examples-sitl-mission/README.md diff --git a/examples/mavlink2-bridge-sitl-mission/dataflow.yml b/external/dora-mavlink2/examples-sitl-mission/dataflow.yml similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/dataflow.yml rename to external/dora-mavlink2/examples-sitl-mission/dataflow.yml diff --git a/examples/mavlink2-bridge-sitl-mission/dataflow_long.yml b/external/dora-mavlink2/examples-sitl-mission/dataflow_long.yml similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/dataflow_long.yml rename to external/dora-mavlink2/examples-sitl-mission/dataflow_long.yml diff --git a/examples/mavlink2-bridge-sitl-mission/dataflow_rover.yml b/external/dora-mavlink2/examples-sitl-mission/dataflow_rover.yml similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/dataflow_rover.yml rename to external/dora-mavlink2/examples-sitl-mission/dataflow_rover.yml diff --git a/examples/mavlink2-bridge-sitl-mission/mission.py b/external/dora-mavlink2/examples-sitl-mission/mission.py similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/mission.py rename to external/dora-mavlink2/examples-sitl-mission/mission.py diff --git a/examples/mavlink2-bridge-sitl-mission/mission_long.py b/external/dora-mavlink2/examples-sitl-mission/mission_long.py similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/mission_long.py rename to external/dora-mavlink2/examples-sitl-mission/mission_long.py diff --git a/examples/mavlink2-bridge-sitl-mission/mission_rover.py b/external/dora-mavlink2/examples-sitl-mission/mission_rover.py similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/mission_rover.py rename to external/dora-mavlink2/examples-sitl-mission/mission_rover.py diff --git a/examples/mavlink2-bridge-sitl-mission/requirements.txt b/external/dora-mavlink2/examples-sitl-mission/requirements.txt similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/requirements.txt rename to external/dora-mavlink2/examples-sitl-mission/requirements.txt diff --git a/examples/mavlink2-bridge-sitl-mission/scripts/forward_to_qgc.py b/external/dora-mavlink2/examples-sitl-mission/scripts/forward_to_qgc.py similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/scripts/forward_to_qgc.py rename to external/dora-mavlink2/examples-sitl-mission/scripts/forward_to_qgc.py diff --git a/examples/mavlink2-bridge-sitl-mission/scripts/start_mavlink_long.sh b/external/dora-mavlink2/examples-sitl-mission/scripts/start_mavlink_long.sh similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/scripts/start_mavlink_long.sh rename to external/dora-mavlink2/examples-sitl-mission/scripts/start_mavlink_long.sh diff --git a/examples/mavlink2-bridge-sitl-mission/scripts/start_rover.sh b/external/dora-mavlink2/examples-sitl-mission/scripts/start_rover.sh similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/scripts/start_rover.sh rename to external/dora-mavlink2/examples-sitl-mission/scripts/start_rover.sh diff --git a/examples/mavlink2-bridge-sitl-mission/scripts/start_sitl.sh b/external/dora-mavlink2/examples-sitl-mission/scripts/start_sitl.sh similarity index 100% rename from examples/mavlink2-bridge-sitl-mission/scripts/start_sitl.sh rename to external/dora-mavlink2/examples-sitl-mission/scripts/start_sitl.sh diff --git a/examples/mavlink2-bridge/README.md b/external/dora-mavlink2/examples/README.md similarity index 100% rename from examples/mavlink2-bridge/README.md rename to external/dora-mavlink2/examples/README.md diff --git a/examples/mavlink2-bridge/dataflow-cxx.yml b/external/dora-mavlink2/examples/dataflow-cxx.yml similarity index 100% rename from examples/mavlink2-bridge/dataflow-cxx.yml rename to external/dora-mavlink2/examples/dataflow-cxx.yml diff --git a/examples/mavlink2-bridge/dataflow-python.yml b/external/dora-mavlink2/examples/dataflow-python.yml similarity index 100% rename from examples/mavlink2-bridge/dataflow-python.yml rename to external/dora-mavlink2/examples/dataflow-python.yml diff --git a/examples/mavlink2-bridge/dataflow-rust.yml b/external/dora-mavlink2/examples/dataflow-rust.yml similarity index 100% rename from examples/mavlink2-bridge/dataflow-rust.yml rename to external/dora-mavlink2/examples/dataflow-rust.yml diff --git a/examples/mavlink2-bridge/heartbeat-emitter/Cargo.toml b/external/dora-mavlink2/examples/heartbeat-emitter/Cargo.toml similarity index 100% rename from examples/mavlink2-bridge/heartbeat-emitter/Cargo.toml rename to external/dora-mavlink2/examples/heartbeat-emitter/Cargo.toml diff --git a/examples/mavlink2-bridge/heartbeat-emitter/src/main.rs b/external/dora-mavlink2/examples/heartbeat-emitter/src/main.rs similarity index 100% rename from examples/mavlink2-bridge/heartbeat-emitter/src/main.rs rename to external/dora-mavlink2/examples/heartbeat-emitter/src/main.rs diff --git a/examples/mavlink2-bridge/mavlink-sim/Cargo.toml b/external/dora-mavlink2/examples/mavlink-sim/Cargo.toml similarity index 100% rename from examples/mavlink2-bridge/mavlink-sim/Cargo.toml rename to external/dora-mavlink2/examples/mavlink-sim/Cargo.toml diff --git a/examples/mavlink2-bridge/mavlink-sim/src/main.rs b/external/dora-mavlink2/examples/mavlink-sim/src/main.rs similarity index 100% rename from examples/mavlink2-bridge/mavlink-sim/src/main.rs rename to external/dora-mavlink2/examples/mavlink-sim/src/main.rs diff --git a/examples/mavlink2-bridge/requirements.txt b/external/dora-mavlink2/examples/requirements.txt similarity index 100% rename from examples/mavlink2-bridge/requirements.txt rename to external/dora-mavlink2/examples/requirements.txt diff --git a/examples/mavlink2-bridge/run-cxx.rs b/external/dora-mavlink2/examples/run-cxx.rs similarity index 100% rename from examples/mavlink2-bridge/run-cxx.rs rename to external/dora-mavlink2/examples/run-cxx.rs diff --git a/examples/mavlink2-bridge/telemetry-printer-cxx/main.cc b/external/dora-mavlink2/examples/telemetry-printer-cxx/main.cc similarity index 100% rename from examples/mavlink2-bridge/telemetry-printer-cxx/main.cc rename to external/dora-mavlink2/examples/telemetry-printer-cxx/main.cc diff --git a/examples/mavlink2-bridge/telemetry-printer-rust/Cargo.toml b/external/dora-mavlink2/examples/telemetry-printer-rust/Cargo.toml similarity index 100% rename from examples/mavlink2-bridge/telemetry-printer-rust/Cargo.toml rename to external/dora-mavlink2/examples/telemetry-printer-rust/Cargo.toml diff --git a/examples/mavlink2-bridge/telemetry-printer-rust/src/main.rs b/external/dora-mavlink2/examples/telemetry-printer-rust/src/main.rs similarity index 100% rename from examples/mavlink2-bridge/telemetry-printer-rust/src/main.rs rename to external/dora-mavlink2/examples/telemetry-printer-rust/src/main.rs diff --git a/examples/mavlink2-bridge/telemetry_printer.py b/external/dora-mavlink2/examples/telemetry_printer.py similarity index 100% rename from examples/mavlink2-bridge/telemetry_printer.py rename to external/dora-mavlink2/examples/telemetry_printer.py diff --git a/scripts/smoke-all.sh b/scripts/smoke-all.sh index f42441c2b1..ef824b0992 100755 --- a/scripts/smoke-all.sh +++ b/scripts/smoke-all.sh @@ -141,13 +141,6 @@ cleanup_stale() { # and concurrent smoke runs already contend on port 6013 anyway. pkill -f "$TARGET_DIR/debug/dora .*(coordinator|daemon)" > /dev/null 2>&1 || true pkill -f "$TARGET_DIR/debug/dora-(coordinator|daemon|runtime)" > /dev/null 2>&1 || true - # Reap orphan example nodes that bind a FIXED port -- e.g. the MAVLink bridge - # on udp:14550. If one lingers (hard-killed local run, or not self-exiting on - # coordinator loss), the next mavlink example dies with "Address already in - # use". These patterns only match the mavlink example binaries, so they're - # no-ops for every other example. - pkill -f "$TARGET_DIR/(debug|release)/dora-mavlink2-bridge-node" > /dev/null 2>&1 || true - pkill -f "$TARGET_DIR/(debug|release)/mavlink2-bridge-example" > /dev/null 2>&1 || true sleep 0.5 } @@ -411,20 +404,6 @@ if [ "$RUN_RUST" = true ]; then 2>&1 | tail -1 fi -# mavlink2-bridge example: Rust variant runs in --rust-only mode; Python -# variant adds the python printer; C++ variant is its own cargo example. -# Build the Rust nodes (sim + emitter + bridge + rust printer) whenever -# RUN_RUST is on; they're shared across the rust + python YAML variants. -if [ "$RUN_RUST" = true ]; then - echo "Building mavlink2-bridge example nodes..." - cargo build \ - -p dora-mavlink2-bridge-node \ - -p mavlink2-bridge-example-mavlink-sim \ - -p mavlink2-bridge-example-heartbeat-emitter \ - -p mavlink2-bridge-example-telemetry-printer-rust \ - 2>&1 | tail -1 -fi - # --------------------------------------------------------------------------- # Rust examples # --------------------------------------------------------------------------- @@ -594,22 +573,8 @@ if [ "$RUN_RUST" = true ] && [ "$RUN_PYTHON" = true ]; then echo "=== Cross-language examples (local) ===" run_local "local-cross-language-rust-to-python" "examples/cross-language/rust-to-python.yml" 15 run_local "local-cross-language-python-to-rust" "examples/cross-language/python-to-rust.yml" 15 - - echo "" - echo "=== MAVLink 2 bridge — Python variant ===" - run_networked "mavlink2-bridge-python" "examples/mavlink2-bridge/dataflow-python.yml" 30 - run_local "local-mavlink2-bridge-python" "examples/mavlink2-bridge/dataflow-python.yml" 10 else log_skip "cross-language" "requires both Rust and Python" - log_skip "mavlink2-bridge-python" "requires both Rust and Python" -fi - -# MAVLink 2 bridge — Rust variant runs without Python at all. -if [ "$RUN_RUST" = true ]; then - echo "" - echo "=== MAVLink 2 bridge — Rust variant ===" - run_networked "mavlink2-bridge-rust" "examples/mavlink2-bridge/dataflow-rust.yml" 30 - run_local "local-mavlink2-bridge-rust" "examples/mavlink2-bridge/dataflow-rust.yml" 10 fi # --------------------------------------------------------------------------- @@ -634,12 +599,10 @@ log_skip "dynamic-add-remove" "interactive dynamic topology CLI" log_skip "dynamic-agent-tools" "interactive dynamic topology CLI" log_skip "rust-dynamic-add-remove" "dynamic topology lifecycle (covered by node-lifecycle-e2e)" log_skip "cxx-dynamic-add-remove" "C++/CMake + dynamic topology (covered by node-lifecycle-e2e)" -log_skip "mavlink2-bridge-cxx" "C++ + Arrow C++ libs (covered by cxx examples job)" log_skip "cpu-affinity-probe" "Linux-only cpu_affinity (covered by example-smoke.rs + nightly)" log_skip "error-propagation" "deliberate node failure demo (success == nonzero exit)" log_skip "python-parquet-recorder" "webcam + opencv" log_skip "python-yolo-detection" "webcam + YOLO + torch" -log_skip "mavlink2-bridge-sitl-mission" "external ArduPilot SITL on udp:14550" log_skip "ros2-comparison" "ROS2 rclpy comparison (and dataflow.yml node paths are stale, see #issue)" # --------------------------------------------------------------------------- diff --git a/tests/example-smoke.rs b/tests/example-smoke.rs index a1d3d77d39..77bf220ea9 100644 --- a/tests/example-smoke.rs +++ b/tests/example-smoke.rs @@ -23,7 +23,6 @@ static BUILD_ACTION_NODES: Once = Once::new(); static BUILD_CROSS_LANGUAGE_NODES: Once = Once::new(); static BUILD_VALIDATED_PIPELINE_NODES: Once = Once::new(); static BUILD_QUEUE_LATEST_RUST: Once = Once::new(); -static BUILD_MAVLINK2_BRIDGE_NODES: Once = Once::new(); fn dora_bin() -> String { let manifest = env!("CARGO_MANIFEST_DIR"); @@ -1524,83 +1523,6 @@ fn smoke_local_queue_size_latest_data_python() { ); } -fn ensure_mavlink2_bridge_nodes_built() { - BUILD_MAVLINK2_BRIDGE_NODES.call_once(|| { - let status = Command::new("cargo") - .args([ - "build", - "-p", - "dora-mavlink2-bridge-node", - "-p", - "mavlink2-bridge-example-mavlink-sim", - "-p", - "mavlink2-bridge-example-heartbeat-emitter", - "-p", - "mavlink2-bridge-example-telemetry-printer-rust", - ]) - .status() - .expect("failed to run cargo build for mavlink2-bridge example"); - assert!(status.success(), "failed to build mavlink2-bridge nodes"); - }); -} - -// --------------------------------------------------------------------------- -// MAVLink 2 bridge example (#1786) -// -// Three variants share the same bridge + UDP simulator + Rust HEARTBEAT -// emitter; only the consumer that reads `bridge/heartbeat` differs: -// -// * dataflow-rust.yml -- pure Rust (no Python toolchain required) -// * dataflow-python.yml -- Python printer via `--uv` -// * dataflow-cxx.yml -- C++ printer; built+run via the -// `mavlink2-bridge-cxx` cargo example -// (mirrors `cxx-arrow-dataflow`). NOT in -// the smoke harness — see audit table. -// -// UDP avoids `TIME_WAIT` between successive smoke runs and keeps these -// tests CI-friendly without a SITL/MAVProxy dependency. -// --------------------------------------------------------------------------- - -#[test] -fn smoke_mavlink2_bridge_rust() { - ensure_mavlink2_bridge_nodes_built(); - run_smoke_test( - "mavlink2-bridge-rust", - "examples/mavlink2-bridge/dataflow-rust.yml", - Duration::from_secs(30), - ); -} - -#[test] -fn smoke_local_mavlink2_bridge_rust() { - ensure_mavlink2_bridge_nodes_built(); - run_smoke_test_local( - "local-mavlink2-bridge-rust", - "examples/mavlink2-bridge/dataflow-rust.yml", - 10, - ); -} - -#[test] -fn smoke_mavlink2_bridge_python() { - ensure_mavlink2_bridge_nodes_built(); - run_smoke_test( - "mavlink2-bridge-python", - "examples/mavlink2-bridge/dataflow-python.yml", - Duration::from_secs(30), - ); -} - -#[test] -fn smoke_local_mavlink2_bridge_python() { - ensure_mavlink2_bridge_nodes_built(); - run_smoke_test_local( - "local-mavlink2-bridge-python", - "examples/mavlink2-bridge/dataflow-python.yml", - 10, - ); -} - fn ensure_queue_latest_rust_built() { BUILD_QUEUE_LATEST_RUST.call_once(|| { let status = Command::new("cargo") @@ -2066,12 +1988,6 @@ fn smoke_memory_pool_cuda2cuda() { // | | testing-capabilities.md | | // | python-operator-dataflow | covered: `cli` job .github/workflows/ci.yml:393 | covered | // | rust-dataflow-git | covered: `examples` job (3 OS) | covered | -// | mavlink2-bridge-cxx | covered: `examples` job via | covered | -// | | `[[example]] mavlink2-bridge-cxx` (cargo run | | -// | | --example), same shape as `cxx-arrow-dataflow` | | -// | mavlink2-bridge-sitl- | blocker: needs ArduPilot SITL | — | -// | mission | (Ubuntu / macOS only, local-only by design; | | -// | | see examples/mavlink2-bridge-sitl-mission/README) | | // // "Covered" rows are listed so future refactors don't assume the examples // are entirely unexercised — they run in other CI jobs, just not this file.