From 2cbb8b2c3bfbeb0d72454405e3ad02039f8fc218 Mon Sep 17 00:00:00 2001 From: "Felix Exner (fexner)" Date: Tue, 10 Oct 2023 20:03:37 +0200 Subject: [PATCH] Use dedicated build for noetic main (#640) * Use dedicated build for noetic main * Increase timeout waiting for first action server * Add full noetic build matrix * Make the integration test behind a compile flag Since for our integration tests we would require docker being able to spawn a new container that can't necessarily be expected in any usecase. Also, with making this optional we don't require docker as a test dependency which also makes the package a lot more lightweight. --- .github/workflows/ci.yml | 63 ------------------- .github/workflows/ci_format.yml | 20 ++++++ .github/workflows/noetic-binary-main.yml | 22 +++++++ .github/workflows/noetic-binary-testing.yml | 22 +++++++ .github/workflows/noetic-semi-binary-main.yml | 23 +++++++ .../workflows/noetic-semi-binary-testing.yml | 23 +++++++ .github/workflows/reusable_ici.yml | 50 +++++++++++++++ ur_robot_driver/CMakeLists.txt | 12 +++- ur_robot_driver/launch/ur_control.launch | 4 +- ur_robot_driver/test/driver.test | 3 + ur_robot_driver/test/integration_test.py | 15 +++-- 11 files changed, 185 insertions(+), 72 deletions(-) delete mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/ci_format.yml create mode 100644 .github/workflows/noetic-binary-main.yml create mode 100644 .github/workflows/noetic-binary-testing.yml create mode 100644 .github/workflows/noetic-semi-binary-main.yml create mode 100644 .github/workflows/noetic-semi-binary-testing.yml create mode 100644 .github/workflows/reusable_ici.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index b03c613a9..000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: Industrial CI pipeline -on: - push: - pull_request: - schedule: - - cron: '0 7 * * *' - - -jobs: - format_check: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - uses: 'ros-industrial/industrial_ci@master' - env: - ROS_DISTRO: melodic - CLANG_FORMAT_CHECK: file - CLANG_FORMAT_VERSION: "9" - - build: - runs-on: ubuntu-latest - continue-on-error: ${{ matrix.env.experimental }} - strategy: - fail-fast: false - matrix: - env: - - ROS_DISTRO: melodic - ROS_REPO: main - UPSTREAM_WORKSPACE: .melodic.rosinstall - DOCKER_RUN_OPTS: --network static_test_net - BEFORE_INIT: 'apt-get update -qq && apt-get install -y iproute2 iputils-ping && ip addr && ping -c5 192.168.56.101' - IMMEDIATE_TEST_OUTPUT: true - experimental: false - - ROS_DISTRO: noetic - ROS_REPO: main - UPSTREAM_WORKSPACE: .noetic.rosinstall - DOCKER_RUN_OPTS: --network static_test_net - BEFORE_INIT: 'apt-get update -qq && apt-get install -y iproute2 iputils-ping && ip addr && ping -c5 192.168.56.101' - IMMEDIATE_TEST_OUTPUT: true - experimental: false - - ROS_DISTRO: melodic - ROS_REPO: testing - UPSTREAM_WORKSPACE: .melodic.rosinstall - DOCKER_RUN_OPTS: --network static_test_net - BEFORE_INIT: 'apt-get update -qq && apt-get install -y iproute2 iputils-ping && ip addr && ping -c5 192.168.56.101' - IMMEDIATE_TEST_OUTPUT: true - experimental: true - - ROS_DISTRO: noetic - ROS_REPO: testing - UPSTREAM_WORKSPACE: .noetic.rosinstall - DOCKER_RUN_OPTS: --network static_test_net - BEFORE_INIT: 'apt-get update -qq && apt-get install -y iproute2 iputils-ping && ip addr && ping -c5 192.168.56.101' - IMMEDIATE_TEST_OUTPUT: true - experimental: true - - steps: - - uses: actions/checkout@v1 - - name: start ursim - run: | - .github/dockerursim/build_and_run_docker_ursim.sh - - uses: 'ros-industrial/industrial_ci@master' - env: ${{matrix.env}} diff --git a/.github/workflows/ci_format.yml b/.github/workflows/ci_format.yml new file mode 100644 index 000000000..a9bc5adaa --- /dev/null +++ b/.github/workflows/ci_format.yml @@ -0,0 +1,20 @@ +name: Clang-Format check +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + format_check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: 'ros-industrial/industrial_ci@master' + env: + ROS_DISTRO: noetic + CLANG_FORMAT_CHECK: file + CLANG_FORMAT_VERSION: "9" diff --git a/.github/workflows/noetic-binary-main.yml b/.github/workflows/noetic-binary-main.yml new file mode 100644 index 000000000..e2303d0cd --- /dev/null +++ b/.github/workflows/noetic-binary-main.yml @@ -0,0 +1,22 @@ +name: Noetic Binary Build Main +on: + workflow_dispatch: + branches: + - master + pull_request: + branches: + - master + push: + branches: + - master + schedule: + # Run every morning to detect flakiness and broken dependencies + - cron: '32 5 * * *' + +jobs: + binary: + uses: ./.github/workflows/reusable_ici.yml + with: + ros_distro: noetic + ros_repo: main + ref_for_scheduled_build: master diff --git a/.github/workflows/noetic-binary-testing.yml b/.github/workflows/noetic-binary-testing.yml new file mode 100644 index 000000000..033cc814e --- /dev/null +++ b/.github/workflows/noetic-binary-testing.yml @@ -0,0 +1,22 @@ +name: Noetic Binary Build Testing +on: + workflow_dispatch: + branches: + - master + pull_request: + branches: + - master + push: + branches: + - master + schedule: + # Run every morning to detect flakiness and broken dependencies + - cron: '32 5 * * *' + +jobs: + binary: + uses: ./.github/workflows/reusable_ici.yml + with: + ros_distro: noetic + ros_repo: testing + ref_for_scheduled_build: master diff --git a/.github/workflows/noetic-semi-binary-main.yml b/.github/workflows/noetic-semi-binary-main.yml new file mode 100644 index 000000000..96f506889 --- /dev/null +++ b/.github/workflows/noetic-semi-binary-main.yml @@ -0,0 +1,23 @@ +name: Noetic Semi-Binary Build Main +on: + workflow_dispatch: + branches: + - master + pull_request: + branches: + - master + push: + branches: + - master + schedule: + # Run every morning to detect flakiness and broken dependencies + - cron: '32 5 * * *' + +jobs: + binary: + uses: ./.github/workflows/reusable_ici.yml + with: + ros_distro: noetic + ros_repo: main + ref_for_scheduled_build: master + upstream_workspace: .noetic.rosinstall diff --git a/.github/workflows/noetic-semi-binary-testing.yml b/.github/workflows/noetic-semi-binary-testing.yml new file mode 100644 index 000000000..f4b1f45cb --- /dev/null +++ b/.github/workflows/noetic-semi-binary-testing.yml @@ -0,0 +1,23 @@ +name: Noetic Semi-Binary Build Testing +on: + workflow_dispatch: + branches: + - master + pull_request: + branches: + - master + push: + branches: + - master + schedule: + # Run every morning to detect flakiness and broken dependencies + - cron: '32 5 * * *' + +jobs: + binary: + uses: ./.github/workflows/reusable_ici.yml + with: + ros_distro: noetic + ros_repo: testing + ref_for_scheduled_build: master + upstream_workspace: .noetic.rosinstall diff --git a/.github/workflows/reusable_ici.yml b/.github/workflows/reusable_ici.yml new file mode 100644 index 000000000..0e7548979 --- /dev/null +++ b/.github/workflows/reusable_ici.yml @@ -0,0 +1,50 @@ +name: Reusable industrial_ci workflow +# original author: Denis Štogl + +on: + workflow_call: + inputs: + ref_for_scheduled_build: + description: 'Reference on which the repo should be checkout for scheduled build. Usually is this name of a branch or a tag.' + default: '' + required: false + type: string + + upstream_workspace: + description: 'UPSTREAM_WORKSPACE variable for industrial_ci. Usually path to local .repos file.' + default: '' + required: false + type: string + ros_distro: + description: 'ROS_DISTRO variable for industrial_ci' + required: false + type: string + ros_repo: + description: 'ROS_REPO to run for industrial_ci. Possible values: "main", "testing"' + default: 'main' + required: false + type: string + +jobs: + reusable_ici: + name: ${{ inputs.ros_distro }} ${{ inputs.ros_repo }} ${{ inputs.os_code_name }} + runs-on: ubuntu-latest + env: + DOCKER_RUN_OPTS: '-v /var/run/docker.sock:/var/run/docker.sock --network ursim_net' + ADDITIONAL_DEBS: 'docker.io' + steps: + - name: Checkout ${{ inputs.ref }} when build is not scheduled + if: ${{ github.event_name != 'schedule' }} + uses: actions/checkout@v3 + - name: Checkout ${{ inputs.ref }} on scheduled build + if: ${{ github.event_name == 'schedule' }} + uses: actions/checkout@v3 + with: + ref: ${{ inputs.ref_for_scheduled_build }} + - run: docker network create --subnet=192.168.56.0/24 ursim_net + - uses: 'ros-industrial/industrial_ci@master' + env: + UPSTREAM_WORKSPACE: ${{ inputs.upstream_workspace }} + ROS_DISTRO: ${{ inputs.ros_distro }} + ROS_REPO: ${{ inputs.ros_repo }} + CMAKE_ARGS: -DUR_ROBOT_DRIVER_BUILD_INTEGRATION_TESTS=ON diff --git a/ur_robot_driver/CMakeLists.txt b/ur_robot_driver/CMakeLists.txt index f1e2ff82b..6921fe09a 100644 --- a/ur_robot_driver/CMakeLists.txt +++ b/ur_robot_driver/CMakeLists.txt @@ -8,6 +8,14 @@ if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo) endif() +# Default to off as this only works in environments where a new docker container can be started with the appropriate networking, which +# might not be possible e.g. inside the buildfarm +option( + UR_ROBOT_DRIVER_BUILD_INTEGRATION_TESTS + "Build integration tests using the start_ursim script" + OFF +) + find_package(catkin REQUIRED COMPONENTS actionlib @@ -127,7 +135,9 @@ target_link_libraries(controller_stopper_node if(CATKIN_ENABLE_TESTING) find_package(rostest REQUIRED) - add_rostest(test/driver.test) + if(${UR_ROBOT_DRIVER_BUILD_INTEGRATION_TESTS}) + add_rostest(test/driver.test) + endif() endif() diff --git a/ur_robot_driver/launch/ur_control.launch b/ur_robot_driver/launch/ur_control.launch index 161b4cc43..c98baf09b 100644 --- a/ur_robot_driver/launch/ur_control.launch +++ b/ur_robot_driver/launch/ur_control.launch @@ -75,11 +75,11 @@ + output="screen" args="$(arg controllers) --timeout 600" /> + output="screen" args="--stopped $(arg stopped_controllers) --timeout 600" unless="$(eval arg('stopped_controllers') == '')"/> diff --git a/ur_robot_driver/test/driver.test b/ur_robot_driver/test/driver.test index e8ec1f72c..c96aa0b43 100644 --- a/ur_robot_driver/test/driver.test +++ b/ur_robot_driver/test/driver.test @@ -12,6 +12,9 @@ + + + diff --git a/ur_robot_driver/test/integration_test.py b/ur_robot_driver/test/integration_test.py index c15a8cdf4..1de325dbf 100755 --- a/ur_robot_driver/test/integration_test.py +++ b/ur_robot_driver/test/integration_test.py @@ -53,42 +53,45 @@ def init_robot(self): """Make sure the robot is booted and ready to receive commands""" rospy.init_node('ur_robot_driver_integration_test') + # In CI we pull the docker image when this test is started. So, we wait a little longer for + # the first service... + initial_timeout = rospy.Duration(300) timeout = rospy.Duration(30) self.set_mode_client = actionlib.SimpleActionClient( '/ur_hardware_interface/set_mode', SetModeAction) - if not self.set_mode_client.wait_for_server(timeout): + if not self.set_mode_client.wait_for_server(initial_timeout): self.fail( "Could not reach set_mode action. Make sure that the driver is actually running." - " Msg: {}".format(err)) + ) self.trajectory_client = actionlib.SimpleActionClient( 'follow_joint_trajectory', FollowJointTrajectoryAction) if not self.trajectory_client.wait_for_server(timeout): self.fail( "Could not reach controller action. Make sure that the driver is actually running." - " Msg: {}".format(err)) + ) self.cartesian_passthrough_trajectory_client = actionlib.SimpleActionClient( 'forward_cartesian_trajectory', FollowCartesianTrajectoryAction) if not self.cartesian_passthrough_trajectory_client.wait_for_server(timeout): self.fail( "Could not reach cartesian passthrough controller action. Make sure that the driver is actually running." - " Msg: {}".format(err)) + ) self.joint_passthrough_trajectory_client = actionlib.SimpleActionClient( 'forward_joint_trajectory', FollowJointTrajectoryAction) if not self.joint_passthrough_trajectory_client.wait_for_server(timeout): self.fail( "Could not reach joint passthrough controller action. Make sure that the driver is actually running." - " Msg: {}".format(err)) + ) self.cartesian_trajectory_client = actionlib.SimpleActionClient( 'follow_cartesian_trajectory', FollowCartesianTrajectoryAction) if not self.cartesian_trajectory_client.wait_for_server(timeout): self.fail( "Could not reach cartesian controller action. Make sure that the driver is actually running." - " Msg: {}".format(err)) + ) self.set_io_client = rospy.ServiceProxy('/ur_hardware_interface/set_io', SetIO) try: