From 23d9f9a9ac457c9b03dcb85f5cad0a31df8e095b Mon Sep 17 00:00:00 2001 From: Filip Parag Date: Tue, 7 Dec 2021 21:03:03 +0100 Subject: [PATCH] Continuous integration (#29) Co-authored-by: Darko Lukic --- .github/workflows/ci.yml | 32 ++++++++++++++++++++++++++ .github/workflows/linter.yml | 24 +++++++++++++++++++ .gitignore | 4 ++++ README.md | 11 ++++++++- mep3_driver/launch/driver_launch.py | 13 +++++++---- mep3_driver/package.xml | 2 ++ mep3_simulation/launch/robot_launch.py | 30 +++++++++++++----------- mep3_simulation/package.xml | 1 - mep3_simulation/setup.py | 15 ++++++++---- mep3_simulation/test/test_copyright.py | 23 ------------------ mep3_simulation/test/test_flake8.py | 14 ----------- mep3_simulation/test/test_pep257.py | 14 ----------- 12 files changed, 106 insertions(+), 77 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/linter.yml delete mode 100644 mep3_simulation/test/test_copyright.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..104d9528c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +on: + pull_request: + types: [opened, synchronize, reopened, labeled, unlabeled] + +env: + WEBOTS_VERSION: 2021b + WEBOTS_OFFSCREEN: 1 + CI: 1 + DEBIAN_FRONTEND: noninteractive + QTWEBENGINE_DISABLE_SANDBOX: 1 + +jobs: + ros2: + name: Build and test ROS 2 packages + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: Install ROS2 + uses: ros-tooling/setup-ros@v0.2 + with: + required-ros-distributions: foxy + - name: Install Webots + run: | + sudo -E apt-get update + sudo -E apt-get install -y wget dialog apt-utils psmisc + wget "https://github.com/cyberbotics/webots/releases/download/R$WEBOTS_VERSION/webots_${WEBOTS_VERSION}_amd64.deb" + sudo -E apt-get install -y "./webots_${WEBOTS_VERSION}_amd64.deb" xvfb + - name: Build packages and run and tests + uses: ros-tooling/action-ros-ci@v0.2 + with: + target-ros2-distro: foxy diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 000000000..0f2bd18c6 --- /dev/null +++ b/.github/workflows/linter.yml @@ -0,0 +1,24 @@ +on: + pull_request: + types: [opened, synchronize, reopened, labeled, unlabeled] + +jobs: + linter: + name: Check code using Ament linter + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + linter: [flake8, pep257, xmllint] + package: [mep3_driver, mep3_simulation] + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: Install ROS2 + uses: ros-tooling/setup-ros@v0.2 + - name: Run ${{ matrix.linter }} linter for ${{ matrix.package }} + uses: ros-tooling/action-ros-lint@v0.1 + with: + distribution: foxy + linter: ${{ matrix.linter }} + package-name: ${{ matrix.package }} diff --git a/.gitignore b/.gitignore index 93c700e85..8182863a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ .vscode/ .idea/ +build/ +install/ +log/ +**.pyc diff --git a/README.md b/README.md index cafa318f6..7fca096de 100644 --- a/README.md +++ b/README.md @@ -56,4 +56,13 @@ ros2 run teleop_twist_keyboard teleop_twist_keyboard To launch simulation with `rviz` and `nav2` run ```sh ros2 launch mep3_simulation robot_launch.py rviz:=true nav:=true -``` \ No newline at end of file +``` + +## Testing + +- Change working directory to `foxy_ws` +- Run the following command: +```sh +source /opt/ros/foxy/local_setup.bash +colcon test --event-handlers console_cohesion+ --return-code-on-test-failure +``` diff --git a/mep3_driver/launch/driver_launch.py b/mep3_driver/launch/driver_launch.py index 951ea9fbc..7bc1e30e5 100644 --- a/mep3_driver/launch/driver_launch.py +++ b/mep3_driver/launch/driver_launch.py @@ -1,19 +1,22 @@ import os import pathlib -from launch import LaunchDescription + from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): package_dir = get_package_share_directory('mep3_driver') - robot_description = pathlib.Path(os.path.join(package_dir, 'resource', 'mep3_big_config.urdf')).read_text() - ros2_control_params = os.path.join(package_dir, 'resource', 'mep3_big_ros2_control.yaml') + robot_description = pathlib.Path(os.path.join( + package_dir, 'resource', 'mep3_big_config.urdf')).read_text() + ros2_control_params = os.path.join( + package_dir, 'resource', 'mep3_big_ros2_control.yaml') controller_manager_node = Node( - package="controller_manager", - executable="ros2_control_node", + package='controller_manager', + executable='ros2_control_node', parameters=[ {'robot_description': robot_description}, ros2_control_params diff --git a/mep3_driver/package.xml b/mep3_driver/package.xml index ee6ca9282..be9f53b73 100644 --- a/mep3_driver/package.xml +++ b/mep3_driver/package.xml @@ -16,6 +16,8 @@ ament_lint_auto ament_lint_common + ament_flake8 + ament_pep257 ament_cmake diff --git a/mep3_simulation/launch/robot_launch.py b/mep3_simulation/launch/robot_launch.py index 6ce7cc32c..c2d866b48 100644 --- a/mep3_simulation/launch/robot_launch.py +++ b/mep3_simulation/launch/robot_launch.py @@ -1,11 +1,12 @@ import os import pathlib + +from ament_index_python.packages import get_package_share_directory import launch -from launch_ros.actions import Node -from launch.substitutions import LaunchConfiguration from launch.actions import IncludeLaunchDescription from launch.launch_description_sources import PythonLaunchDescriptionSource -from ament_index_python.packages import get_package_share_directory +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node from webots_ros2_core.webots_launcher import WebotsLauncher @@ -41,11 +42,12 @@ def generate_launch_description(): arguments=['joint_state_broadcaster'] + controller_manager_timeout, ) - # The node which interacts with a robot in the Webots simulation is located in the - # `webots_ros2_driver` package under name `driver`. + # The node which interacts with a robot in the Webots simulation is located + # in the `webots_ros2_driver` package under name `driver`. # It is necessary to run such a node for each robot in the simulation. - # Typically, we provide it the `robot_description` parameters from a URDF file and - # `ros2_control_params` from the `ros2_control` configuration file. + # Typically, we provide it the `robot_description` parameters from a URDF + # file and `ros2_control_params` from the `ros2_control` + # configuration file. webots_robot_driver = Node( package='webots_ros2_driver', executable='driver', @@ -58,13 +60,13 @@ def generate_launch_description(): ] ) - # Often we want to publish robot transforms, so we use the `robot_state_publisher` - # node for that. - # If robot model is not specified in the URDF file then Webots can help us with the - # URDF exportation feature. - # Since the exportation feature is available only once the simulation has started and - # the `robot_state_publisher` node requires a `robot_description` parameter before we - # have to specify a dummy robot. + # Often we want to publish robot transforms, so we use the + # `robot_state_publisher` node for that. + # If robot model is not specified in the URDF file then Webots can help + # us with the URDF exportation feature. + # Since the exportation feature is available only once the simulation has + # started and the `robot_state_publisher` node requires a + # `robot_description` parameter before we have to specify a dummy robot. robot_state_publisher = Node( package='robot_state_publisher', executable='robot_state_publisher', diff --git a/mep3_simulation/package.xml b/mep3_simulation/package.xml index cda3e919f..e3116f6dc 100644 --- a/mep3_simulation/package.xml +++ b/mep3_simulation/package.xml @@ -9,7 +9,6 @@ webots_ros2_driver webots_ros2_control robot_state_publisher - ament_copyright ament_flake8 ament_pep257 python3-pytest diff --git a/mep3_simulation/setup.py b/mep3_simulation/setup.py index 2bf16c7c8..28639ab16 100644 --- a/mep3_simulation/setup.py +++ b/mep3_simulation/setup.py @@ -1,7 +1,9 @@ -from setuptools import setup from glob import glob import os +from setuptools import setup + + package_name = 'mep3_simulation' data = { @@ -18,15 +20,18 @@ } -def files_in_directory(dir, extension=None): +def files_in_directory(path, extension=None): files = [] - for i in os.listdir(dir): - if not os.path.isdir(f'{dir}/{i}') and (extension is None or i.endswith(extension)): - files.append(f'{dir}/{i}') + for i in os.listdir(path): + if not os.path.isdir(f'{path}/{i}') and \ + (extension is None or i.endswith(extension)): + files.append(f'{path}/{i}') return files data_files = [] + + data_files.extend([ ('share/ament_index/resource_index/packages', ['resource/' + package_name]), diff --git a/mep3_simulation/test/test_copyright.py b/mep3_simulation/test/test_copyright.py deleted file mode 100644 index cc8ff03f7..000000000 --- a/mep3_simulation/test/test_copyright.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from ament_copyright.main import main -import pytest - - -@pytest.mark.copyright -@pytest.mark.linter -def test_copyright(): - rc = main(argv=['.', 'test']) - assert rc == 0, 'Found errors' diff --git a/mep3_simulation/test/test_flake8.py b/mep3_simulation/test/test_flake8.py index 27ee1078f..63b55be7a 100644 --- a/mep3_simulation/test/test_flake8.py +++ b/mep3_simulation/test/test_flake8.py @@ -1,17 +1,3 @@ -# Copyright 2017 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from ament_flake8.main import main_with_errors import pytest diff --git a/mep3_simulation/test/test_pep257.py b/mep3_simulation/test/test_pep257.py index b234a3840..4795382c6 100644 --- a/mep3_simulation/test/test_pep257.py +++ b/mep3_simulation/test/test_pep257.py @@ -1,17 +1,3 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from ament_pep257.main import main import pytest