ROS 2 Windows CI on GitHub Actions: current options and a Pixi-based pattern

I’m trying to understand what we should currently recommend for ROS 2 projects that want to run a real Windows CI job on GitHub Actions, including both build and tests.

There are several existing actions and examples, but their Windows behavior is somewhat different from Linux. I recently compared a few approaches with ROS 2 Lyrical in a small AI-assisted smoke-test repository, and thought it might be useful to summarize what I found and ask whether there is already a preferred approach.

What I found

action-ros-ci

action-ros-ci@v0.4 currently has:

const doTests = !isWindows;

so colcon test is intentionally skipped on Windows. The related background seems to be ros-tooling/action-ros-ci#712.

This makes it useful for some Windows build jobs, but not for CI whose purpose is explicitly to verify tests.

setup-ros

I also tried setup-ros@v0.7 with Lyrical.

In this experiment, it selected the April 30 Lyrical beta binary and ended up combining the GitHub-hosted Python 3.12 environment with an older colcon/Python toolchain.

That caused plugin-loading errors involving removed Python APIs such as pkgutil.ImpImporter and distutils. More importantly, the job still completed successfully with effectively:

Summary: 0 packages finished
...
Summary: 0 tests, 0 errors, 0 failures, 0 skipped

This may be specific to this Lyrical configuration, and I may be missing an intended version pin or setup. However, the false-green result seems worth being aware of.

Pinned ROS 2 binary + Pixi

The approach that worked most consistently in my experiment was:

  1. Download a known ROS 2 Windows binary release.

  2. Use the pixi.toml provided with the ROS 2 source/release environment.

  3. Run pixi install.and preinstall_setup_windows.py.

  4. Enter the Visual Studio developer environment and source ROS 2.

  5. Run colcon build, colcon test, and colcon test-result explicitly.

For example, this workflow uses the 2026-08-07 Lyrical Windows binary and successfully runs launch tests against Fast DDS, Cyclone DDS, and Zenoh.

There are also existing Windows CI examples with a similar shape:

They are not exactly equivalent use cases—the ros-controls workflow, for example, is primarily a build workflow—but they suggest that using the ROS binary environment together with Pixi is already a practical pattern.

Possible recommendation?

For ROS 2 distributions that provide/support the Pixi environment, I wonder whether the current practical recommendation could be something along these lines:

Download a known ROS 2 Windows binary, reproduce its dependency environment with Pixi, and run colcon build/test explicitly.

It has the advantage that the dependency environment stays close to the one used for the ROS 2 binary itself, while the workflow remains explicit about whether tests are actually executed.

One additional safeguard may be worth recommending regardless of the setup: CI should fail if an expected package or test is not discovered. A green Windows job that actually ran zero tests is particularly easy to overlook.

A few questions remain:

  • Is there already a maintained action or reusable workflow that encapsulates this pattern?

  • Is there a recommended way to resolve a stable distro-specific Windows binary rather than hard-coding a dated release URL? For the experiment above I pinned Lyrical 2026-08-07.

  • Is Windows test execution expected to return to action-ros-ci, or is another approach preferred?

  • For distributions that do not provide the Pixi setup, what is the recommended Windows CI environment today?

If there is already a preferred solution, I would be interested in using and documenting that instead. Otherwise, it may be useful to turn the working Pixi-based pattern into a small reusable example so individual projects do not need to rediscover the same Windows setup details.

Related links

1 Like

I have actually been iterating on this in spare time (with my friend :sparkles:Bob :sparkles:) here: Add a GitHub Actions workflow that builds in the pixi environment by mjcarroll · Pull Request #4 · mjcarroll/ros2 · GitHub

I have a few goals here:

  • Greatly accelerate Windows CI builds by using more aggressive caching
  • Make sure that we support linux and linux arm64, with macOS as a stretch goal via pixi
  • Create Windows “fat binary” artifacts with a regularly updated pixi.lock file so that we can have stable release binaries.

I have been iterating on this with @KimMcG so far, but if you are interested, would appreciate any input/insights that you have.

1 Like

It takes a lot of effort to maintain Windows support for action-ros-ci and setup-ros given the slow feedback loop with GitHub Actions and the finicky nature of Windows (in my experience), so it has definitely fallen behind.

Now that we have Pixi, and now that Pixi is the recommended way to install ROS 2 on Windows, setup-ros (#893) and action-ros-ci (#1043) should really just completely switch to it. PRs are welcome.

  • Is there a recommended way to resolve a stable distro-specific Windows binary rather than hard-coding a dated release URL? For the experiment above I pinned Lyrical 2026-08-07.

Not AFAIK, but I’m sure we could programmatically find the latest Windows from the ros2/ros2 releases in setup-ros using the GitHub API.

..turns out I opened an issue for exactly this 5 years ago: Detect and use latest binary releases on Windows & macOS · Issue #453 · ros-tooling/setup-ros · GitHub

1 Like

hi!

It is nice that you noticed the ros2-rust github windows action. I actually have set that one up for the project initially and usually it has worked quite nice! The only issue is, that if something breaks in that end (like now it is failing because of the updated pixi toml file), I have to dig into that github action to fix it myself… As I just recently realized.

Ideally it would be nice if we can coordinate this more on the existing gh actions or perhaps have some unified strategy here. Luckily we soon have a certain conference where some of us can come together around the table on this :eyes:

So to specifically answer your questions:

Is there already a maintained action or reusable workflow that encapsulates this pattern?

No, but there hopefully will be one soon

Is there a recommended way to resolve a stable distro-specific Windows binary rather than hard-coding a dated release URL? For the experiment above I pinned Lyrical 2026-08-07.

Sadly no, but you could in your case you could perhaps get a list of the latest tags/release names and be able to determine the latest release programmatically as @christophebedard said

Is Windows test execution expected to return to action-ros-ci, or is another approach preferred?

This is still very much under discussion… but it seems like the most logical approach to coordinate all of this effort in is to implement it into action-ros-ci.

For distributions that do not provide the Pixi setup, what is the recommended Windows CI environment today?

Currently this only relates to humble, which is still advised for the dependencies to be installed by chocolatey. This seems to be still the case in setup-ros action I saw

Sorry, seems like everything is still quite up in the air so a straight answer to your questions is difficult :sweat_smile:. But at least you know that we are thinking about this hard at the moment.

3 Likes

Thanks everyone for the comments and suggestions on this.

As a follow-up, while trying the Pixi-based Windows GitHub Actions setup, I found two issues around lint/test execution.

The first one is Pixi-specific: clang-tidy is currently not installed in the Pixi environment. I reported that here:

The second one is Windows-specific and relates to how lint tools discover executable files.

Both issues showed up while trying to run the same lint/test path on Windows that we normally expect on Linux.

If these two issues are addressed, I’m hoping that running the full test suite, including lint tests, in a Pixi-based Windows CI environment will become reasonably stable.

1 Like

Side note: In my Windows experiment with the prebuilt ROS 2 binary archive, the C++ launch tests failed under the default Debug configuration, while the Python tests passed. Building the test package with -DCMAKE_BUILD_TYPE=Release made the C++ tests pass. This appears to be related to an MSVC CRT/ABI mismatch between the test binaries (/MDd) and the prebuilt ROS 2 libraries (/MD), so the Windows CI build should make the Release configuration explicit.

Also, the current Windows binary installation documentation does not explicitly mention this, but the prebuilt ROS 2 binaries appear to require downstream C++ packages to use the Release MSVC runtime. For older distro like humble, it was explained in around here.