Skip to content

fix(discovery): announce all participant locators on multi-homed hosts #177

fix(discovery): announce all participant locators on multi-homed hosts

fix(discovery): announce all participant locators on multi-homed hosts #177

Workflow file for this run

name: ci
on:
push:
branches: [main]
pull_request:
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: "0"
RUSTFLAGS: "-D warnings"
jobs:
# ---------------------------------------------------------------------------
# Lint & format — must pass before anything else runs.
# Maps to docs/architecture/04_safety_by_architecture.md §3.2.
# ---------------------------------------------------------------------------
fmt:
name: rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --all -- --check
clippy:
name: clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
# NOTE: no `--all-features` here. `--all-features` activates the opt-in
# `wolfcrypt` backend, whose `wolfcrypt-sys` build needs libwolfssl /
# WOLFSSL_SRC — not present on the hosted GitHub runner (it panics:
# "required wolfcrypt source not found"). wolfCrypt is an opt-in,
# GPL-3.0/wolfSSL-commercial backend; the FULL `--all-features` clippy
# (including wolfcrypt, aws-lc, fips) runs on the GitLab CI, whose ci-rust
# image ships libwolfssl. This public mirror lints default features
# (ring backend) + all targets, which is green without any system lib.
- run: cargo clippy --workspace --all-targets -- -D warnings
deny:
name: cargo-deny (licenses, advisories, bans)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
# rust-toolchain.toml pins 1.88.0; the cargo-deny-action Docker image
# only has 1.85.0-musl pre-installed. The rust-version input forces
# the action to rustup-install the pinned version before cargo-deny.
- uses: EmbarkStudios/cargo-deny-action@v2
with:
command: check
rust-version: "1.88.0"
# ---------------------------------------------------------------------------
# jscpd — copy/paste-detection gate (catches code duplication).
#
# Why: a duplicate C# `ExtensibilityKind` enum slipped in and only surfaced
# at a build break. jscpd is language-agnostic (Rust, C#, Java, Kotlin, TS,
# Go, Zig, …) so it covers the WHOLE codebase, not just the Rust crates.
#
# Config lives in `.jscpd.json` at the repo root — `minTokens` (50), the
# `ignore` globs (build/generated output, content mirrors like docs/website,
# the release mirror, and intentional teaching duplication under
# examples/tutorials), and the `threshold`: the max duplicated-LINES % over
# all scanned files. The threshold (8.5) sits ~0.5pp above the measured
# cleaned baseline (8.01% lines on main, 2026-07), so the gate is GREEN
# today but trips on new large-scale copy-paste (a duplicated file / module
# / enum block — the ExtensibilityKind failure class). It is a RATCHET:
# lower it as the known real clones (crates/idl-* cross-backend emitters,
# the coap/mqtt/websocket bridge daemons, crates/ts-node ↔ crates/ts-wasm
# cdr code) get de-duplicated. Do NOT raise it to paper over new duplication.
#
# To whitelist a legitimate clone: add a narrow glob to `.jscpd.json`
# `ignore`, or wrap the block in `jscpd:ignore-start` / `jscpd:ignore-end`
# comments. `.jscpd.json` is auto-discovered; its `threshold` reporter exits
# non-zero when duplication% exceeds the threshold.
#
# This job MUST stay in sync with the `jscpd` job in .gitlab-ci.yml (the
# authoritative root/GitLab CI) — otherwise the mirror sync re-diverges the
# gate.
# ---------------------------------------------------------------------------
jscpd:
name: jscpd (copy/paste detection)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v4
with:
node-version: "22"
- run: npx --yes jscpd@5 .
# ---------------------------------------------------------------------------
# cpd — the SECOND, token-based copy/paste gate (PMD CPD), run alongside the
# line-based `jscpd` job above. Two independent detectors on purpose: jscpd
# tokenizes by lines, PMD CPD by language tokens, so each catches clones the
# other misses (notably small same-language clones — the C#
# `ExtensibilityKind` class — that a repo-wide line-% budget does not fail
# on).
#
# All logic (per-language minimum-tokens + committed baselines, the shared
# exclude list mirroring .jscpd.json, and the PMD download) lives in ONE
# script, scripts/cpd-gate.sh, called identically here and in the GitLab CI
# so the gate can't drift. PMD 7.x is a JVM tool → setup-java; the script
# fetches pmd-dist at runtime (never committed). To re-baseline:
# `scripts/cpd-gate.sh --update-baseline` and copy the numbers into the file.
#
# This job MUST stay in sync with the `cpd` job in .gitlab-ci.yml (the
# authoritative root/GitLab CI) — otherwise the mirror sync re-diverges it.
# ---------------------------------------------------------------------------
cpd:
name: cpd (token-based copy/paste detection)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
- run: bash scripts/cpd-gate.sh
# ---------------------------------------------------------------------------
# Build & test matrix — Full profile on Linux x86_64 and ARM64.
# Phase-0 scope per docs/architecture/06_roadmap.md §3.
# Windows, macOS, QNX, and embedded targets land with later phases.
# ---------------------------------------------------------------------------
build-test:
name: build & test (${{ matrix.target }})
needs: [fmt, clippy]
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
runner: ubuntu-latest
cross: false
- target: aarch64-unknown-linux-gnu
runner: ubuntu-latest
cross: true
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
- name: Install cross
if: matrix.cross
run: cargo install cross --locked
- name: Build
run: |
if [ "${{ matrix.cross }}" = "true" ]; then
# Exclude iceoryx2-oracle-consumer from the cross build: it is a
# publish=false, x86_64-Linux-only oracle tool that hard-depends on
# the upstream iceoryx2 crate, whose iceoryx2-pal-posix runs bindgen
# and fails to cross-compile for aarch64 (clang can't find stddef.h
# in the cross sysroot). Not part of the shipped library and
# meaningless on an aarch64 embedded target.
cross build --workspace --exclude iceoryx2-oracle-consumer --target ${{ matrix.target }}
else
cargo build --workspace --target ${{ matrix.target }}
fi
- name: Test (non-DCPS workspace, parallel)
if: ${{ !matrix.cross }}
run: cargo test --workspace --exclude zerodds-dcps --target ${{ matrix.target }}
- name: Test (DCPS, serial — UDP multicast tests share one multicast group per binary)
if: ${{ !matrix.cross }}
run: cargo test -p zerodds-dcps --target ${{ matrix.target }} -- --test-threads=1
# ---------------------------------------------------------------------------
# tsn-live — live AF_PACKET transport (DDS-TSN 1.0 Annex A, EtherType
# 0x88B5). The workspace test job builds WITHOUT the transport-tsn
# `live` feature, so socket.rs (target_os=linux) and its frame logic
# are otherwise never compiled/run. GitHub ubuntu runners allow
# `sudo ip link add` (veth) + AF_PACKET, so unlike the internal GitLab
# runner the real veth RTPS round trip executes here. See
# internal/ci/tsn-live.md.
# ---------------------------------------------------------------------------
tsn-live:
name: TSN live AF_PACKET transport
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Build socket.rs + run live_frame unit tests
run: cargo test -p zerodds-transport-tsn --features live
- name: Real RTPS round trip over a veth pair (needs root)
run: |
sudo -E "$(command -v cargo)" test -p zerodds-transport-tsn \
--features live --test veth_loopback -- --ignored --test-threads=1
# ---------------------------------------------------------------------------
# No-std build for the Safe-Subset crates.
# Verifies the Safe-Subset contract from
# docs/architecture/04_safety_by_architecture.md §2.
# Scope widens as Safe-Subset crates gain real content.
# ---------------------------------------------------------------------------
no-std:
name: no_std build (safe subset)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
targets: thumbv7em-none-eabihf
- uses: Swatinem/rust-cache@v2
- name: Build safe-subset crates for bare-metal
run: |
cargo build --target thumbv7em-none-eabihf \
-p zerodds-foundation \
-p zerodds-cdr \
-p zerodds-types \
-p zerodds-qos \
-p zerodds-rtps \
-p zerodds-discovery \
-p zerodds-transport \
-p zerodds-xrce-client \
--no-default-features
# ---------------------------------------------------------------------------
# Coverage — cargo-llvm-cov, line/region/function coverage.
# Branch coverage requires nightly Rust and will be added later as a separate
# nightly job. Target bar: 99% (soft gate, no merge block
# during the bootstrap era, see memory/project_quality_bar_branch_coverage).
# ---------------------------------------------------------------------------
coverage:
name: coverage (cargo-llvm-cov)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- uses: Swatinem/rust-cache@v2
- name: Install cargo-llvm-cov
run: cargo install cargo-llvm-cov --version 0.6.21 --locked
- name: Run coverage
# `--lib --bins`: measures only library and binary code paths
# (unit tests in the crates themselves). Integration tests
# (`tests/*.rs`) are end-to-end discovery tests and primarily
# yield line coverage, hardly any branch coverage. They also
# have E2E timing dependencies under cov instrumentation
# (see docs/timing-architecture-audit.md prio 4).
# build-test x86_64 + aarch64 still run the integration tests
# — coverage measures code, build-test measures behavior.
run: cargo llvm-cov --workspace --lib --bins --lcov --output-path lcov.info
- name: Coverage summary
run: cargo llvm-cov --workspace --lib --bins --summary-only
- name: Upload lcov artifact
uses: actions/upload-artifact@v7
with:
name: lcov
path: lcov.info
retention-days: 30