Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 21 additions & 100 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ on:
branches: [ main ]

jobs:
no-ros:
name: ROS-independent Test
nix-matrix:
name: Generate Nix CI Matrix
runs-on: ubuntu-latest

outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand All @@ -23,63 +24,22 @@ jobs:
experimental-features = nix-command flakes
accept-flake-config = true

- name: Setup sccache
if: env.ACT != 'true'
uses: mozilla-actions/sccache-action@v0.0.9

- name: Check Nix formatting
run: |
nix fmt -- --check flake.nix

- name: Check Markdown formatting
run: |
nix develop '.#noRos-ci' -c markdownlint '**/*.md'

- name: Check Rust formatting
run: |
nix develop '.#noRos-ci' -c cargo fmt --all -- --check

- name: Clippy (default workspace)
run: |
nix develop '.#noRos-ci' -c cargo clippy --lib --bins --tests -- -D warnings

- name: Check default workspace
run: |
nix develop '.#noRos-ci' -c cargo check

- name: Build default workspace
run: |
nix develop '.#noRos-ci' -c cargo build

- name: Build examples without ROS dependencies
run: |
nix develop '.#noRos-ci' -c cargo build --example z_custom_message

- name: Run tests
run: |
nix develop '.#noRos-ci' -c cargo test

- name: Check ros-z-msgs with bundled messages (no ROS required)
run: |
nix develop '.#noRos-ci' -c cargo check -p ros-z-msgs
nix develop '.#noRos-ci' -c cargo check -p ros-z-msgs --features bundled_msgs
nix develop '.#noRos-ci' -c cargo check -p ros-z-msgs --features common_interfaces
- name: Setup Magic Nix Cache
uses: DeterminateSystems/magic-nix-cache-action@v8

- name: Build ros-z-msgs with individual bundled packages
- name: Generate CI matrix from flake
id: set-matrix
run: |
nix develop '.#noRos-ci' -c cargo build -p ros-z-msgs --no-default-features --features std_msgs
nix develop '.#noRos-ci' -c cargo build -p ros-z-msgs --no-default-features --features geometry_msgs
nix develop '.#noRos-ci' -c cargo build -p ros-z-msgs --no-default-features --features sensor_msgs
nix develop '.#noRos-ci' -c cargo build -p ros-z-msgs --no-default-features --features nav_msgs
set -euo pipefail
matrix="$(nix eval --json '.#githubActions.matrix')"
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"

with-ros:
name: ROS-dependent Test (${{ matrix.distro }})
nix-build:
name: ${{ matrix.attr }}
needs: nix-matrix
runs-on: ubuntu-latest
strategy:
matrix:
distro: [jazzy]
# distro: [jazzy, rolling] # Uncomment to test rolling when stable

matrix: ${{fromJSON(needs.nix-matrix.outputs.matrix)}}
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand All @@ -99,50 +59,11 @@ jobs:
with:
name: ros
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
skipPush: true

- name: Setup sccache
if: env.ACT != 'true'
uses: mozilla-actions/sccache-action@v0.0.9

- name: Check rcl-z
run: |
nix develop '.#${{ matrix.distro }}-ci' -c cargo check -p rcl-z

- name: Check ros-z-msgs (default bundled features)
run: |
nix develop '.#${{ matrix.distro }}-ci' -c cargo check -p ros-z-msgs

- name: Check ros-z-msgs with external messages
run: |
nix develop '.#${{ matrix.distro }}-ci' -c cargo check -p ros-z-msgs --features external_msgs
nix develop '.#${{ matrix.distro }}-ci' -c cargo check -p ros-z-msgs --features example_interfaces
# Push build outputs to cachix for reuse
skipPush: false

- name: Check ros-z-msgs with all messages (bundled + external)
run: |
nix develop '.#${{ matrix.distro }}-ci' -c cargo check -p ros-z-msgs --features all_msgs

- name: Check with protobuf feature
run: |
nix develop '.#${{ matrix.distro }}-ci' -c cargo check -p ros-z -p ros-z-msgs --features ros-z/protobuf,ros-z-msgs/protobuf

