Skip to content
Merged
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
13 changes: 13 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,16 @@ jobs:

- name: Run tests
run: pixi run test

- name: Install Windows ROS activation test environment
if: runner.os == 'Windows'
run: >-
pixi exec --spec conda -- conda env create --yes
--prefix "${{ runner.temp }}/vinca-ros-activation"
--file tests/windows/environment.yml

- name: Test ROS activation with conda and Git Bash
if: runner.os == 'Windows'
env:
VINCA_WINDOWS_ROS_PREFIX: ${{ runner.temp }}/vinca-ros-activation
run: pixi run pytest -v vinca/test_windows_activation.py
24 changes: 24 additions & 0 deletions tests/windows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
The Windows CI job installs `environment.yml` into a disposable conda environment
and runs `vinca/test_windows_activation.py` using Git for Windows Bash. The test
renders and installs the PR's hooks, then activates the environment through real
conda. It checks the conda-build guard, ROS variables, native Python's ament index
lookup, repeated activation, and deactivation. It restores the installed hooks
afterward. An additional package with real `.dsv` hooks exercises PATH prepends,
appends and assignments, PYTHONPATH prepends, a CMAKE_PREFIX_PATH append, and paths
containing spaces. The assignment case replaces the inherited PATH with an
explicit Windows path list and checks its exact contents and order.

To reproduce in PowerShell from the repository root:

```powershell
pixi exec --spec conda -- conda env create --yes --prefix "$PWD/.pixi/ros-activation" --file tests/windows/environment.yml
$env:VINCA_WINDOWS_ROS_PREFIX = "$PWD/.pixi/ros-activation"
pixi run pytest -v vinca/test_windows_activation.py
```

The integration test skips unless `VINCA_WINDOWS_ROS_PREFIX` is set, and skips on
non-Windows platforms. Once a prefix is supplied, missing dependencies or Git Bash
fail the test rather than skipping it. Use a disposable environment: the test
temporarily replaces its ros_workspace activation hooks.

This test does not run a full rclcpp CMake build.
11 changes: 11 additions & 0 deletions tests/windows/environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: vinca-ros-activation
channels:
- robostack-jazzy
- conda-forge
- nodefaults
dependencies:
- python=3.12
- conda
- ros-jazzy-ros-workspace
- ros-jazzy-ros-environment
- ros-jazzy-ament-index-python
101 changes: 85 additions & 16 deletions vinca/templates/activate.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,92 @@
# exit 0;
# fi

# Not sure if this is necessary on UNIX?
# export QT_PLUGIN_PATH=$CONDA_PREFIX\plugins
case "$OSTYPE" in
msys*|cygwin*)
# Windows: conda runs this script (not activate.bat) when the environment
# is activated from Git Bash / MSYS2 / Cygwin. The ROS packages only ship
# .bat/.dsv environment hooks there (under %CONDA_PREFIX%\Library), so do
# what activate.bat -> local_setup.bat does: let ament's
# _local_setup_util.py evaluate every package's .dsv hooks, in "sh" mode,
# and apply the result. Values stay in Windows form (C:\...;C:\...) since
# native Windows programs (python, cmake, ros2) read them; only PATH is
# converted to the form the shell itself uses.
if [ -n "${SYS_PREFIX:-}" ]; then
# Don't do anything when we are in conda build (as activate.bat).
:
elif ! command -v cygpath > /dev/null 2>&1; then
echo "Not activating ROS: cygpath not found" >&2
else
# Keep an absolute path: a .dsv assignment may remove cygpath from PATH.
_ros_cygpath="$(command -v cygpath)"
_ros_prefix_w="$(cygpath -w "$CONDA_PREFIX")"
_ros_python="$(cygpath -u "$_ros_prefix_w\\python.exe")"
_ros_util="$(cygpath -u "$_ros_prefix_w\\Library\\_local_setup_util.py")"

if [ "$CONDA_BUILD" = "1" -a "$target_platform" != "$build_platform" ]; then
# ignore sourcing
echo "Not activating ROS when cross-compiling";
else
source $CONDA_PREFIX/setup.sh
fi
export QT_PLUGIN_PATH="$_ros_prefix_w\\Library\\plugins"
unset PYTHONHOME

