diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml deleted file mode 100644 index 846498c..0000000 --- a/.github/workflows/docker-build.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Docker build -on: - push: - branches: ['main'] - pull_request: - schedule: - - cron: '0 11 * * *' -jobs: - spaceros: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up buildx - uses: docker/setup-buildx-action@v1 - - name: Build spaceros image - uses: docker/build-push-action@v2 - with: - context: spaceros - push: false - tags: spaceros - cache-from: type=gha - cache-to: type=gha,mode=max - no-cache: true diff --git a/.github/workflows/earthly-build.yaml b/.github/workflows/earthly-build.yaml new file mode 100644 index 0000000..5666f91 --- /dev/null +++ b/.github/workflows/earthly-build.yaml @@ -0,0 +1,50 @@ +name: Earthly build +on: + push: + branches: ['main'] + pull_request: + schedule: + - cron: '0 11 * * *' +jobs: + build-testing-results: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set up earthly + run: | + sudo wget https://github.com/earthly/earthly/releases/latest/download/earthly-linux-amd64 -O /usr/local/bin/earthly + sudo chmod 755 /usr/local/bin/earthly + - name: Build Space ROS + id: build + run: | + cd spaceros + earthly --ci --output +sources + earthly --ci +build-testing + printf "::set-output name=archivename::%s\n" $(basename log/build_results_archives/build_results_*.tar.bz2) + - name: Upload build results archive + uses: actions/upload-artifact@v3 + with: + name: ${{steps.build.outputs.archivename}} + path: spaceros/log/build_results_archives/${{steps.build.outputs.archivename}} + space-ros-image: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set up earthly + run: | + sudo wget https://github.com/earthly/earthly/releases/latest/download/earthly-linux-amd64 -O /usr/local/bin/earthly + sudo chmod 755 /usr/local/bin/earthly + - name: Build spaceros image + run: | + cd spaceros + earthly --ci --output +sources + earthly --ci +image + - name: Push spaceros image + env: + DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_RW_TOKEN }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + run: | + echo $DOCKER_HUB_TOKEN | docker login --username osrfbot --password-stdin + earthly --ci --push +image diff --git a/spaceros/.gitignore b/spaceros/.gitignore new file mode 100644 index 0000000..4709e4b --- /dev/null +++ b/spaceros/.gitignore @@ -0,0 +1,4 @@ +spaceros_ws/ +src/ +install/ +log/ diff --git a/spaceros/Dockerfile b/spaceros/Dockerfile deleted file mode 100644 index 1052288..0000000 --- a/spaceros/Dockerfile +++ /dev/null @@ -1,162 +0,0 @@ -# Copyright 2021 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. -# -# A Docker configuration script to build the Space ROS image. -# -# The script provides the following build arguments: -# -# VCS_REF - The git revision of the Space ROS source code (no default value). -# VERSION - The version of Space ROS (default: "preview") - -FROM nvidia/cudagl:11.4.1-devel-ubuntu20.04 - -# Define arguments used in the metadata definition -ARG VCS_REF -ARG VERSION="preview" - -# Specify the docker image metadata -LABEL org.label-schema.schema-version="1.0" -LABEL org.label-schema.name="Space ROS" -LABEL org.label-schema.description="Preview version of the Space ROS platform" -LABEL org.label-schema.vendor="Open Robotics" -LABEL org.label-schema.version=${VERSION} -LABEL org.label-schema.url="https://github.com/space-ros" -LABEL org.label-schema.vcs-url="https://github.com/space-ros/docker-images" -LABEL org.label-schema.vcs-ref=${VCS_REF} - -# Disable prompting during package installation -ARG DEBIAN_FRONTEND=noninteractive - -# Define the username and key variables -ENV USERNAME spaceros-user -ENV HOME_DIR=/home/${USERNAME} -ENV SPACEROS_DIR=${HOME_DIR}/spaceros -ARG IKOS_DIR=${HOME_DIR}/ikos -ARG REPOS_FILE_URL="https://raw.githubusercontent.com/space-ros/space-ros/main/ros2.repos" -ENV ROSDISTRO=humble - -# https://github.com/NVIDIA/cuda-repo-management/issues/1 -# Use new GPG keys for nvidia apt repositories that have not yet propagated to base images. -RUN apt-key del 7fa2af80 -RUN apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/3bf863cc.pub - -# Update the Ubuntu software repository -RUN apt-get update - -# Set the locale -RUN apt-get install -y locales -RUN locale-gen en_US en_US.UTF-8 -RUN update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 -ENV LANG=en_US.UTF-8 - -# Add the ROS 2 apt repository -RUN apt-get install -y software-properties-common -RUN add-apt-repository universe -RUN apt-get update && apt-get install -y curl gnupg lsb-release -RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg -RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null - -# Install required software development tools and ROS tools (and vim, included for convenience) -RUN apt-get update && apt-get install -y \ - bison \ - build-essential \ - cmake \ - git \ - python3-colcon-common-extensions \ - python3-flake8 \ - python3-pip \ - python3-pytest-cov \ - python3-rosdep \ - python3-setuptools \ - python3-vcstool \ - wget \ - vim - -# Install the required pip packages -RUN python3 -m pip install -U \ - flake8-blind-except \ - flake8-builtins \ - flake8-class-newline \ - flake8-comprehensions \ - flake8-deprecated \ - flake8-docstrings \ - flake8-import-order \ - flake8-quotes \ - pytest-repeat \ - pytest-rerunfailures \ - pytest \ - setuptools - -# Create a spaceros user -RUN useradd -m $USERNAME && \ - echo "$USERNAME:$USERNAME" | chpasswd && \ - usermod --shell /bin/bash $USERNAME && \ - usermod -aG sudo $USERNAME && \ - mkdir -p /etc/sudoers.d && \ - echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/$USERNAME && \ - chmod 0440 /etc/sudoers.d/$USERNAME -USER ${USERNAME} - -## Get the Space ROS source code -RUN mkdir -p ${SPACEROS_DIR}/src -WORKDIR ${SPACEROS_DIR} -ADD --chown=${USERNAME}:${USERNAME} ${REPOS_FILE_URL} ros2.repos -RUN vcs import src < ros2.repos - -# Install system dependencies -RUN sudo rosdep init && \ - rosdep update && \ - rosdep install --from-paths src --ignore-src --rosdistro ${ROSDISTRO} -y --skip-keys "console_bridge fastcdr fastrtps rti-connext-dds-5.3.1 urdfdom_headers rmw_connextdds ros_testing rmw_connextdds rmw_fastrtps_cpp rmw_fastrtps_dynamic_cpp composition demo_nodes_py lifecycle rosidl_typesupport_fastrtps_cpp rosidl_typesupport_fastrtps_c ikos" - -# Build the Space ROS source code -RUN colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - -# Install dependencies needed by the IKOS static analyzer -RUN sudo apt-get install -y \ - clang-9 \ - cmake \ - g++ \ - gcc \ - libboost-dev \ - libboost-filesystem-dev \ - libboost-test-dev \ - libboost-thread-dev \ - libedit-dev \ - libgmp-dev \ - libsqlite3-dev \ - libtbb-dev \ - llvm-9 \ - llvm-9-dev \ - llvm-9-tools \ - python3 \ - python3-pygments \ - zlib1g-dev - -# Get the IKOS source and build it -WORKDIR ${HOME_DIR} -RUN git clone https://github.com/NASA-SW-VnV/ikos.git && cd ikos && git checkout 8b0bab34846b72777cca2a60d473282971806cfc -ENV PYTHONPATH "$PYTHONPATH:${IKOS_DIR}/install/lib/python3.8/site-packages" -WORKDIR ${IKOS_DIR} -RUN mkdir build && cd build && cmake .. -DLLVM_CONFIG_EXECUTABLE=/usr/bin/llvm-config-9 --no-warn-unused-cli && make && sudo make install -ENV PATH "$PATH:${IKOS_DIR}/install/bin" -ENV IKOS_SCAN_NOTIFIER_FILES "yes" - -# The IKOS installation doesn't install the IKOS egg file, so do it manually (https://github.com/NASA-SW-VnV/ikos/issues/185) -RUN cd ${IKOS_DIR}/install/lib/python3.8/site-packages && sudo python3 /usr/lib/python3/dist-packages/easy_install.py ./ikos-3.0-py3.8.egg - -# Set up the entrypoint -WORKDIR ${SPACEROS_DIR} -COPY ./entrypoint.sh / -ENTRYPOINT ["/entrypoint.sh"] -CMD ["bash"] diff --git a/spaceros/Earthfile b/spaceros/Earthfile new file mode 100644 index 0000000..3548b70 --- /dev/null +++ b/spaceros/Earthfile @@ -0,0 +1,150 @@ +# Copyright 2021 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. +VERSION 0.6 +FROM ubuntu:jammy + +earthfile: + COPY Earthfile Earthfile + SAVE ARTIFACT Earthfile + +setup: + # Disable prompting during package installation + ARG DEBIAN_FRONTEND=noninteractive + + # The following commands are based on the source install for ROS 2 Rolling Ridley. + # See: https://docs.ros.org/en/ros2_documentation/rolling/Installation/Ubuntu-Development-Setup.html + # The main variation is getting Space ROS sources instead of the Rolling sources. + + # Update the Ubuntu software repository + RUN apt-get update + + # Set the locale + RUN apt-get install -y locales + RUN locale-gen en_US en_US.UTF-8 + RUN update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 + ENV LANG=en_US.UTF-8 + + # Add the ROS 2 apt repository + RUN apt-get install -y software-properties-common + RUN add-apt-repository universe + RUN apt-get update && apt-get install -y curl gnupg lsb-release + RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg + RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null + + # Install required software development tools and ROS tools (and vim included for convenience) + RUN apt-get update && apt-get install -y \ + bison \ + build-essential \ + cmake \ + git \ + python3-colcon-common-extensions \ + python3-flake8 \ + python3-flake8-blind-except \ + python3-flake8-builtins \ + python3-flake8-class-newline \ + python3-flake8-comprehensions \ + python3-flake8-deprecated \ + python3-flake8-docstrings \ + python3-flake8-import-order \ + python3-flake8-quotes \ + python3-pip \ + python3-pytest \ + python3-pytest-cov \ + python3-pytest-repeat \ + python3-pytest-rerunfailures \ + python3-rosdep \ + python3-setuptools \ + python3-vcstool \ + wget \ + vim + + # Define the username and key variables + ENV USERNAME spaceros-user + ENV SRC_DIR=/home/${USERNAME}/src + ENV SPACEROS_DIR=${SRC_DIR}/spaceros + ARG IKOS_DIR=${SRC_DIR}/ikos + ARG REPOS_FILE_URL="https://raw.githubusercontent.com/space-ros/space-ros/main/ros2.repos" + ENV ROSDISTRO=humble + + # Create a spaceros user + RUN useradd -m $USERNAME && \ + echo "$USERNAME:$USERNAME" | chpasswd && \ + usermod --shell /bin/bash $USERNAME && \ + usermod -aG sudo $USERNAME && \ + mkdir -p /etc/sudoers.d && \ + echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/$USERNAME && \ + chmod 0440 /etc/sudoers.d/$USERNAME + USER ${USERNAME} + + WORKDIR $SPACEROS_DIR + + +sources: + FROM +setup + COPY github.com/space-ros/space-ros:earthly-wrapper+repos-file/ros2.repos ros2.repos + RUN mkdir src + RUN vcs import src < ros2.repos + SAVE ARTIFACT src AS LOCAL src + +workspace: + FROM +setup + COPY src src/ + +vcs-exact: + FROM +workspace + RUN vcs export --exact src > exact.repos + SAVE ARTIFACT exact.repos AS LOCAL exact.repos + +rosdep: + FROM +workspace + # Install system package dependencies using rosdep + RUN sudo rosdep init && rosdep update + RUN rosdep install --from-paths src --ignore-src --rosdistro rolling -y --skip-keys "console_bridge fastcdr fastrtps rti-connext-dds-5.3.1 urdfdom_headers rmw_connextdds ros_testing rmw_connextdds rmw_fastrtps_cpp rmw_fastrtps_dynamic_cpp composition demo_nodes_py lifecycle rosidl_typesupport_fastrtps_cpp rosidl_typesupport_fastrtps_c ikos" + +build: + FROM +rosdep + RUN colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON --no-warn-unused-cli + COPY +vcs-exact/exact.repos install/exact.repos + SAVE ARTIFACT install AS LOCAL install + +build-testing: + FROM +rosdep + RUN colcon build --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_EXPORT_COMPILE_COMMANDS=ON --no-warn-unused-cli + RUN colcon test --retest-until-pass 2 --ctest-args -LE "(ikos|xfail)" --pytest-args -m "not xfail" + RUN . install/setup.sh && ros2 run process_sarif make_build_archive + COPY +vcs-exact/exact.repos install/exact.repos + SAVE ARTIFACT log/build_results_archives/build_results*.tar.bz2 AS LOCAL spaceros_ws/log/build_results_archives/ + SAVE ARTIFACT install AS LOCAL install + +image: + FROM +rosdep + + ARG VCS_REF + + # Specify the docker image metadata + LABEL org.label-schema.schema-version="1.0" + LABEL org.label-schema.name="Space ROS" + LABEL org.label-schema.description="Preview version of the Space ROS platform" + LABEL org.label-schema.vendor="Open Robotics" + LABEL org.label-schema.url="https://github.com/space-ros" + LABEL org.label-schema.vcs-url="https://github.com/space-ros/docker-images" + LABEL org.label-schema.vcs-ref=${VCS_REF} + + COPY +build/install ${SPACEROS_DIR}/install + COPY +vcs-exact/exact.repos ${SPACEROS_DIR}/exact.repos + RUN rm -r src + COPY entrypoint.sh /ros_entrypoint.sh + ENTRYPOINT ["/ros_entrypoint.sh"] + CMD ["bash"] + SAVE IMAGE osrf/space-ros:latest diff --git a/spaceros/README.md b/spaceros/README.md index 4b5ce9a..8ae0185 100644 --- a/spaceros/README.md +++ b/spaceros/README.md @@ -1,11 +1,13 @@ -# Space ROS Docker Image +# Space ROS Docker Image and Earthly configuration -The Dockerfile in this directory builds Space ROS from source code. -To include drivers for NVIDIA GPUs, the Space ROS docker image is based on the NVIDIA CudaGL development image, version 11.4.1, which is, in turn, based on Ubuntu 20.04. +The Earthfile configuration in this directory facilitates builds of Space ROS from source code. +The generated container image is based on Ubuntu 22.04 (Jammy) and can be used with [`rocker`](https://github.com/osrf/rocker) to add X11 and GPU passthrough. ## Building the Docker Image -To build the docker image, run: +The [Earthly](https://earthly.dev/get-earthly) utility is required to build this image. + +To build the image, run: ``` $ ./build.sh @@ -26,11 +28,11 @@ The output will look something like this: ``` $ docker image list REPOSITORY TAG IMAGE ID CREATED SIZE -openrobotics/spaceros latest 629b13cf7b74 1 hour ago 7.8GB -nvidia/cudagl 11.4.1-devel-ubuntu20.04 336416dfcbba 1 day ago 5.35GB +osrf/space-ros latest 109ad8fb7460 4 days ago 2.45GB +ubuntu jammy a8780b506fa4 5 days ago 77.8MB ``` -The new image is named **openrobotics/spaceros:latest**. +The new image is named **osrf/space-ros:latest**. There is a run.sh script provided for convenience that will run the spaceros image in a container. @@ -78,12 +80,21 @@ Commands: Call `ros2 -h` for more detailed usage. ``` -## Running the Space ROS Unit Tests +## Rebuilding Space ROS and running unit tests + +Space ROS sources and intermediate build artifacts are not included in the docker image. -The Space ROS unit tests are not built as part of the Docker image build. To run the unit tests in the container, execute the following command from the top of the Space ROS workspace: +A manifest of the exact sources used to produce the current image is saved as `exact.repos` in the spaceros directory. +To clone all sources from this manifest you can use the command sequence +``` +spaceros-user@d10d85c68f0e:~/spaceros$ mkdir src +spaceros-user@d10d85c68f0e:~/spaceros$ vcs import src < exact.repos +``` +From there you can run a new build and any additional tests. ``` -spaceros-user@d10d85c68f0e:~/spaceros$ colcon test +spaceros-user@d10d85c68f0e:~/spaceros$ colcon build --cmake-args -DCMAKE_BUILD_TYPE=Debug --DCMAKE_EXPORT_COMPILE_COMMANDS=ON --no-warn-unused-cli +spaceros-user@d10d85c68f0e:~/spaceros$ colcon test --ctest-args -LE "(ikos|xfail)" --pytest-args -m "not xfail" ``` The tests include running the static analysis tools clang_tidy and cppcheck (which has the MISRA 2012 add-on enabled). diff --git a/spaceros/build.sh b/spaceros/build.sh index e638db2..199e287 100755 --- a/spaceros/build.sh +++ b/spaceros/build.sh @@ -4,16 +4,17 @@ ORG=openrobotics IMAGE=spaceros TAG=latest -VCS_REF="" +VCS_REF="$(git rev-parse HEAD)" VERSION=preview echo "" echo "##### Building Space ROS Docker Image #####" echo "" -docker build -t $ORG/$IMAGE:$TAG \ - --build-arg VCS_REF="$VCS_REF" \ - --build-arg VERSION="$VERSION" . +rm -rf src +earthly +sources +earthly +image \ + --VCS_REF="$VCS_REF" echo "" echo "##### Done! #####" diff --git a/spaceros/run.sh b/spaceros/run.sh index 6a868d2..78a5d9c 100755 --- a/spaceros/run.sh +++ b/spaceros/run.sh @@ -1,2 +1,2 @@ # Start the container -docker run --rm --gpus all --net=host -e DISPLAY=$DISPLAY --device=/dev/dri:/dev/dri --volume="$HOME/.Xauthority:/home/spaceros-user/.Xauthority:rw" -it openrobotics/spaceros +docker run --rm --net=host -e DISPLAY=$DISPLAY --device=/dev/dri:/dev/dri --volume="$HOME/.Xauthority:/home/spaceros-user/.Xauthority:rw" -it osrf/space-ros