- name: Check ros-z (with rcl-z feature)
run: |
nix develop '.#${{ matrix.distro }}-ci' -c cargo check -p ros-z --features rcl-z

- name: Build ROS message examples
run: |
nix develop '.#${{ matrix.distro }}-ci' -c cargo build -p ros-z-msgs
nix develop '.#${{ matrix.distro }}-ci' -c cargo build --example twist_pub
nix develop '.#${{ matrix.distro }}-ci' -c cargo build --example battery_state_sub
nix develop '.#${{ matrix.distro }}-ci' -c cargo build --example laser_scan
nix develop '.#${{ matrix.distro }}-ci' -c cargo build --example z_srvcli --features external_msgs

- name: Build protobuf demo
run: |
nix develop '.#${{ matrix.distro }}-ci' -c cargo build -p protobuf_demo
- name: Setup Magic Nix Cache
uses: DeterminateSystems/magic-nix-cache-action@v8

# FIXME: This requires the installation of rmw_zenoh_cpp triggering a build from source...
# - name: Run unit tests
# run: |
# nix develop .#ci -c cargo test --all-features
- name: Run check
run: nix build -L '.#${{ matrix.attr }}'
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,12 @@ nix develop .#noRos-ci

**Note on `ros-z-msgs`:** This package can build without ROS installed! When
ROS is not available, it automatically falls back to using bundled message
definitions from the roslibrust repository. The build system searches for ROS
packages in this order:
definitions from the roslibrust git dependency. The build system searches for
ROS packages in this order:

1. System ROS installation (via `AMENT_PREFIX_PATH` or `CMAKE_PREFIX_PATH`)
2. Common ROS installation paths (`/opt/ros/{rolling,jazzy,iron,humble}`)
3. Local roslibrust checkout (`../../roslibrust/assets/`)
4. Roslibrust git dependency (`~/.cargo/git/checkouts/roslibrust-*/assets/`)
3. Roslibrust git dependency (`~/.cargo/git/checkouts/roslibrust-*/assets/`)

This allows `ros-z-msgs` to generate message types even in environments without
ROS 2 installed. The default `common_interfaces` feature includes `std_msgs`,
Expand Down
181 changes: 181 additions & 0 deletions ci.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# CI checks module
# This module defines all CI checks for ros-z project
{
pkgs,
self,
commonBuildInputs,
mkRosEnv,
exportEnvVars,
}:
let
# Vendor Cargo dependencies for sandboxed builds
cargoVendorDir = pkgs.rustPlatform.importCargoLock {
lockFile = ./Cargo.lock;
outputHashes = {
"cdr-encoding-0.10.2" = "sha256-bpo8Fu3Qp5TapzFFAvyRJdSiO50G3YBBTSJNV/cNa4Y=";
"roslibrust-0.16.0" = "sha256-qi4h1ksC/iLwK1uiUs6LU9CX3RDYVOd6E4SRdUAbqZo=";
};
};