case "$OSTYPE" in
darwin*) export ROS_OS_OVERRIDE="conda:osx";;
linux*) export ROS_OS_OVERRIDE="conda:linux";;
esac
if [ -f "$_ros_util" ]; then
while IFS= read -r _ros_line; do
case "$_ros_line" in
"export "*"#:}")
# strip a leading separator: ';' on Windows, not ':'
_ros_line="${_ros_line%#:\}}#;}"
;;
"export "*"%:}")
# strip a trailing separator: ';' on Windows, not ':'
_ros_line="${_ros_line%\%:\}}%;}"
;;
esac
case "$_ros_line" in
"export PATH="*)
# ament emits Windows lists even in sh mode. Evaluate against a
# Windows PATH in a subshell, then convert the complete result.
# This handles prepends, appends and assignments without mixing
# semicolons, drive-letter colons and Bash's ':' separators.
_ros_value="$(
PATH="$("$_ros_cygpath" -w -p "$PATH")"
eval "$_ros_line"
printf '%s' "$PATH"
)"
export PATH="$("$_ros_cygpath" -u -p "$_ros_value")"
;;
"export "*)
eval "$_ros_line"
;;
esac
done <<EOF
$("$_ros_python" "$_ros_util" sh | tr -d '\r')
EOF
fi

export ROS_OS_OVERRIDE="conda:win64"
export ROS_ETC_DIR="$_ros_prefix_w\\Library\\etc\\ros"
export AMENT_PREFIX_PATH="$_ros_prefix_w\\Library"
export AMENT_PYTHON_EXECUTABLE="$_ros_prefix_w\\python.exe"
unset _ros_prefix_w _ros_python _ros_util _ros_line _ros_value _ros_cygpath
fi
;;
*)
# Not sure if this is necessary on UNIX?
# export QT_PLUGIN_PATH=$CONDA_PREFIX\plugins

export ROS_ETC_DIR=$CONDA_PREFIX/etc/ros
export AMENT_PREFIX_PATH=$CONDA_PREFIX
if [ "$CONDA_BUILD" = "1" -a "$target_platform" != "$build_platform" ]; then
# ignore sourcing
echo "Not activating ROS when cross-compiling";
else
source $CONDA_PREFIX/setup.sh
fi

# Looks unnecessary for UNIX
# unset PYTHONHOME=
case "$OSTYPE" in
darwin*) export ROS_OS_OVERRIDE="conda:osx";;
linux*) export ROS_OS_OVERRIDE="conda:linux";;
esac

export ROS_ETC_DIR=$CONDA_PREFIX/etc/ros
export AMENT_PREFIX_PATH=$CONDA_PREFIX

# Looks unnecessary for UNIX
# unset PYTHONHOME=
;;
esac
2 changes: 2 additions & 0 deletions vinca/templates/bld_catkin.bat.in
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ if "%PKG_NAME%" == "@(ros_package_prefix)-catkin" (
if "%PKG_NAME%" == "@(ros_package_prefix)-ros-workspace" (
:: Copy the [de]activate scripts to %PREFIX%\etc\conda\[de]activate.d.
:: This will allow them to be run on environment activation.
:: The .sh scripts are what conda runs in Git Bash / MSYS2 / Cygwin.
for %%F in (activate deactivate) DO (
if not exist %PREFIX%\etc\conda\%%F.d mkdir %PREFIX%\etc\conda\%%F.d
copy %RECIPE_DIR%\%%F.bat %PREFIX%\etc\conda\%%F.d\%PKG_NAME%_%%F.bat
copy %RECIPE_DIR%\%%F.ps1 %PREFIX%\etc\conda\%%F.d\%PKG_NAME%_%%F.ps1
copy %RECIPE_DIR%\%%F.sh %PREFIX%\etc\conda\%%F.d\%PKG_NAME%_%%F.sh
)
)
11 changes: 11 additions & 0 deletions vinca/templates/deactivate.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,14 @@ unset ROS_OS_OVERRIDE
unset ROS_LOCALHOST_ONLY
unset ament_python_executable
unset RMW_IMPLEMENTATION

case "$OSTYPE" in
msys*|cygwin*)
# Windows (Git Bash / MSYS2 / Cygwin): also undo what activate.sh sets
# there, as deactivate.bat does.
unset PYTHONHOME
unset PYTHONPATH
unset QT_PLUGIN_PATH
unset AMENT_PYTHON_EXECUTABLE
;;
esac
Loading
Loading