diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index b34feaa7f..2ce4e9118 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,17 +1,9 @@ FROM ros:humble-ros-base-jammy -SHELL ["/bin/bash", "-c"] - # setup environment ENV LANG C.UTF-8 ENV LC_ALL C.UTF-8 -# install packages -RUN apt-get update \ - && apt-get install -q -y --no-install-recommends \ - curl \ - && rm -rf /var/lib/apt/lists/* - ARG ROS_DISTRO=humble ENV ROS_DISTRO $ROS_DISTRO ARG INSTALL_PACKAGE=base @@ -21,6 +13,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update -q && \ apt-get update -q && \ apt-get install -yq --no-install-recommends \ lcov \ + curl \ python3-pip \ python-is-python3 \ python3-argcomplete \ @@ -36,15 +29,6 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update -q && \ # I added this RUN source "/opt/ros/${ROS_DISTRO}/setup.bash" -# Spot packages -RUN apt-get update -q && \ - apt-get install -y --no-install-recommends \ - ros-${ROS_DISTRO}-joint-state-publisher-gui \ - ros-${ROS_DISTRO}-depth-image-proc \ - ros-${ROS_DISTRO}-vision-msgs \ - ros-${ROS_DISTRO}-interactive-markers && \ - rm -rf /var/lib/apt/lists/* - # Install bosdyn_msgs package RUN curl -sL https://github.com/bdaiinstitute/bosdyn_msgs/releases/download/v3.3.2-AMD64/ros-humble-bosdyn-msgs_3.3.2-0jammy_amd64.deb --output /tmp/ros-humble-bosdyn-msgs_3.3.2-0jammy_amd64.deb --silent \ && dpkg -i /tmp/ros-humble-bosdyn-msgs_3.3.2-0jammy_amd64.deb \ @@ -55,15 +39,26 @@ RUN curl -sL https://github.com/bdaiinstitute/spot-cpp-sdk/releases/download/3.3 && dpkg -i /tmp/spot-cpp-sdk_3.3.2_amd64.deb \ && rm /tmp/spot-cpp-sdk_3.3.2_amd64.deb -# Install packages inside the new environment +# Install bosdyn_msgs missing dependencies RUN python -m pip install --no-cache-dir --upgrade pip==22.3.1 \ && pip install --root-user-action=ignore --no-cache-dir --default-timeout=900 \ numpy==1.24.1 \ bosdyn-client==3.3.2 \ bosdyn-mission==3.3.2 \ bosdyn-api==3.3.2 \ - bosdyn-core==3.3.2 && \ + bosdyn-core==3.3.2 \ + pip cache purge + +# Install spot_wrapper requirements +RUN --mount=type=bind,source=spot_wrapper,target=/tmp/context/spot_wrapper cd /tmp/context && \ + pip install --root-user-action=ignore --no-cache-dir --default-timeout=900 -r spot_wrapper/requirements.txt && \ pip cache purge +# Install packages dependencies +RUN --mount=type=bind,source=.,target=/tmp/context \ + apt-get update -q && rosdep update && \ + rosdep install -y -i --from-paths /tmp/context --skip-keys "bosdyn bosdyn_msgs spot_wrapper" && \ + rm -rf /var/lib/apt/lists/* + # ROS doesn't recognize the docker shells as terminals so force colored output ENV RCUTILS_COLORIZED_OUTPUT=1 diff --git a/.github/workflows/build_docker.yml b/.github/workflows/build_docker.yml deleted file mode 100644 index bf09ffd11..000000000 --- a/.github/workflows/build_docker.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: Build and publish Jammy/Humble Docker image - -on: - pull_request: - paths: - - ".devcontainer/**" - push: - branches: - - main - -env: - # Use docker.io for Docker Hub if empty - REGISTRY: ghcr.io - # github.repository as / - IMAGE_NAME: bdaiinstitute/spot_ros2_jammy_humble - -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - # This is used to complete the identity challenge - # with sigstore/fulcio when running outside of PRs. - id-token: write - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - # Workaround: https://github.com/docker/build-push-action/issues/461 - - name: Setup Docker buildx - uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf - - # Login against a Docker registry except on PR - # https://github.com/docker/login-action - - name: Log into registry ${{ env.REGISTRY }} - if: github.event_name != 'pull_request' - uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - # Extract metadata (tags, labels) for Docker - # https://github.com/docker/metadata-action - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - - # Build and push Docker image with Buildx (don't push on PR) - # https://github.com/docker/build-push-action - - name: Build and push Docker image - id: build-and-push - uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a - with: - context: . - file: .devcontainer/Dockerfile - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..03e4f1480 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,134 @@ +name: spot_ros2 CI + +on: + pull_request: + push: + branches: + - main + workflow_call: + secrets: + CODECOV_TOKEN: + required: true + +permissions: + contents: write + +env: + # Use docker.io for Docker Hub if empty + REGISTRY: ghcr.io + # github.repository as / + IMAGE_NAME: bdaiinstitute/spot_ros2_jammy_humble + +defaults: + run: + shell: bash + +jobs: + lint: + name: Lint spot_ros2 packages + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - name: Lint sources + uses: pre-commit/action@v3.0.0 + prepare_container: + name: Prepare Humble container for tests + runs-on: ubuntu-latest + needs: lint + permissions: + contents: read + packages: write + # This is used to complete the identity challenge + # with sigstore/fulcio when running outside of PRs. + id-token: write + outputs: + image: ${{ fromJSON(steps.meta.outputs.json).tags[0] }} + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: recursive + - name: Setup Docker buildx # to workaround: https://github.com/docker/build-push-action/issues/461 + uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf + - name: Log into registry ${{ env.REGISTRY }} + uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c # https://github.com/docker/login-action + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract metadata (tags, labels) for Docker + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 # https://github.com/docker/metadata-action + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + id: meta + - name: Build and push Docker image (may be cached) + uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a # https://github.com/docker/build-push-action + with: + context: . + file: .devcontainer/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + build_and_test_package_and_docs: + name: Build and test spot_ros2 packages + runs-on: ubuntu-latest + needs: prepare_container + container: + image: ${{ needs.prepare_container.outputs.image }} + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: recursive + path: src + - name: Build packages + run: | + source /opt/ros/$ROS_DISTRO/setup.bash + colcon build --symlink-install --packages-skip-regex proto2ros --cmake-args -DCMAKE_CXX_FLAGS="--coverage" + - name: Test packages + run: | + source install/setup.bash + colcon test --python-testing pytest --pytest-with-coverage --event-handlers console_direct+ --packages-skip-regex bdai_ros2_wrappers proto2ros + - name: Generate coverage report + run: lcov -c -d build/spot_driver/ -o coverage_spot_driver.info --include "*/spot_driver/*" --exclude "*/test/*" + - name: Upload python coverage to Coveralls + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fail-on-error: true + flag-name: unittests-python + parallel: true + debug: true + files: $(find . -name "coverage.xml" -type f) + - name: Upload cpp coverage to Coveralls + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fail-on-error: true + flag-name: unittests-cpp + debug: true + files: coverage_spot_driver.info + format: lcov + - name: Aggregate coverage + uses: coverallsapp/github-action@v2 + with: + parallel-finished: true + carryforward: "unittests-python, unittests-cpp" + - name: Report on test results + run: colcon test-result --all --verbose + if: always() + - name: Build packages documentation + run: | + source /opt/ros/$ROS_DISTRO/setup.bash + pip install -r docs/requirements.txt + # go to documentation folder and build the .rst files + cd docs + # we don't use the --implicit-namespaces flag + sphinx-apidoc -f -o source/ ../ ../*setup* ../examples ../*launch.py ../*command_spot_driver.py + cd .. + sphinx-build docs _build -v + working-directory: ${{ github.workspace }}/src diff --git a/.github/workflows/maintenance.yml b/.github/workflows/maintenance.yml new file mode 100644 index 000000000..7d3b052fd --- /dev/null +++ b/.github/workflows/maintenance.yml @@ -0,0 +1,26 @@ +name: spot_ros2 CI maintenance + +on: + schedule: + - cron: "0 0 * * 0" # once a week + +env: + ORG_NAME: bdaiinstitute + # github.repository as / + IMAGE_NAME: spot_ros2_jammy_humble + +jobs: + clean-ghcr: + name: Prune old images from Github Container Registry + runs-on: ubuntu-latest + steps: + - name: Delete old pull request images + uses: snok/container-retention-policy@v2 + with: + image-names: ${{ env.IMAGE_NAME }} + skip-tags: main + cut-off: One week ago UTC + org-name: ${{ env.ORG_NAME }} + account-type: org + token: ${{ secrets.GITHUB_TOKEN }} + token-type: github-token diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 08a30633c..000000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,84 +0,0 @@ -name: spot_ros2 CI -on: - pull_request: - push: - branches: - - main - workflow_call: - secrets: - CODECOV_TOKEN: - required: true - -permissions: - contents: write - -jobs: - build_and_test_package_and_docs: - name: build_and_test_package_and_docs - runs-on: ubuntu-latest - defaults: - run: - shell: bash - container: ghcr.io/bdaiinstitute/spot_ros2_jammy_humble:main - steps: - - name: Checkout repo and submodules - uses: actions/checkout@v3 - with: - submodules: recursive - - name: Build package - run: | - apt-get update - apt install wget - ./install_spot_ros2.sh - # go to root folder - cd ../../ - source /opt/ros/$ROS_DISTRO/setup.bash - colcon build --symlink-install --packages-skip proto2ros_tests --cmake-args -DCMAKE_CXX_FLAGS="--coverage" - source install/local_setup.bash - - name: Test Package - run: | - source /opt/ros/$ROS_DISTRO/setup.bash - source install/local_setup.bash - # skip testing submodules - colcon test --python-testing pytest --pytest-with-coverage --event-handlers console_direct+ --packages-skip bdai_ros2_wrappers proto2ros_tests - working-directory: ${{ github.workspace }}/../../ - - name: Generate coverage report - run: lcov -c -d build/spot_driver/ -o coverage_spot_driver.info --include "*/spot_driver/*" --exclude "*/test/*" - working-directory: ${{ github.workspace }}/../../ - - name: Upload python coverage to Coveralls - uses: coverallsapp/github-action@v2 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - fail-on-error: true - flag-name: unittests-python - parallel: true - debug: true - files: $(find ../../ -name "coverage.xml" -type f) - - name: Upload cpp coverage to Coveralls - uses: coverallsapp/github-action@v2 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - fail-on-error: true - flag-name: unittests-cpp - parallel: true - debug: true - files: ../../coverage_spot_driver.info - format: lcov - - name: Aggregate coverage - uses: coverallsapp/github-action@v2 - with: - parallel-finished: true - carryforward: "unittests-python, unittests-cpp" - - if: always() - run: colcon test-result --verbose - working-directory: ${{ github.workspace }}/../../ - - name: Install docs dependencies & build docs - run: | - source /opt/ros/$ROS_DISTRO/setup.bash - pip install -r docs/requirements.txt - # go to documentation folder and build the .rst files - cd docs - # we don't use the --implicit-namespaces flag - sphinx-apidoc -f -o source/ ../ ../*setup* ../examples ../*launch.py ../*command_spot_driver.py - cd .. - sphinx-build docs _build -v diff --git a/.github/workflows/util_pre-commit.yml b/.github/workflows/util_pre-commit.yml deleted file mode 100644 index 853b6dec2..000000000 --- a/.github/workflows/util_pre-commit.yml +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2023 Boston Dynamics AI Institute, Inc. All rights reserved. - -name: Util - Pre-Commit Runner - -on: - push: - branches: - - main - pull_request: - branches: - - main - -jobs: - pre-commit: - name: util_pre-commit - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - - uses: pre-commit/action@v3.0.0