# Fetch roslibrust git repo for assets directory (with submodules for ros2_common_interfaces)
roslibrustSrc = pkgs.fetchgit {
url = "https://github.com/YuanYuYuan/roslibrust";
rev = "f08547babb04c3b19a77af9a55a10b8148908e55"; # dev/ros-z branch
hash = "sha256-qi4h1ksC/iLwK1uiUs6LU9CX3RDYVOd6E4SRdUAbqZo=";
fetchSubmodules = true;
};
in
let
# Create a cargo check that runs in sandbox with vendored dependencies
mkCargoCheck =
{
name,
packages,
rosEnv ? null,
script,
extraAttrs ? { },
}:
pkgs.stdenv.mkDerivation (
{
name = "check-${name}";
src = self;
nativeBuildInputs = packages ++ [ pkgs.nixfmt-rfc-style ]; # For format checks
buildInputs = pkgs.lib.optional (rosEnv != null) rosEnv;

# Disable ROS setup hooks that interfere with Cargo builds
dontUseCmakeConfigure = true;
dontUseColconBuildSetup = true;

buildPhase = ''
# Export environment variables
${exportEnvVars}

# Disable sccache in sandbox (no HOME directory)
unset RUSTC_WRAPPER

# Setup ROS environment if provided
${pkgs.lib.optionalString (rosEnv != null) ''
export AMENT_PREFIX_PATH="${rosEnv}"
export CMAKE_PREFIX_PATH="${rosEnv}"
''}

# Setup vendored cargo dependencies
export CARGO_HOME=$(pwd)/.cargo
mkdir -p .cargo
cat > .cargo/config.toml <<EOF
[source.crates-io]
replace-with = "vendored-sources"

[source."https://github.com/YuanYuYuan/cdr-encoding"]
git = "https://github.com/YuanYuYuan/cdr-encoding"
branch = "feat/byte-buf"
replace-with = "vendored-sources"

[source."https://github.com/YuanYuYuan/roslibrust"]
git = "https://github.com/YuanYuYuan/roslibrust"
branch = "dev/ros-z"
replace-with = "vendored-sources"

[source.vendored-sources]
directory = "${cargoVendorDir}"
EOF

# Point build.rs to roslibrust assets from fetched git repo
export ROSLIBRUST_ASSETS_DIR="${roslibrustSrc}/assets"

# Run checks
set -euo pipefail
${script}
'';

installPhase = ''
touch $out
'';

# Disable hardening for ROS compatibility
hardeningDisable = [ "all" ];
}
// extraAttrs
);
in
let
# Formatting check - runs first and other checks depend on this
formatting = mkCargoCheck {
name = "formatting";
packages = commonBuildInputs;
script = ''
echo "=== Nix Formatting ==="
nixfmt --check flake.nix

echo "=== Markdown Linting ==="
markdownlint '**/*.md'

echo "=== Rust Formatting ==="
cargo fmt --all -- --check
'';
};

# ROS-independent checks (linting, build, test)
no-ros = mkCargoCheck {
name = "no-ros";
packages = commonBuildInputs;
script = ''
# This check depends on formatting passing first
# Reference the formatting check to create a build-time dependency
echo "Prerequisites: ${formatting}"

echo "=== Build & Test ==="
cargo build --workspace --lib --bins --exclude rcl-z --exclude protobuf_demo
cargo test --workspace --lib --bins --exclude rcl-z --exclude protobuf_demo

echo "=== Lint ==="
cargo clippy --workspace --lib --bins --exclude rcl-z -- -D warnings

echo "=== Message Package Checks ==="
cargo check -p ros-z-msgs
cargo check -p ros-z-msgs --features bundled_msgs
cargo check -p ros-z-msgs --features common_interfaces

echo "=== Individual Message Packages ==="
cargo build -p ros-z-msgs --no-default-features --features std_msgs
cargo build -p ros-z-msgs --no-default-features --features geometry_msgs
cargo build -p ros-z-msgs --no-default-features --features sensor_msgs
cargo build -p ros-z-msgs --no-default-features --features nav_msgs
'';
};

# ROS-dependent checks for Jazzy distribution
with-ros-jazzy = mkCargoCheck {
name = "with-ros-jazzy";
packages = commonBuildInputs;
rosEnv = (mkRosEnv "jazzy").build;
script = ''
# This check depends on formatting passing first
# Reference the formatting check to create a build-time dependency
echo "Prerequisites: ${formatting}"

echo "=== RCL Bindings ==="
cargo check -p rcl-z

echo "=== Message Packages ==="
cargo check -p ros-z-msgs
cargo check -p ros-z-msgs --features external_msgs
cargo check -p ros-z-msgs --features example_interfaces
cargo check -p ros-z-msgs --features all_msgs

echo "=== Feature Checks ==="
cargo check -p ros-z -p ros-z-msgs --features ros-z/protobuf,ros-z-msgs/protobuf
cargo check -p ros-z --features rcl-z

echo "=== Build Examples ==="
cargo build -p ros-z-msgs
cargo build --examples
cargo build --example z_srvcli --features external_msgs
cargo build -p protobuf_demo
'';
};
in
{
# Export all checks
inherit formatting no-ros with-ros-jazzy;
}
21 changes: 21 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading