From 063ab996b74b41d882b5108e03e82d3b3b113ebc Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 01:05:02 -0500 Subject: [PATCH 01/64] Comment out old CI for migration --- .circleci/config.yml | 70 +++++++++++++------------- .github/workflows/lint.yml | 2 +- .github/workflows/update_ci_image.yaml | 14 +++--- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4d962b4f0e..1fbb46907c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -536,38 +536,38 @@ _parameters: workflows: version: 2 - build_and_test: - jobs: - - release_build: - <<: *release_parameters - - system_build: - requires: - - release_build - - release_test: - requires: - - system_build - cache_test: true - nightly: - jobs: - - release_build: - <<: *release_parameters - - system_build: - requires: - - release_build - - release_test: - requires: - - system_build - <<: *release_parameters - matrix: - alias: release_test - parameters: - rmw: - - rmw_cyclonedds_cpp - - rmw_fastrtps_cpp - triggers: - - schedule: - cron: "0 13 * * *" - filters: - branches: - only: - - main + # build_and_test: + # jobs: + # - release_build: + # <<: *release_parameters + # - system_build: + # requires: + # - release_build + # - release_test: + # requires: + # - system_build + # cache_test: true + # nightly: + # jobs: + # - release_build: + # <<: *release_parameters + # - system_build: + # requires: + # - release_build + # - release_test: + # requires: + # - system_build + # <<: *release_parameters + # matrix: + # alias: release_test + # parameters: + # rmw: + # - rmw_cyclonedds_cpp + # - rmw_fastrtps_cpp + # triggers: + # - schedule: + # cron: "0 13 * * *" + # filters: + # branches: + # only: + # - main diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c181fe25f4..9d2c8ac738 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,6 +1,6 @@ name: Lint on: - pull_request: + # pull_request: jobs: ament_lint_general: diff --git a/.github/workflows/update_ci_image.yaml b/.github/workflows/update_ci_image.yaml index ce987eb118..bb0052a535 100644 --- a/.github/workflows/update_ci_image.yaml +++ b/.github/workflows/update_ci_image.yaml @@ -6,13 +6,13 @@ on: # 7am UTC, 12am PDT - cron: '0 7 * * *' push: - branches: - - main - paths: - - '**/package.xml' - - '**/*.repos' - - 'Dockerfile' - - '.github/workflows/update_ci_image.yaml' + # branches: + # - main + # paths: + # - '**/package.xml' + # - '**/*.repos' + # - 'Dockerfile' + # - '.github/workflows/update_ci_image.yaml' jobs: check_ci_files: From a4dff339058c085d8134af7b008c0ac430302f0e Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 01:45:06 -0500 Subject: [PATCH 02/64] Simplify dockerignore by inverting matching set --- .dockerignore | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/.dockerignore b/.dockerignore index 19c4cc591c..57395a5850 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,12 +1,7 @@ -################################################################################ -# Repo +# Ignore everything by default +* -.circleci/ -.devcontainer/ -.dockerignore -.git/ -.github/ -.gitignore -**.Dockerfile -**Dockerfile -doc/ +# First-order allow exception for select directories +!/cache +!/nav* +!/tools From b070400749a4cf9cf9e9f32fb243ca62cdee3151 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 01:53:34 -0500 Subject: [PATCH 03/64] Refactor Dockerfile using Buildkit and bake files --- Dockerfile | 456 +++++++++++++++++++----------------- docker-bake.hcl | 110 +++++++++ tools/.ccache/ccache.conf | 32 +++ tools/.colcon/defaults.yaml | 18 ++ tools/runner_apt_debs.txt | 16 ++ tools/tooler_apt_deps.txt | 17 ++ 6 files changed, 436 insertions(+), 213 deletions(-) create mode 100644 docker-bake.hcl create mode 100644 tools/.ccache/ccache.conf create mode 100644 tools/.colcon/defaults.yaml create mode 100644 tools/runner_apt_debs.txt create mode 100644 tools/tooler_apt_deps.txt diff --git a/Dockerfile b/Dockerfile index 4360541532..fb07fc66c0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,226 +1,256 @@ -# This dockerfile can be configured via --build-arg -# Build context must be the /navigation2 root folder for COPY. -# Example build command: -# export UNDERLAY_MIXINS="debug ccache lld" -# export OVERLAY_MIXINS="debug ccache coverage-gcc lld" -# docker build -t nav2:latest \ -# --build-arg UNDERLAY_MIXINS \ -# --build-arg OVERLAY_MIXINS ./ -ARG FROM_IMAGE=ros:rolling -ARG UNDERLAY_WS=/opt/underlay_ws -ARG OVERLAY_WS=/opt/overlay_ws - -# multi-stage for caching -FROM $FROM_IMAGE AS cacher - -# clone underlay source -ARG UNDERLAY_WS -WORKDIR $UNDERLAY_WS/src -COPY ./tools/underlay.repos ../ -RUN vcs import ./ < ../underlay.repos +# syntax=docker/dockerfile:1.7 +ARG DEV_FROM_STAGE=tooler +ARG EXPORT_FROM_STAGE=builder +ARG PREP_FROM_STAGE=runner +ARG WS_CACHE_ID=nav2 + +ARG FROM_IMAGE=base +# Stage from full image tag name for dependabot detection +FROM ros:rolling as base + +################################################################################ +# MARK: baser - setup base image using snapshots +################################################################################ +FROM $FROM_IMAGE as baser +ENV FROM_IMAGE=${FROM_IMAGE} + +# Configure ubuntu snapshot +RUN UBUNTU_DEB_SNAPSHOT=$(date -r /var/lib/dpkg/info +%Y%m%dT%H%M%SZ) && \ + sed -i "s|http://archive.ubuntu.com/ubuntu/|http://snapshot.ubuntu.com/ubuntu/${UBUNTU_DEB_SNAPSHOT}|g" /etc/apt/sources.list && \ + sed -i "s|http://security.ubuntu.com/ubuntu/|http://snapshot.ubuntu.com/ubuntu/${UBUNTU_DEB_SNAPSHOT}|g" /etc/apt/sources.list + +# Edit apt config for caching +RUN mv /etc/apt/apt.conf.d/docker-clean /etc/apt/ && \ + echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' \ + > /etc/apt/apt.conf.d/keep-cache && \ + # Given fixed snapshots, just cache apt update once + apt-get update && echo v1 + +# Configure overlay workspace +ENV OVERLAY_WS=/opt/nav2_ws +WORKDIR $OVERLAY_WS + +# install bootstrap tools +RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ + apt-get install -y --no-install-recommends \ + gettext-base \ + wget \ + zstd + +# init and update rosdep +ENV ROS_HOME=/opt/.ros +RUN rosdep update \ + --rosdistro $ROS_DISTRO + +################################################################################ +# MARK: cacher - cache source and dependency instructions +################################################################################ +FROM baser AS cacher # copy overlay source -ARG OVERLAY_WS -WORKDIR $OVERLAY_WS/src -COPY ./ ./navigation2 - -# copy manifests for caching -WORKDIR /opt -RUN find . -name "src" -type d \ - -mindepth 1 -maxdepth 2 -printf '%P\n' \ - | xargs -I % mkdir -p /tmp/opt/% && \ - find . -name "package.xml" \ - | xargs cp --parents -t /tmp/opt && \ - find . -name "COLCON_IGNORE" \ - | xargs cp --parents -t /tmp/opt || true - -# multi-stage for building -FROM $FROM_IMAGE AS builder - -# config dependencies install -ARG DEBIAN_FRONTEND=noninteractive -RUN echo '\ -APT::Install-Recommends "0";\n\ -APT::Install-Suggests "0";\n\ -' > /etc/apt/apt.conf.d/01norecommend -ENV PYTHONUNBUFFERED 1 - -# install CI dependencies -ARG RTI_NC_LICENSE_ACCEPTED=yes -RUN apt-get update && \ - apt-get upgrade -y --with-new-pkgs && \ - apt-get install -y \ - ccache \ - lcov \ - lld \ +COPY ./ ./src/nav2 + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN dep_types=(\ + "exec:--dependency-types=exec" \ + "test:--dependency-types=test" \ + "build:"\ + ) && \ + for dep_type in "${dep_types[@]}"; do \ + IFS=":"; set -- $dep_type; \ + rosdep install -y \ + --from-paths src \ + --ignore-src \ + --skip-keys " \ + # From Nav2 + slam_toolbox \ + turtlebot3_gazebo \ + "\ + --reinstall \ + --simulate \ + ${2} \ + | sed -E "s/'//g; s/ \(alternative .*\)//g" \ + | tail -n +2 \ + | awk '{print $NF}' \ + | sort > /tmp/rosdep_${1}_debs.txt; \ + done + +################################################################################ +# MARK: runner - setup runtime dependencies for deployment +################################################################################ +FROM baser as runner + +# install packages for field work +COPY tools/runner_apt_debs.txt /tmp/runner_apt_debs.txt +RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ + cut -d# -f1 < /tmp/runner_apt_debs.txt | envsubst \ + | xargs apt-get install -y --no-install-recommends + +COPY --from=cacher /tmp/rosdep_exec_debs.txt /tmp/rosdep_exec_debs.txt +RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ + < /tmp/rosdep_exec_debs.txt xargs apt-get install -y --no-install-recommends + +################################################################################ +# MARK: prepper - bootstrap general dependencies for development +################################################################################ +FROM $PREP_FROM_STAGE as prepper + +# install bootstrap tools +RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ + apt-get install -y --no-install-recommends \ + git \ + python3-colcon-clean \ python3-pip \ - ros-$ROS_DISTRO-rmw-fastrtps-cpp \ - ros-$ROS_DISTRO-rmw-connextdds \ - ros-$ROS_DISTRO-rmw-cyclonedds-cpp \ && pip3 install --break-system-packages \ - fastcov \ - git+https://github.com/ruffsl/colcon-cache.git@a937541bfc496c7a267db7ee9d6cceca61e470ca \ - git+https://github.com/ruffsl/colcon-clean.git@a7f1074d1ebc1a54a6508625b117974f2672f2a9 \ - && rosdep update \ - && colcon mixin update \ - && colcon metadata update \ - && rm -rf /var/lib/apt/lists/* - -# install underlay dependencies -ARG UNDERLAY_WS -ENV UNDERLAY_WS $UNDERLAY_WS -WORKDIR $UNDERLAY_WS -COPY --from=cacher /tmp/$UNDERLAY_WS ./ -RUN . /opt/ros/$ROS_DISTRO/setup.sh && \ - apt-get update && rosdep install -q -y \ - --from-paths src \ - --skip-keys " \ - slam_toolbox \ - " \ - --ignore-src \ - && rm -rf /var/lib/apt/lists/* - -# build underlay source -COPY --from=cacher $UNDERLAY_WS ./ -ARG UNDERLAY_MIXINS="release ccache lld" -ARG CCACHE_DIR="$UNDERLAY_WS/.ccache" -RUN . /opt/ros/$ROS_DISTRO/setup.sh && \ - colcon cache lock && \ - colcon build \ - --symlink-install \ - --mixin $UNDERLAY_MIXINS \ - --event-handlers console_direct+ + git+https://github.com/ruffsl/colcon-cache.git@6076815bbb574da028d270cf6eb93bdd5b29c7f4 +ENV COLCON_EXTENSION_BLOCKLIST="$COLCON_EXTENSION_BLOCKLIST:colcon_core.package_augmentation.cache_git" + +################################################################################ +# MARK: validator - setup test dependencies for validation +################################################################################ +FROM prepper as validator + +COPY --from=cacher /tmp/rosdep_test_debs.txt /tmp/rosdep_test_debs.txt +RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ + < /tmp/rosdep_test_debs.txt xargs apt-get install -y --no-install-recommends + +################################################################################ +# MARK: tooler - setup build dependencies for compilation +################################################################################ +FROM validator as tooler + +COPY --from=cacher /tmp/rosdep_build_debs.txt /tmp/ +RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ + < /tmp/rosdep_build_debs.txt xargs apt-get install -y --no-install-recommends + +# install packages for build work +COPY tools/tooler_apt_deps.txt /tmp/tooler_apt_deps.txt +RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ + cut -d# -f1 < /tmp/tooler_apt_deps.txt | envsubst \ + | xargs apt-get install -y --no-install-recommends + +# setup default ccache configuration +COPY tools/.ccache/ccache.conf /opt/.ccache/ +ENV CCACHE_CONFIGPATH="/opt/.ccache/ccache.conf" +ENV CCACHE_DIR="$OVERLAY_WS/.ccache" + +# setup default colcon configuration +COPY tools/.colcon/defaults.yaml $COLCON_HOME/ +ARG OVERLAY_MIXINS="release ccache lld" +ENV OVERLAY_MIXINS=${OVERLAY_MIXINS} + +# capture environment to modify layer digest +RUN env > /tmp/env.txt + +################################################################################ +# MARK: seeder - seed workspace artifacts for caching +################################################################################ +FROM baser as seeder +ARG WS_CACHE_ID + +ARG CLEAR_WS_CACHE +RUN --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS \ + if [ -n "$CLEAR_WS_CACHE" ]; then \ + echo "Clearing cache!" && \ + rm -rf $OVERLAY_WS/* && \ + echo "Cache cleared!"; \ + fi -# install overlay dependencies -ARG OVERLAY_WS -ENV OVERLAY_WS $OVERLAY_WS -WORKDIR $OVERLAY_WS -COPY --from=cacher /tmp/$OVERLAY_WS ./ +ARG SEED_WS_CACHE +RUN --mount=type=bind,source=./,target=/seeder/\ + --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS \ + if [ -n "$SEED_WS_CACHE" ]; then \ + echo "Seeding cache!" && \ + cp -rT /seeder/cache/$OVERLAY_WS $OVERLAY_WS && \ + echo "Cache seeded!"; \ + fi -RUN . $UNDERLAY_WS/install/setup.sh && \ - apt-get update && rosdep install -q -y \ - --from-paths src \ - --skip-keys " \ - slam_toolbox \ - "\ - --ignore-src \ - && rm -rf /var/lib/apt/lists/* +RUN --mount=type=cache,from=cacher,target=/cacher \ + --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS \ + rm -rf ./src && \ + cp -r /cacher/$OVERLAY_WS/src ./ && \ + echo $(date) > /tmp/seeder_stamp.txt -# multi-stage for testing -FROM builder AS tester +################################################################################ +# MARK: builder - build workspace artifacts for deployment +################################################################################ +FROM tooler as builder +ARG WS_CACHE_ID # build overlay source -COPY --from=cacher $OVERLAY_WS ./ -ARG OVERLAY_MIXINS="release ccache lld" -ARG CCACHE_DIR="$OVERLAY_WS/.ccache" -RUN . $UNDERLAY_WS/install/setup.sh && \ - colcon cache lock && \ +ARG BUST_BUILD_CACHE +RUN --mount=type=cache,from=seeder,target=/seeder \ + --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS \ + . /opt/ros/$ROS_DISTRO/setup.sh && \ + colcon cache lock \ + --dirhash-reset && \ + colcon clean packages -y \ + --packages-select-cache-invalid \ + --packages-select-cache-key build \ + --base-select install && \ colcon build \ - --symlink-install \ - --mixin $OVERLAY_MIXINS + --packages-skip-cache-valid \ + --mixin $OVERLAY_MIXINS \ + || true && \ + echo $(date) > /tmp/builder_stamp.txt + +ARG FAIL_ON_BUILD_FAILURE=1 +RUN --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS \ + . /opt/ros/$ROS_DISTRO/setup.sh && \ + BUILD_FAILED=$( \ + colcon list \ + --packages-select-build-failed) && \ + if [ -n "$BUILD_FAILED" ]; then \ + echo "BUILD_FAILED: \n$BUILD_FAILED" && \ + ([ -z "$FAIL_ON_BUILD_FAILURE" ] || exit 1); \ + fi -# source overlay from entrypoint -RUN sed --in-place \ - 's|^source .*|source "$OVERLAY_WS/install/setup.bash"|' \ - /ros_entrypoint.sh +################################################################################ +# MARK: dever - setup user account for development +################################################################################ +FROM $DEV_FROM_STAGE as dever -# test overlay build -ARG RUN_TESTS -ARG FAIL_ON_TEST_FAILURE -RUN if [ -n "$RUN_TESTS" ]; then \ - . install/setup.sh && \ - colcon test && \ - colcon test-result \ - || ([ -z "$FAIL_ON_TEST_FAILURE" ] || exit 1) \ - fi +# add default user for devcontainer +ENV DEV_USER=ubuntu +RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +################################################################################ +# MARK: tester - test workspace artifacts for development +################################################################################ +FROM validator as tester +ARG WS_CACHE_ID -# multi-stage for developing -FROM builder AS dever - -# edit apt for caching -RUN mv /etc/apt/apt.conf.d/docker-clean /etc/apt/ - -# install developer dependencies -RUN apt-get update && \ - apt-get install -y \ - bash-completion \ - gdb \ - wget && \ - pip3 install --break-system-packages \ - bottle \ - glances - -# source underlay for shell -RUN echo 'source "$UNDERLAY_WS/install/setup.bash"' >> /etc/bash.bashrc - -# multi-stage for caddy -FROM caddy:builder AS caddyer - -# build custom modules -RUN xcaddy build \ - --with github.com/caddyserver/replace-response - -# multi-stage for visualizing -FROM dever AS visualizer - -ENV ROOT_SRV /srv -RUN mkdir -p $ROOT_SRV - -# install demo dependencies -RUN apt-get update && apt-get install -y \ - ros-$ROS_DISTRO-rviz2 \ - -# install gzweb dependacies -RUN apt-get install -y --no-install-recommends \ - imagemagick \ - libboost-all-dev \ - libgazebo-dev \ - libgts-dev \ - libjansson-dev \ - libtinyxml-dev \ - nodejs \ - npm \ - psmisc \ - xvfb - -# clone gzweb -ENV GZWEB_WS /opt/gzweb -RUN git clone https://github.com/osrf/gzweb.git $GZWEB_WS - -# setup gzweb -RUN cd $GZWEB_WS && . /usr/share/gazebo/setup.sh && \ - GAZEBO_MODEL_PATH=$GAZEBO_MODEL_PATH:$(find /opt/ros/$ROS_DISTRO/share \ - -mindepth 1 -maxdepth 2 -type d -name "models" | paste -s -d: -) && \ - sed -i "s|var modelList =|var modelList = []; var oldModelList =|g" gz3d/src/gzgui.js && \ - xvfb-run -s "-screen 0 1280x1024x24" ./deploy.sh -m local && \ - ln -s $GZWEB_WS/http/client/assets http/client/assets/models && \ - ln -s $GZWEB_WS/http/client $ROOT_SRV/gzweb - -# patch gzsever -RUN GZSERVER=$(which gzserver) && \ - mv $GZSERVER $GZSERVER.orig && \ - echo '#!/bin/bash' > $GZSERVER && \ - echo 'exec xvfb-run -s "-screen 0 1280x1024x24" gzserver.orig "$@"' >> $GZSERVER && \ - chmod +x $GZSERVER - -# install foxglove dependacies -RUN apt-get install -y --no-install-recommends \ - ros-$ROS_DISTRO-foxglove-bridge - -# setup foxglove -# Use custom fork until PR is merged: -# https://github.com/foxglove/studio/pull/5987 -# COPY --from=ghcr.io/foxglove/studio /src $ROOT_SRV/foxglove -COPY --from=ghcr.io/ruffsl/foxglove_studio@sha256:8a2f2be0a95f24b76b0d7aa536f1c34f3e224022eed607cbf7a164928488332e /src $ROOT_SRV/foxglove - -# install web server -COPY --from=caddyer /usr/bin/caddy /usr/bin/caddy - -# download media files -RUN mkdir -p $ROOT_SRV/media && cd /tmp && \ - export ICONS="icons.tar.gz" && wget https://github.com/ros-planning/navigation2/files/11506823/$ICONS && \ - echo "cae5e2a5230f87b004c8232b579781edb4a72a7431405381403c6f9e9f5f7d41 $ICONS" | sha256sum -c && \ - tar xvz -C $ROOT_SRV/media -f $ICONS && rm $ICONS - -# multi-stage for exporting -FROM tester AS exporter +# test overlay build +ARG BUST_TEST_CACHE +RUN --mount=type=cache,from=builder,target=/builder \ + --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS \ + . install/setup.sh && \ + colcon test \ + --packages-skip-cache-valid && \ + echo $(date) > /tmp/tester_stamp.txt + +ARG FAIL_ON_TEST_FAILURE=1 +RUN --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS \ + . install/setup.sh && \ + colcon test-result \ + --verbose \ + || ([ -z "$FAIL_ON_TEST_FAILURE" ] || exit 1) + +################################################################################ +# MARK: dancer - multi-stage for caches dancing +################################################################################ +FROM $EXPORT_FROM_STAGE as dancer +ARG WS_CACHE_ID + +RUN --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS,readonly \ + echo "Exporting cache!" && \ + mkdir -p /dancer/$OVERLAY_WS && \ + cp -rT $OVERLAY_WS /dancer/$OVERLAY_WS && \ + echo "Cache exported!" + +################################################################################ +# MARK: exporter - multi-stage for exporting caches +################################################################################ +FROM $EXPORT_FROM_STAGE as exporter + +COPY --link --from=dancer /dancer/$OVERLAY_WS $OVERLAY_WS diff --git a/docker-bake.hcl b/docker-bake.hcl new file mode 100644 index 0000000000..be18b67efd --- /dev/null +++ b/docker-bake.hcl @@ -0,0 +1,110 @@ +variable "repo" { + default = "navigation2" +} +variable "registry" { + default = "ghcr.io" +} + +group "default" { + targets = ["tooler"] +} + +################################################################################ +// MARK: General targets +################################################################################ + +target "baser" { + target = "baser" + tags = ["nav2:baser"] + pull = true + no-cache = false + cache-from = [ + // "type=registry,ref=${registry}/${repo}:main-tooler.cache", + ] +} + +target "cacher" { + inherits = ["baser"] + target = "cacher" + tags = ["nav2:cacher"] +} + +target "runner" { + inherits = ["baser"] + target = "runner" + tags = ["nav2:runner"] +} + +target "prepper" { + inherits = ["runner"] + target = "prepper" + tags = ["nav2:prepper"] +} + +target "validator" { + inherits = ["prepper"] + target = "validator" + tags = ["nav2:validator"] +} + +target "tooler" { + inherits = ["validator"] + target = "tooler" + tags = ["nav2:tooler"] +} + +################################################################################ +// MARK: Development targets +################################################################################ + +target "dever" { + inherits = ["tooler"] + target = "dever" + tags = ["nav2:dever"] +} + +target "seeder" { + inherits = ["dever"] + target = "seeder" + tags = ["nav2:seeder"] + // no-cache-filter = ["builder"] + args = { + CLEAR_WS_CACHE = null, + // CLEAR_WS_CACHE = "${timestamp()}", + SEED_WS_CACHE = null, + // SEED_WS_CACHE = "${timestamp()}", + } +} + +target "builder" { + inherits = ["seeder"] + target = "builder" + tags = ["nav2:builder"] + // no-cache-filter = ["builder"] + args = { + BUST_BUILD_CACHE = null, + // BUST_BUILD_CACHE = "${timestamp()}", + } +} + +target "tester" { + inherits = ["builder"] + target = "tester" + tags = ["nav2:tester"] + args = { + BUST_TEST_CACHE = null, + // BUST_TEST_CACHE = "${timestamp()}", + } +} + +target "dancer" { + inherits = ["builder"] + target = "dancer" + tags = ["nav2:dancer"] +} + +target "exporter" { + inherits = ["dancer"] + target = "exporter" + tags = ["nav2:exporter"] +} diff --git a/tools/.ccache/ccache.conf b/tools/.ccache/ccache.conf new file mode 100644 index 0000000000..7bb7470470 --- /dev/null +++ b/tools/.ccache/ccache.conf @@ -0,0 +1,32 @@ +# Set the maximum size of the cache to 5G +# max_size = 5G + +# Set the base directory for the cache +# cache_dir = + +# Set the compression level +# compression = true + +# Set the compression level +# compression_level = 0 + +# Set the log file +# log_file = + +# Set the temporary directory +# temporary_dir = + +# Set the umask +# umask = + +# Set the compiler check +# compiler_check = mtime + +# Set the direct mode +# direct_mode = true + +# Set the read-only mode +# read_only = false + +# Set the hard link mode +# hard_link = false \ No newline at end of file diff --git a/tools/.colcon/defaults.yaml b/tools/.colcon/defaults.yaml new file mode 100644 index 0000000000..70abdba213 --- /dev/null +++ b/tools/.colcon/defaults.yaml @@ -0,0 +1,18 @@ +_common: &common + # Record test results to separate directory + # for simpler parsing and exporting with CI + "test-result-base": "test_results" + +"clean.packages": + <<: *common +"build": + <<: *common + "executor": "parallel" + # "parallel-workers": 4 + "symlink-install": false +"test": + <<: *common + "executor": "parallel" + # "parallel-workers": 1 +"test-result": + <<: *common diff --git a/tools/runner_apt_debs.txt b/tools/runner_apt_debs.txt new file mode 100644 index 0000000000..7e8f34b54c --- /dev/null +++ b/tools/runner_apt_debs.txt @@ -0,0 +1,16 @@ +# ROS +ros-${ROS_DISTRO}-rmw-cyclonedds-cpp +ros-${ROS_DISTRO}-ros2cli-common-extensions + +# System +bash-completion + +# Tooling +bashtop +byobu +fish +htop +iftop +rsync +tmux +tmuxinator diff --git a/tools/tooler_apt_deps.txt b/tools/tooler_apt_deps.txt new file mode 100644 index 0000000000..6d73ae3f86 --- /dev/null +++ b/tools/tooler_apt_deps.txt @@ -0,0 +1,17 @@ +# System tools +build-essential +ca-certificates +ccache +distcc +gdb +git +git-lfs +lld +mesa-utils +nano +unzip +valgrind +yadm + +# ROS tools +ros-${ROS_DISTRO}-rqt-common-plugins From 7a09d15dc262088793f6161f150cfc2c6f71b60f Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 10:22:02 -0500 Subject: [PATCH 04/64] Change COLCON_HOME in Dockerfile for now and refactor into dev container scripts later on --- Dockerfile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Dockerfile b/Dockerfile index fb07fc66c0..a279c2567f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -105,6 +105,15 @@ RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ git+https://github.com/ruffsl/colcon-cache.git@6076815bbb574da028d270cf6eb93bdd5b29c7f4 ENV COLCON_EXTENSION_BLOCKLIST="$COLCON_EXTENSION_BLOCKLIST:colcon_core.package_augmentation.cache_git" +# setup colcon mixin and metadata +ENV COLCON_HOME=/opt/.colcon +RUN colcon mixin add default \ + https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml && \ + colcon mixin update && \ + colcon metadata add default \ + https://raw.githubusercontent.com/colcon/colcon-metadata-repository/master/index.yaml && \ + colcon metadata update + ################################################################################ # MARK: validator - setup test dependencies for validation ################################################################################ From cdbe1654c5cb67553d583d09aadab20b121d643a Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 10:37:45 -0500 Subject: [PATCH 05/64] Refactor Dev Container using Buildkit and bake files --- .devcontainer/devcontainer.json | 49 ++++++++++++++++++------- .devcontainer/initialize-command.sh | 17 +++++++++ .devcontainer/on-create-command.sh | 22 ++++++++++- .devcontainer/post-create-command.sh | 11 +++--- .devcontainer/update-content-command.sh | 6 ++- 5 files changed, 83 insertions(+), 22 deletions(-) create mode 100755 .devcontainer/initialize-command.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 77a326648d..7cfcc5d358 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,44 +1,65 @@ { "name": "Nav2", - "build": { - "dockerfile": "../Dockerfile", - "context": "..", - "target": "dever", - "cacheFrom": "ghcr.io/ros-navigation/navigation2:main" - }, + "initializeCommand": ".devcontainer/initialize-command.sh dever", // Bakes to tag nav2:devcontainer + "image": "nav2:devcontainer", "runArgs": [ - "--name=nav2" // "--cap-add=SYS_PTRACE", // enable debugging, e.g. gdb // "--ipc=host", // shared memory transport with host, e.g. rviz GUIs // "--network=host", // network access to host interfaces, e.g. eth0 // "--pid=host", // DDS discovery with host, without --network=host // "--privileged", // device access to host peripherals, e.g. USB // "--security-opt=seccomp=unconfined", // enable debugging, e.g. gdb + // "--device=/dev/dri", // enable Intel integrated graphics + // "--ulimit", "nofile=1024:4096", // increase file descriptor limit for valgrind + // + "--runtime=nvidia", // enable NVIDIA Container Toolkit + "--env=NVIDIA_VISIBLE_DEVICES=all", // enable GPUs with env as --gpus doesn't parse nicely + "--env=NVIDIA_DRIVER_CAPABILITIES=all", // enable all capabilities, including `graphics` ], - "workspaceFolder": "/opt/overlay_ws/src/navigation2", + "workspaceFolder": "/opt/nav2_ws/src/navigation2", "workspaceMount": "source=${localWorkspaceFolder},target=${containerWorkspaceFolder},type=bind", "onCreateCommand": ".devcontainer/on-create-command.sh", "updateContentCommand": ".devcontainer/update-content-command.sh", "postCreateCommand": ".devcontainer/post-create-command.sh", "remoteEnv": { "OVERLAY_MIXINS": "release ccache lld", - "CCACHE_DIR": "/tmp/.ccache" + "CCACHE_DIR": "/opt/nav2_ws/.ccache", + // Explicitly set DISPLAY for NVIDIA Container Toolkit + "DISPLAY": "${localEnv:DISPLAY}", }, + "remoteUser": "ubuntu", "mounts": [ { - "source": "ccache-${devcontainerId}", - "target": "/tmp/.ccache", + // Explicitly mount X11 socket for NVIDIA Container Toolkit + // as setting NVIDIA_DRIVER_CAPABILITIES to include `graphics` + // interferes with VSCode's default X11 forwarding behavior + "source": "/tmp/.X11-unix", + "target": "/tmp/.X11-unix", + "type": "bind" + }, + { + // Cache apt downloads + "source": "apt-cache", + "target": "/var/cache/apt", + "type": "volume" + }, + { + // Cache ccache caches + "source": "ccache", + "target": "/opt/nav2_ws/.ccache", "type": "volume" }, { + // Cache colcon workspace "source": "overlay-${devcontainerId}", - "target": "/opt/overlay_ws", + "target": "/opt/nav2_ws", "type": "volume" } ], "features": { // "ghcr.io/devcontainers/features/desktop-lite:1": {}, - "ghcr.io/devcontainers/features/github-cli:1": {} + // "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}, + // "ghcr.io/devcontainers/features/github-cli:1": {} }, "customizations": { "codespaces": { @@ -53,6 +74,8 @@ "eamodio.gitlens", "esbenp.prettier-vscode", "GitHub.copilot", + "hashicorp.hcl", + // "ms-azuretools.vscode-docker", "ms-iot.vscode-ros", "streetsidesoftware.code-spell-checker", "twxs.cmake" diff --git a/.devcontainer/initialize-command.sh b/.devcontainer/initialize-command.sh new file mode 100755 index 0000000000..1bb56e66ec --- /dev/null +++ b/.devcontainer/initialize-command.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Immediately catch all errors +set -eo pipefail + +# Uncomment for debugging +# set -x +# env + +# Use first argument as target name +target=$1 + +# Bake the target and export locally to static tag +docker buildx bake --load \ + --file docker-bake.hcl \ + --set $target.tags=nav2:devcontainer \ + $target diff --git a/.devcontainer/on-create-command.sh b/.devcontainer/on-create-command.sh index f86d22bc8d..883a1cb862 100755 --- a/.devcontainer/on-create-command.sh +++ b/.devcontainer/on-create-command.sh @@ -7,6 +7,26 @@ set -eo pipefail # set -x # env +# Set git config for submodules +git config --local include.path ../.gitconfig + +# Set git config for colcon cache git config --global --add safe.directory "*" -.devcontainer/update-content-command.sh +# NOTE: This is slow if not using a mounted volumes, +# i.e. using workspace from the docker image directly, +# presumably due to docker overlayfs driver overhead. +# If needing to use workspace pre-baked into base image, +# consider using a new volume to be auto populated with +# the workspace pre-baked in image via devcontainer tools. +# Either by deleting old volume from the docker engine +# Or simpler changing volume name in devcontainer.json +sudo chown -R :ubuntu $OVERLAY_WS +# Recursively update group permissions for workspace +# to allow write access via dev users current group +sudo chmod -R g+rwx $OVERLAY_WS + +# Recursively update group permissions for ros home +# to allow write access such as ros node logs +sudo chown -R :ubuntu /opt/.ros +sudo chmod -R g+rwx /opt/.ros diff --git a/.devcontainer/post-create-command.sh b/.devcontainer/post-create-command.sh index 9f64a2c6ab..34680fef2d 100755 --- a/.devcontainer/post-create-command.sh +++ b/.devcontainer/post-create-command.sh @@ -10,9 +10,8 @@ set -eo pipefail # Enable autocomplete for user cp /etc/skel/.bashrc ~/ -# Check if srv folder exists -if [ -d "$ROOT_SRV" ]; then - # Setup Nav2 web app - for dir in $OVERLAY_WS/src/navigation2/.devcontainer/caddy/srv/*; \ - do if [ -d "$dir" ]; then ln -s "$dir" $ROOT_SRV; fi done -fi +# Enable autocomplete using colcon +echo "source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash" >> ~/.bashrc + +# Add aliases to .bashrc +echo "alias sows='source $OVERLAY_WS/install/setup.bash'" >> ~/.bashrc diff --git a/.devcontainer/update-content-command.sh b/.devcontainer/update-content-command.sh index 2bdbf5cc1a..f4c0428e14 100755 --- a/.devcontainer/update-content-command.sh +++ b/.devcontainer/update-content-command.sh @@ -49,11 +49,13 @@ then fi echo BUILD_PACKAGES: $BUILD_PACKAGES +# DEBUG: Uncoment for more sterile but slower builds # colcon clean packages --yes \ # --packages-select ${BUILD_PACKAGES} \ -# --base-select install +# --base-select build install -. $UNDERLAY_WS/install/setup.sh +# OPTOINAL: Uncomment to build packages upon update +. /opt/ros/$ROS_DISTRO/setup.sh colcon build \ --symlink-install \ --mixin $OVERLAY_MIXINS \ From acec6434ee237026bbe6c5b434d3ee070beeab33 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 21:50:10 -0500 Subject: [PATCH 06/64] Refactor Action Workflows using Buildkit and bake files --- .github/actions/bake-base-stages/action.yml | 173 ++++++++++++++ .../bake-base-stages/lifecycle-policy.json | 17 ++ .../bake-base-stages/repository-policy.json | 26 +++ .github/actions/bake-prod-stages/action.yml | 152 ++++++++++++ .../actions/cache-source-checkout/action.yml | 57 +++++ .github/actions/get-layer-metadata/README.md | 60 +++++ .github/actions/get-layer-metadata/action.yml | 50 ++++ .github/workflows/build_prod_images.yaml | 95 ++++++++ .github/workflows/build_test.yaml | 30 +++ .github/workflows/build_test_colcon.yaml | 219 ++++++++++++++++++ .github/workflows/build_test_integration.yaml | 96 ++++++++ .github/workflows/ecr_retention.yaml | 72 ++++++ .github/workflows/ghac_eviction.yaml | 47 ++++ 13 files changed, 1094 insertions(+) create mode 100644 .github/actions/bake-base-stages/action.yml create mode 100644 .github/actions/bake-base-stages/lifecycle-policy.json create mode 100644 .github/actions/bake-base-stages/repository-policy.json create mode 100644 .github/actions/bake-prod-stages/action.yml create mode 100644 .github/actions/cache-source-checkout/action.yml create mode 100644 .github/actions/get-layer-metadata/README.md create mode 100644 .github/actions/get-layer-metadata/action.yml create mode 100644 .github/workflows/build_prod_images.yaml create mode 100644 .github/workflows/build_test.yaml create mode 100644 .github/workflows/build_test_colcon.yaml create mode 100644 .github/workflows/build_test_integration.yaml create mode 100644 .github/workflows/ecr_retention.yaml create mode 100644 .github/workflows/ghac_eviction.yaml diff --git a/.github/actions/bake-base-stages/action.yml b/.github/actions/bake-base-stages/action.yml new file mode 100644 index 0000000000..e3eb10aa5c --- /dev/null +++ b/.github/actions/bake-base-stages/action.yml @@ -0,0 +1,173 @@ +name: "Bake base stages" +description: "GitHub Action to bake base stages and push images for CI" +author: 'ros-navigation' +branding: + icon: 'package' + color: 'blue' + +inputs: + integration_repo: + required: true + type: string + description: The repository to checkout for running CI + token: + required: true + type: string + description: The token to use for image registry login + +outputs: + overlay_cache_sha: + description: 'Cache sha to restore overlay workspace cache' + value: ${{ steps.job_workflow_info.outputs.overlay_cache_sha }} + metadata: + description: 'Layer result metadata' + value: ${{ steps.get_layer_metadata.outputs.metadata }} + tooler_image: + description: 'Docker image for building overlay workspace' + value: ${{ steps.job_workflow_info.outputs.tooler_image }} + validator_image: + description: 'Docker image for testing overlay workspace' + value: ${{ steps.job_workflow_info.outputs.validator_image }} + +runs: + using: "composite" + steps: + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + # TODO: Check if default cleanup clears cache on host runner + # and if so, postpone cleanup when baking base stages + # later when baking prod stages if using the same runner + with: + cleanup: false + buildkitd-config-inline: | + [gc] + enabled = false + [worker.oci] + gc = false + [worker.containerd] + gc = false + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-region: ${{ env.RUNS_ON_AWS_REGION }} + - name: AWS ECR Login + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + - name: AWS ECR Info + shell: bash + run: | + echo "ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }}" >> $GITHUB_ENV + echo "INTEGRATION_REPO=$(basename ${{ inputs.integration_repo }})" >> $GITHUB_ENV + echo "ECR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV + - name: AWS ECR Init + shell: bash + run: | + REPO_EXISTS=$(aws ecr describe-repositories --repository-names ${{ env.ECR_REPO }} 2>&1 || true) + if echo "${REPO_EXISTS}" | grep -q 'RepositoryNotFoundException'; then + aws ecr create-repository \ + --repository-name ${{ env.ECR_REPO }} + aws ecr put-lifecycle-policy \ + --repository-name ${{ env.ECR_REPO }} \ + --lifecycle-policy-text file://${{ github.action_path }}/lifecycle-policy.json + aws ecr set-repository-policy \ + --repository-name ${{ env.ECR_REPO }} \ + --policy-text file://${{ github.action_path }}/repository-policy.json + fi + + - name: Docker validator meta + id: docker_meta_validator + uses: docker/metadata-action@v5 + with: + images: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPO }} + flavor: suffix=-validator + bake-target: validator + tags: type=raw,value=${{ github.head_ref || github.ref_name }} + - name: Docker tooler meta + id: docker_meta_tooler + uses: docker/metadata-action@v5 + with: + images: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPO }} + flavor: suffix=-tooler + bake-target: tooler + tags: type=raw,value=${{ github.head_ref || github.ref_name }} + + - name: Set Extra Bake Args + id: docker_bake_extra + shell: bash + run: | + { + echo 'EXTRA_BAKE_SET<> "$GITHUB_ENV" + - name: Bake base stages + id: bake_base_stages + uses: docker/bake-action@v4 + with: + pull: true + push: true + load: false + provenance: false + no-cache: false + targets: | + tooler + validator + set: | + *.cache-from=type=registry,ref=${{ env.ECR_REGISTRY }}/${{ env.INTEGRATION_REPO }}:main-tooler.cache + *.cache-to=type=s3,blobs_prefix=cache/${{ env.INTEGRATION_REPO }}/,manifests_prefix=cache/${{ env.INTEGRATION_REPO }}/,region=${{ env.RUNS_ON_AWS_REGION }},bucket=${{ env.RUNS_ON_S3_BUCKET_CACHE }},mode=max + ${{ env.EXTRA_BAKE_SET }} + files: | + ./docker-bake.hcl + ${{ steps.docker_meta_tooler.outputs.bake-file }} + ${{ steps.docker_meta_validator.outputs.bake-file }} + + - name: Get Layer Metadata + id: get_layer_metadata + uses: ros-navigation/navigation2/.github/actions/get-layer-metadata@main + with: + metadata: ${{ steps.bake_base_stages.outputs.metadata }} + load: false + - name: Job Workflow Info + id: job_workflow_info + shell: bash + run: | + overlay_cache_sha="${{ fromJSON(steps.get_layer_metadata.outputs.metadata)['tooler']['layer.digest'] }}" + overlay_cache_sha="${overlay_cache_sha#sha256:}" + overlay_cache_sha="$(echo $overlay_cache_sha | cut -c1-12)" + echo "overlay_cache_sha=${overlay_cache_sha}" >> $GITHUB_OUTPUT + + tooler_image_name="${{ fromJSON(steps.get_layer_metadata.outputs.metadata)['tooler']['image.name'] }}" + tooler_image_digest="${{ fromJSON(steps.get_layer_metadata.outputs.metadata)['tooler']['containerimage.digest'] }}" + tooler_image="${tooler_image_name}@${tooler_image_digest}" + echo "tooler_image=${tooler_image}" >> $GITHUB_OUTPUT + + validator_image_name="${{ fromJSON(steps.get_layer_metadata.outputs.metadata)['validator']['image.name'] }}" + validator_image_digest="${{ fromJSON(steps.get_layer_metadata.outputs.metadata)['validator']['containerimage.digest'] }}" + validator_image="${validator_image_name}@${validator_image_digest}" + echo "validator_image=${validator_image}" >> $GITHUB_OUTPUT + + cat << EOF > $GITHUB_STEP_SUMMARY + ## Base Images + | Image tag | Digest | + |-|-| + | \`${tooler_image_name##*:}\` | \`${tooler_image_digest}\` | + | \`${validator_image_name##*:}\` | \`${validator_image_digest}\` | + + ### tooler + \`\`\` + ${tooler_image} + \`\`\` + + ### validator + \`\`\` + ${validator_image} + \`\`\` + EOF diff --git a/.github/actions/bake-base-stages/lifecycle-policy.json b/.github/actions/bake-base-stages/lifecycle-policy.json new file mode 100644 index 0000000000..e23f44414a --- /dev/null +++ b/.github/actions/bake-base-stages/lifecycle-policy.json @@ -0,0 +1,17 @@ +{ + "rules": [ + { + "rulePriority": 1, + "description": "Expire untagged images 10 days since pushed", + "selection": { + "tagStatus": "untagged", + "countType": "sinceImagePushed", + "countUnit": "days", + "countNumber": 10 + }, + "action": { + "type": "expire" + } + } + ] +} diff --git a/.github/actions/bake-base-stages/repository-policy.json b/.github/actions/bake-base-stages/repository-policy.json new file mode 100644 index 0000000000..d21cc400ed --- /dev/null +++ b/.github/actions/bake-base-stages/repository-policy.json @@ -0,0 +1,26 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "DevAccountRead", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::abcdefghijk:root" + }, + "Action": [ + "ecr:BatchCheckLayerAvailability", + "ecr:BatchGetImage", + "ecr:DescribeImageScanFindings", + "ecr:DescribeImages", + "ecr:DescribeRepositories", + "ecr:GetAuthorizationToken", + "ecr:GetDownloadUrlForLayer", + "ecr:GetLifecyclePolicy", + "ecr:GetLifecyclePolicyPreview", + "ecr:GetRepositoryPolicy", + "ecr:ListImages", + "ecr:ListTagsForResource" + ] + } + ] + } diff --git a/.github/actions/bake-prod-stages/action.yml b/.github/actions/bake-prod-stages/action.yml new file mode 100644 index 0000000000..c70040011f --- /dev/null +++ b/.github/actions/bake-prod-stages/action.yml @@ -0,0 +1,152 @@ +name: "Bake prod stages" +description: "GitHub Action to bake prod stages and push images for CD" +author: 'ros-navigation' +branding: + icon: 'package' + color: 'blue' + +inputs: + cache_image: + required: true + type: string + description: The image to cache from via registry + integration_repo: + required: true + type: string + description: The repository to checkout for running CI + token: + required: true + type: string + description: The token to use for image registry login + +outputs: + metadata: + description: 'Layer result metadata' + value: ${{ steps.bake_prod_stages.outputs.metadata }} + releaser_image: + description: 'Docker image for releasing in production' + value: ${{ steps.job_workflow_info.outputs.releaser_image }} + debugger_image: + description: 'Docker image for debugging in production' + value: ${{ steps.job_workflow_info.outputs.debugger_image }} + +runs: + using: "composite" + steps: + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + cleanup: false + buildkitd-config-inline: | + [gc] + enabled = false + [worker.oci] + gc = false + [worker.containerd] + gc = false + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-region: ${{ env.RUNS_ON_AWS_REGION }} + - name: AWS ECR Login + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + - name: AWS ECR Info + shell: bash + run: | + echo "ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }}" >> $GITHUB_ENV + echo "INTEGRATION_REPO=$(basename ${{ inputs.integration_repo }})" >> $GITHUB_ENV + echo "ECR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV + + - name: Docker debugger meta + id: docker_meta_debugger + uses: docker/metadata-action@v5 + with: + images: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPO }} + flavor: suffix=-debugger + bake-target: debugger + tags: type=raw,value=${{ github.head_ref || github.ref_name }} + - name: Docker releaser meta + id: docker_meta_releaser + uses: docker/metadata-action@v5 + with: + images: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPO }} + flavor: suffix=-releaser + bake-target: releaser + tags: type=raw,value=${{ github.head_ref || github.ref_name }} + + - name: Set Extra Bake Args + id: docker_bake_extra + shell: bash + run: | + { + echo 'EXTRA_BAKE_SET<> "$GITHUB_ENV" + - name: Bake prod stages + id: bake_prod_stages + uses: docker/bake-action@v4 + with: + pull: true + push: true + load: false + provenance: false + no-cache: false + targets: | + debugger + releaser + set: | + *.args.CLEAR_WS_CACHE=${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }} + *.args.SEED_WS_CACHE=${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }} + *.args.EXPORT_FROM_STAGE=seeder + debugger.cache-from=type=registry,ref=${{ env.ECR_REGISTRY }}/${{ env.INTEGRATION_REPO }}:main-debugger.cache + releaser.cache-from=type=registry,ref=${{ env.ECR_REGISTRY }}/${{ env.INTEGRATION_REPO }}:main-releaser.cache + ${{ env.EXTRA_BAKE_SET }} + files: | + ./docker-bake.hcl + ${{ steps.docker_meta_debugger.outputs.bake-file }} + ${{ steps.docker_meta_releaser.outputs.bake-file }} + + - name: Job Workflow Info + id: job_workflow_info + shell: bash + run: | + debugger_image_name="${{ fromJSON(steps.bake_prod_stages.outputs.metadata)['debugger']['image.name'] }}" + debugger_image_digest="${{ fromJSON(steps.bake_prod_stages.outputs.metadata)['debugger']['containerimage.digest'] }}" + debugger_image="${debugger_image_name}@${debugger_image_digest}" + echo "debugger_image=${debugger_image}" >> $GITHUB_OUTPUT + + releaser_image_name="${{ fromJSON(steps.bake_prod_stages.outputs.metadata)['releaser']['image.name'] }}" + releaser_image_digest="${{ fromJSON(steps.bake_prod_stages.outputs.metadata)['releaser']['containerimage.digest'] }}" + releaser_image="${releaser_image_name}@${releaser_image_digest}" + echo "releaser_image=${releaser_image}" >> $GITHUB_OUTPUT + + cat << EOF > $GITHUB_STEP_SUMMARY + ## Prod Images + | Image tag | Digest | + |-|-| + | \`${debugger_image_name##*:}\` | \`${debugger_image_digest}\` | + | \`${releaser_image_name##*:}\` | \`${releaser_image_digest}\` | + + ### debugger + \`\`\` + ${debugger_image} + \`\`\` + + ### releaser + \`\`\` + ${releaser_image} + \`\`\` + EOF diff --git a/.github/actions/cache-source-checkout/action.yml b/.github/actions/cache-source-checkout/action.yml new file mode 100644 index 0000000000..2d6230a91e --- /dev/null +++ b/.github/actions/cache-source-checkout/action.yml @@ -0,0 +1,57 @@ +name: "Cache Source Checkout" +description: "GitHub Action to cache checkout of source repos" +author: 'ros-navigation' +branding: + icon: 'play-circle' + color: 'blue' + +inputs: + integration_repo: + required: true + type: string + description: The repository to checkout for running CI + overlay_ws: + required: true + type: string + description: The absolute path to the overlay workspace + +outputs: + checkout_cache_key: + description: 'Cache key to restore source checkout cache' + value: ${{ steps.cache_key_info.outputs.checkout_cache_key }} + +runs: + using: "composite" + steps: + - name: Cache key info + id: cache_key_info + shell: bash + run: | + checkout_cache_key="checkout-v1"\ + "-${{ github.ref }}"\ + "-${{ github.run_id }}"\ + "-${{ github.run_number }}"\ + "-${{ github.run_attempt }}" + echo "checkout_cache_key=${checkout_cache_key}" >> $GITHUB_OUTPUT + + - name: Checkout cache dance + id: cache_dance_info + shell: bash + run: | + overlay_ws_src="${{ inputs.overlay_ws }}/src" + echo "overlay_ws_src=${overlay_ws_src}" >> $GITHUB_OUTPUT + rm -rf $overlay_ws_src || true + + integration_repo_name=$(basename ${{ inputs.integration_repo }}) + integration_repo_path="$overlay_ws_src/$integration_repo_name" + mkdir -p $integration_repo_path + + shopt -s dotglob + mv ${{ github.workspace }}/* $integration_repo_path + + - name: Cache checkout + id: cache_checkout + uses: runs-on/cache@v4 + with: + path: ${{ steps.cache_dance_info.outputs.overlay_ws_src }}/ + key: ${{ steps.cache_key_info.outputs.checkout_cache_key }} diff --git a/.github/actions/get-layer-metadata/README.md b/.github/actions/get-layer-metadata/README.md new file mode 100644 index 0000000000..50369591e4 --- /dev/null +++ b/.github/actions/get-layer-metadata/README.md @@ -0,0 +1,60 @@ +# get-layer-metadata + +GitHub Action to get layer metadata from Docker Buildx Bake output result. + +## Usage + +```yaml +jobs: + get-layer-metadata: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Build and load + id: docker_bake_load + uses: docker/bake-action@v4 + with: + push: false + load: true + - name: Get Layer Metadata Locally + id: get_layer_metadata_local + uses: ros-navigation/navigation2/.github/actions/get-layer-metadata@main + with: + metadata: ${{ steps.docker_bake_load.outputs.metadata }} + load: true + + - name: Build and push + id: docker_bake_push + uses: docker/bake-action@v4 + with: + push: true + load: false + - name: Get Layer Metadata Remotely + id: get_layer_metadata_remote + uses: ros-navigation/navigation2/.github/actions/get-layer-metadata@main + with: + metadata: ${{ steps.docker_bake_push.outputs.metadata }} + load: false + + - name: Layer metadata + id: layer_metadata + run: | + local_layer_digest="${{ fromJSON(steps.get_layer_metadata_local.outputs.metadata)['']['layer.digest'] }}" + remote_layer_digest="${{ fromJSON(steps.get_layer_metadata_remote.outputs.metadata)['']['layer.digest'] }}" + +``` + +## Inputs + +| Name | Description | +| --- | --- | +| metadata | Build result metadata | +| load | Load is a shorthand to use local registry | + +## Outputs + +| Name | Description | +| --- | --- | +| metadata | Layer result metadata | \ No newline at end of file diff --git a/.github/actions/get-layer-metadata/action.yml b/.github/actions/get-layer-metadata/action.yml new file mode 100644 index 0000000000..cb6647a6c0 --- /dev/null +++ b/.github/actions/get-layer-metadata/action.yml @@ -0,0 +1,50 @@ +name: "Get Layer Metadata" +description: "GitHub Action to get layer metadata from Docker Buildx Bake output result" +author: 'ros-navigation' +branding: + icon: 'layers' + color: 'blue' + +inputs: + metadata: + description: 'Build result metadata' + required: true + load: + description: "Load is a shorthand to use local registry" + required: false + default: 'false' + +outputs: + metadata: + description: 'Layer result metadata' + value: ${{ steps.iterate_metadata.outputs.metadata }} + +runs: + using: "composite" + steps: + - name: Iterate Metadata + id: iterate_metadata + env: + METADATA_INPUT: ${{ inputs.metadata }} + LOAD: ${{ inputs.load }} + shell: bash + run: | + set -eo pipefail + metadata_output=$METADATA_INPUT + for target in $(jq -r 'keys[]' <<< $METADATA_INPUT); do + data=$(jq -r ".${target}" <<< $METADATA_INPUT) + if [[ $LOAD == 'true' ]]; then + image_digest=$(jq -r '."containerimage.config.digest"' <<< $data) + layer_digest=$(docker inspect $image_digest | jq -r '.[0].RootFS.Layers[-1]') + else + image_digest=$(jq -r '."containerimage.digest"' <<< $data) + image_name=$(jq -r '."image.name"' <<< $data) + layer_digest=$(docker buildx imagetools inspect --raw $image_name@$image_digest | jq -r '.layers[-1].digest') + fi + metadata_output=$(jq ".${target}.\"layer.digest\" = \"$layer_digest\"" <<< $metadata_output) + done + { + echo "metadata<> $GITHUB_OUTPUT \ No newline at end of file diff --git a/.github/workflows/build_prod_images.yaml b/.github/workflows/build_prod_images.yaml new file mode 100644 index 0000000000..aa76643c1d --- /dev/null +++ b/.github/workflows/build_prod_images.yaml @@ -0,0 +1,95 @@ +name: Build Prod Images + +on: + workflow_call: + inputs: + checkout_cache_key: + required: true + type: string + overlay_cache_key: + required: true + type: string + overlay_ws: + required: true + type: string + metadata: + required: true + type: string + runs_on: + required: true + type: string + cache_image: + required: true + type: string + outputs: + debugger_image: + value: ${{ jobs.build_prod_images.outputs.debugger_image }} + metadata: + value: ${{ jobs.build_prod_images.outputs.metadata }} + releaser_image: + value: ${{ jobs.build_prod_images.outputs.releaser_image }} + +jobs: + build_prod_images: + name: Build Images + outputs: + debugger_image: ${{ steps.bake_prod_stages.outputs.debugger_image }} + metadata: ${{ steps.bake_prod_stages.outputs.metadata }} + releaser_image: ${{ steps.bake_prod_stages.outputs.releaser_image }} + runs-on: ${{ inputs.runs_on }} + steps: + - name: Workspace cache prep + id: workspace_cache_prep + shell: bash + run: | + rm -rf ${{ inputs.overlay_ws }} || true + rm -rf /home/runner/${{ inputs.overlay_ws }} || true + + - name: Restore checkout + id: restore_checkout + uses: runs-on/cache/restore@v4 + with: + fail-on-cache-miss: true + path: ${{ inputs.overlay_ws }}/src/ + key: ${{ inputs.checkout_cache_key }} + - name: Restore overlay + id: restore_overlay + uses: runs-on/cache/restore@v4 + with: + fail-on-cache-miss: true + path: | + ${{ inputs.overlay_ws }}/build + ${{ inputs.overlay_ws }}/install + ${{ inputs.overlay_ws }}/test_results + key: ${{ inputs.overlay_cache_key }} + + - name: Workspace cache dance + id: workspace_cache_dance + shell: bash + run: | + overlay_ws_src="${{ inputs.overlay_ws }}/src" + integration_repo_name=$(basename ${{ github.repository }}) + integration_repo_path="$overlay_ws_src/$integration_repo_name" + + shopt -s dotglob + mv $integration_repo_path/* ${{ github.workspace }} + + overlay_ws_dir=$(dirname ${{ inputs.overlay_ws }}) + mkdir -p ${{ github.workspace }}/cache/$overlay_ws_dir + # FIXME: GitHub Cache Action restores caches relative to the working directory + # when the cache was intially saved, I.e. that of the orginating job container. + # Thus the restore_overlay step restores to ../../opt//... + # instead of simply /opt//... as the restore_checkout step does. + # In either case, paths outside of github.workspace could result in crosstalk + # if the same self-hosted runner VM is configured to run multiple concurrent jobs + mv /home/runner/${{ inputs.overlay_ws }} ${{ github.workspace }}/cache/$overlay_ws_dir/ + + tree -L 4 ${{ github.workspace }}/cache + + - name: Bake prod stages + id: bake_prod_stages + uses: ros-navigation/navigation2/.github/actions/bake-prod-stages@main + with: + cache_image: ${{ inputs.cache_image }} + integration_repo: ${{ github.repository }} + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/build_test.yaml b/.github/workflows/build_test.yaml new file mode 100644 index 0000000000..6e5e938e32 --- /dev/null +++ b/.github/workflows/build_test.yaml @@ -0,0 +1,30 @@ +name: Call + +on: + push: + branches: + - main + paths: + - '.github/workflows/build_prod_images.yaml' + - '.github/workflows/build_test_colcon.yaml' + - '.github/workflows/build_test_integration.yaml' + - '.github/workflows/build_test.yaml' + - 'docker-bake.hcl' + - 'Dockerfile' + - 'nav*/**' + pull_request: + paths: + - '.github/workflows/build_prod_images.yaml' + - '.github/workflows/build_test_colcon.yaml' + - '.github/workflows/build_test_integration.yaml' + - '.github/workflows/build_test.yaml' + - 'docker-bake.hcl' + - 'Dockerfile' + - 'nav*/**' + workflow_dispatch: + +jobs: + integration: + name: Integration + uses: ros-navigation/navigation2/.github/workflows/build_test_integration.yaml@main + secrets: inherit diff --git a/.github/workflows/build_test_colcon.yaml b/.github/workflows/build_test_colcon.yaml new file mode 100644 index 0000000000..655ae68a26 --- /dev/null +++ b/.github/workflows/build_test_colcon.yaml @@ -0,0 +1,219 @@ +name: Colcon Build and Test + +on: + workflow_call: + inputs: + checkout_cache_key: + required: true + type: string + overlay_cache_sha: + required: true + type: string + overlay_ws: + required: true + type: string + metadata: + required: true + type: string + runs_on: + required: true + type: string + tooler_image: + required: true + type: string + validator_image: + required: true + type: string + outputs: + overlay_cache_key: + value: ${{ jobs.test_colcon_workspace.outputs.overlay_cache_key }} + +jobs: + build_colcon_workspace: + name: Build Workspace + outputs: + overlay_cache_key: ${{ steps.cache_overlay_info.outputs.overlay_cache_key }} + build_packages: ${{ steps.check_differential.outputs.build_packages }} + runs-on: ${{ inputs.runs_on }} + container: + image: ${{ inputs.tooler_image }} + # NOTE: credentials needed for ECR login are set via RunsOn preinsall script + # https://github.com/runs-on/runs-on/discussions/71#discussioncomment-9280395 + # credentials: + # username: AWS + # password: + defaults: + run: + shell: bash + working-directory: ${{ inputs.overlay_ws }}/ + steps: + - name: Restore checkout + id: restore_checkout + uses: runs-on/cache@v4 + with: + fail-on-cache-miss: true + path: ${{ inputs.overlay_ws }}/src/ + key: ${{ inputs.checkout_cache_key }} + - name: Cache ccache + id: cache_ccache + uses: runs-on/cache@v4 + with: + save-always: true + path: | + ${{ inputs.overlay_ws }}/.ccache + key: "ccache-v1\ + -${{ github.ref }}\ + -${{ github.run_id }}\ + -${{ github.run_number }}\ + -${{ github.run_attempt }}" + restore-keys: | + ccache-v1-${{ github.ref }} + ccache-v1-refs/heads/${{ github.head_ref }} + ccache-v1-refs/heads/${{ github.base_ref }} + - name: Cache overlay info + id: cache_overlay_info + run: | + overlay_cache_key="overlay-v1"\ + "-${{ github.ref }}"\ + "-${{ inputs.overlay_cache_sha }}"\ + "-${{ github.run_id }}"\ + "-${{ github.run_number }}"\ + "-${{ github.run_attempt }}" + echo "overlay_cache_key=${overlay_cache_key}" >> $GITHUB_OUTPUT + - name: Cache overlay + id: cache_overlay + uses: runs-on/cache@v4 + with: + save-always: true + path: | + ${{ inputs.overlay_ws }}/build + ${{ inputs.overlay_ws }}/install + ${{ inputs.overlay_ws }}/test_results + key: ${{ steps.cache_overlay_info.outputs.overlay_cache_key }} + restore-keys: | + overlay-v1-${{ github.ref }}-${{ inputs.overlay_cache_sha }} + overlay-v1-refs/heads/${{ github.head_ref }}-${{ inputs.overlay_cache_sha }} + overlay-v1-refs/heads/${{ github.base_ref }}-${{ inputs.overlay_cache_sha }} + - name: Check Differential + id: check_differential + shell: bash + run: | + marked_base_paths=$(find ./src -name "COLCON_MARK" -exec dirname {} \; | xargs) + if [ -n "$marked_base_paths" ]; then + echo "Differential build detected!" + base_paths=$marked_base_paths + else + echo "Defaulting full build..." + base_paths='./src' + fi + BUILD_PACKAGES=$( + colcon list \ + --names-only \ + --base-paths $base_paths \ + | xargs) + echo BUILD_PACKAGES: $BUILD_PACKAGES + echo "build_packages=$BUILD_PACKAGES" >> $GITHUB_OUTPUT + - name: Ccache Info + run: | + ccache -z # zero stats + ccache -V # show version + ccache -p # show config + - name: Colcon Build + id: colcon_build + run: | + . /opt/ros/$ROS_DISTRO/setup.sh + colcon cache lock \ + --dirhash-reset + colcon clean packages -y \ + --packages-select-cache-invalid \ + --packages-select-cache-key build \ + --base-select install + colcon build \ + --packages-up-to \ + ${{ steps.check_differential.outputs.build_packages }} \ + --packages-skip-cache-valid \ + --mixin $OVERLAY_MIXINS + - name: Ccache Stats + if: always() + run: | + ccache -s # show stats + - name: Upload Logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: build-logs + path: ${{ inputs.overlay_ws }}/log/ + + test_colcon_workspace: + name: Test Workspace + outputs: + overlay_cache_key: ${{ needs.build_colcon_workspace.outputs.overlay_cache_key }}-${{ github.run_attempt }} + runs-on: ${{ inputs.runs_on }} + needs: + - build_colcon_workspace + container: + image: ${{ inputs.validator_image }} + # NOTE: credentials needed for ECR login are set via RunsOn preinsall script + # https://github.com/runs-on/runs-on/discussions/71#discussioncomment-9280395 + # credentials: + # username: AWS + # password: + defaults: + run: + shell: bash + working-directory: ${{ inputs.overlay_ws }}/ + steps: + - name: Restore checkout + id: restore_checkout + uses: runs-on/cache@v4 + with: + fail-on-cache-miss: true + path: ${{ inputs.overlay_ws }}/src/ + key: ${{ inputs.checkout_cache_key }} + - name: Cache overlay + id: cache_overlay + uses: runs-on/cache@v4 + with: + save-always: true + path: | + ${{ inputs.overlay_ws }}/build + ${{ inputs.overlay_ws }}/install + ${{ inputs.overlay_ws }}/test_results + key: ${{ needs.build_colcon_workspace.outputs.overlay_cache_key }}-${{ github.run_attempt }} + restore-keys: | + ${{ needs.build_colcon_workspace.outputs.overlay_cache_key }} + - name: Colcon Test + id: colcon_test + run: | + . install/setup.sh + colcon test \ + --packages-select \ + ${{ needs.build_colcon_workspace.outputs.build_packages }} \ + --packages-skip-cache-valid + TEST_FAILURES=$( + colcon list \ + --names-only \ + --packages-select-test-failures \ + | xargs) + echo TEST_FAILURES: $TEST_FAILURES + TEST_UNFINISHED=$( + colcon list \ + --names-only \ + --packages-skip-test-passed \ + | xargs) + echo TEST_UNFINISHED: $TEST_UNFINISHED + colcon test-result \ + --verbose \ + || true + - name: Upload Logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-logs + path: ${{ inputs.overlay_ws }}/log/ + - name: Upload Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results + path: ${{ inputs.overlay_ws }}/test_results/ diff --git a/.github/workflows/build_test_integration.yaml b/.github/workflows/build_test_integration.yaml new file mode 100644 index 0000000000..44ee25dab0 --- /dev/null +++ b/.github/workflows/build_test_integration.yaml @@ -0,0 +1,96 @@ +name: Integration Build and Test + +on: + workflow_call: + inputs: + integration_ref: + required: false + type: string + default: ${{ github.sha }} + integration_repo: + required: false + type: string + default: ${{ github.repository }} + runs_on: + required: false + type: string + default: runs-on,run-id=${{ github.run_id }},image=ecr_login_image + workflow_dispatch: + inputs: + integration_ref: + required: true + type: string + integration_repo: + required: false + type: string + default: 'ros-navigation/navigation2' + runs_on: + required: true + type: string + +env: + OVERLAY_WS: /opt/auto_ws + +jobs: + build_base_images: + name: Build Base Images + outputs: + checkout_cache_key: ${{ steps.cache_source_checkout.outputs.checkout_cache_key }} + metadata: ${{ steps.bake_base_stages.outputs.metadata }} + overlay_cache_sha: ${{ steps.bake_base_stages.outputs.overlay_cache_sha }} + overlay_ws: ${{ env.OVERLAY_WS }} + tooler_image: ${{ steps.bake_base_stages.outputs.tooler_image }} + validator_image: ${{ steps.bake_base_stages.outputs.validator_image }} + runs-on: ${{ inputs.runs_on }},runner=2cpu-linux-x64 + steps: + - name: Checkout Integration Repo + id: checkout_integration_repo + uses: actions/checkout@v4 + with: + ref: ${{ inputs.integration_ref }} + repository: ${{ inputs.integration_repo }} + token: ${{ secrets.GIT_CHECKOUT_PAT }} + submodules: 'recursive' + + - name: Bake base stages + id: bake_base_stages + uses: ros-navigation/navigation2/.github/actions/bake-base-stages@main + with: + integration_repo: ${{ inputs.integration_repo }} + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Cache source checkout + id: cache_source_checkout + uses: ros-navigation/navigation2/.github/actions/cache-source-checkout@main + with: + integration_repo: ${{ inputs.integration_repo }} + overlay_ws: ${{ env.OVERLAY_WS }} + + colcon_build_test: + name: Colcon + uses: ros-navigation/navigation2/.github/workflows/build_test_colcon.yaml@main + secrets: inherit + needs: build_base_images + with: + checkout_cache_key: ${{ needs.build_base_images.outputs.checkout_cache_key }} + metadata: ${{ needs.build_base_images.outputs.metadata }} + overlay_cache_sha: ${{ needs.build_base_images.outputs.overlay_cache_sha }} + overlay_ws: ${{ needs.build_base_images.outputs.overlay_ws }} + runs_on: ${{ inputs.runs_on }},runner=4cpu-linux-x64 + tooler_image: ${{ needs.build_base_images.outputs.tooler_image }} + validator_image: ${{ needs.build_base_images.outputs.validator_image }} + + build_prod_images: + name: Prod + uses: ros-navigation/navigation2/.github/workflows/build_prod_images.yaml@main + secrets: inherit + needs: + - build_base_images + - colcon_build_test + with: + cache_image: ${{ needs.build_base_images.outputs.tooler_image }} + checkout_cache_key: ${{ needs.build_base_images.outputs.checkout_cache_key }} + metadata: ${{ needs.build_base_images.outputs.metadata }} + overlay_cache_key: ${{ needs.colcon_build_test.outputs.overlay_cache_key }} + overlay_ws: ${{ needs.build_base_images.outputs.overlay_ws }} + runs_on: ${{ inputs.runs_on }},runner=2cpu-linux-x64 diff --git a/.github/workflows/ecr_retention.yaml b/.github/workflows/ecr_retention.yaml new file mode 100644 index 0000000000..702a88db4c --- /dev/null +++ b/.github/workflows/ecr_retention.yaml @@ -0,0 +1,72 @@ +name: ECR Retention Policy + +on: + pull_request: + types: + - closed + workflow_call: + workflow_dispatch: + +jobs: + clean-unused-ecr: + name: Delete unused container images + runs-on: runs-on,runner=2cpu-linux-x64,run-id=${{ github.run_id }},image=ecr_login_image + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-region: ${{ env.RUNS_ON_AWS_REGION }} + - name: AWS ECR Login + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + - name: AWS ECR Info + shell: bash + run: | + echo "ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }}" >> $GITHUB_ENV + echo "ECR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV + - name: Docker meta + id: docker_meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPO }} + flavor: suffix=- + tags: type=raw,value=${{ github.head_ref || github.ref_name }} + # NOTE: This is convoluted because AWS ECR has no simple way to untag image without deletion + # given we want to leave deletion of untagged image to the ECR repo's own lifecycle policy + # https://stackoverflow.com/questions/70065254/remove-ecr-image-tag-despite-imagereferencedbymanifestlist-error + # https://github.com/aws/containers-roadmap/issues/1567 + - name: AWS ECR Cleanup + shell: bash + run: | + REPO_EXISTS=$(aws ecr describe-repositories --repository-names $ECR_REPO 2>&1 || true) + if echo "${REPO_EXISTS}" | grep -q 'RepositoryNotFoundException'; then + echo "Repository not found, skipping cleanup." + exit 0 + fi + IMAGE_TAGS=$(aws ecr list-images --repository-name $ECR_REPO --query 'imageIds[*].imageTag' --output text) + + docker pull busybox + docker tag busybox $ECR_REGISTRY/$ECR_REPO:_ + docker push $ECR_REGISTRY/$ECR_REPO:_ + + TEMP_IMAGE=$( + aws ecr batch-get-image \ + --repository-name $ECR_REPO \ + --image-ids imageTag=_ ) + TEMP_MANIFEST=$(echo $TEMP_IMAGE | jq -r '.images[].imageManifest') + TEMP_DIGEST=$(echo $TEMP_IMAGE | jq -r '.images[].imageId.imageDigest') + + TAG_PREFIX=$(echo ${{ fromJSON(steps.docker_meta.outputs.json).tags[0] }} | cut -d: -f2) + for TAG in $IMAGE_TAGS + do + if [[ $TAG == $TAG_PREFIX* ]]; then + docker tag busybox $ECR_REGISTRY/$ECR_REPO:$TAG + docker push $ECR_REGISTRY/$ECR_REPO:$TAG + echo "Untaged image $TAG" + fi + done + + # Delete the temporary image by digest + aws ecr batch-delete-image \ + --repository-name $ECR_REPO \ + --image-ids imageDigest=$TEMP_DIGEST diff --git a/.github/workflows/ghac_eviction.yaml b/.github/workflows/ghac_eviction.yaml new file mode 100644 index 0000000000..8a74e2a57b --- /dev/null +++ b/.github/workflows/ghac_eviction.yaml @@ -0,0 +1,47 @@ +name: GH Action Cache Eviction Policy + +on: + pull_request: + types: + - closed + workflow_dispatch: + +jobs: + clean-ghac: + name: Delete old unused action caches + runs-on: ubuntu-latest + permissions: + actions: write + contents: read + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Cleanup + run: | + gh extension install actions/gh-actions-cache + + REPO=${{ github.repository }} + BRANCH=refs/pull/${{ github.event.pull_request.number }}/merge + + # loop until the list is empty, because it deletes only 30 per page + has_items=true + while [ "$has_items" = true ] + do + echo "Fetching list of cache key" + cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 ) + if [ -z "$cache_keys" ]; then + has_items=false + fi + + ## Setting this to not fail the workflow while deleting cache keys. + set +e + echo "Deleting caches..." + for cacheKey in $cacheKeysForPR + do + gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm + done + done + echo "Done" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From b0dd1316f0a05e9ac4e2881c6048c9d814e89515 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 21:51:37 -0500 Subject: [PATCH 07/64] Comment out CI trigger while WIP --- .github/workflows/build_test.yaml | 40 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build_test.yaml b/.github/workflows/build_test.yaml index 6e5e938e32..6e7bf1cb45 100644 --- a/.github/workflows/build_test.yaml +++ b/.github/workflows/build_test.yaml @@ -1,26 +1,26 @@ name: Call on: - push: - branches: - - main - paths: - - '.github/workflows/build_prod_images.yaml' - - '.github/workflows/build_test_colcon.yaml' - - '.github/workflows/build_test_integration.yaml' - - '.github/workflows/build_test.yaml' - - 'docker-bake.hcl' - - 'Dockerfile' - - 'nav*/**' - pull_request: - paths: - - '.github/workflows/build_prod_images.yaml' - - '.github/workflows/build_test_colcon.yaml' - - '.github/workflows/build_test_integration.yaml' - - '.github/workflows/build_test.yaml' - - 'docker-bake.hcl' - - 'Dockerfile' - - 'nav*/**' + # push: + # branches: + # - main + # paths: + # - '.github/workflows/build_prod_images.yaml' + # - '.github/workflows/build_test_colcon.yaml' + # - '.github/workflows/build_test_integration.yaml' + # - '.github/workflows/build_test.yaml' + # - 'docker-bake.hcl' + # - 'Dockerfile' + # - 'nav*/**' + # pull_request: + # paths: + # - '.github/workflows/build_prod_images.yaml' + # - '.github/workflows/build_test_colcon.yaml' + # - '.github/workflows/build_test_integration.yaml' + # - '.github/workflows/build_test.yaml' + # - 'docker-bake.hcl' + # - 'Dockerfile' + # - 'nav*/**' workflow_dispatch: jobs: From 35d28c7358e89f53688446faf23002dcd3d5fd71 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 21:57:41 -0500 Subject: [PATCH 08/64] Rollback RunsOn cache action to use GitHub's cache --- .github/actions/cache-source-checkout/action.yml | 2 +- .github/workflows/build_prod_images.yaml | 4 ++-- .github/workflows/build_test_colcon.yaml | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/actions/cache-source-checkout/action.yml b/.github/actions/cache-source-checkout/action.yml index 2d6230a91e..7db410e89a 100644 --- a/.github/actions/cache-source-checkout/action.yml +++ b/.github/actions/cache-source-checkout/action.yml @@ -51,7 +51,7 @@ runs: - name: Cache checkout id: cache_checkout - uses: runs-on/cache@v4 + uses: actions/cache@v4 with: path: ${{ steps.cache_dance_info.outputs.overlay_ws_src }}/ key: ${{ steps.cache_key_info.outputs.checkout_cache_key }} diff --git a/.github/workflows/build_prod_images.yaml b/.github/workflows/build_prod_images.yaml index aa76643c1d..dc0ba54d1b 100644 --- a/.github/workflows/build_prod_images.yaml +++ b/.github/workflows/build_prod_images.yaml @@ -47,14 +47,14 @@ jobs: - name: Restore checkout id: restore_checkout - uses: runs-on/cache/restore@v4 + uses: actions/cache/restore@v4 with: fail-on-cache-miss: true path: ${{ inputs.overlay_ws }}/src/ key: ${{ inputs.checkout_cache_key }} - name: Restore overlay id: restore_overlay - uses: runs-on/cache/restore@v4 + uses: actions/cache/restore@v4 with: fail-on-cache-miss: true path: | diff --git a/.github/workflows/build_test_colcon.yaml b/.github/workflows/build_test_colcon.yaml index 655ae68a26..b42c76dac0 100644 --- a/.github/workflows/build_test_colcon.yaml +++ b/.github/workflows/build_test_colcon.yaml @@ -49,14 +49,14 @@ jobs: steps: - name: Restore checkout id: restore_checkout - uses: runs-on/cache@v4 + uses: actions/cache@v4 with: fail-on-cache-miss: true path: ${{ inputs.overlay_ws }}/src/ key: ${{ inputs.checkout_cache_key }} - name: Cache ccache id: cache_ccache - uses: runs-on/cache@v4 + uses: actions/cache@v4 with: save-always: true path: | @@ -82,7 +82,7 @@ jobs: echo "overlay_cache_key=${overlay_cache_key}" >> $GITHUB_OUTPUT - name: Cache overlay id: cache_overlay - uses: runs-on/cache@v4 + uses: actions/cache@v4 with: save-always: true path: | @@ -165,14 +165,14 @@ jobs: steps: - name: Restore checkout id: restore_checkout - uses: runs-on/cache@v4 + uses: actions/cache@v4 with: fail-on-cache-miss: true path: ${{ inputs.overlay_ws }}/src/ key: ${{ inputs.checkout_cache_key }} - name: Cache overlay id: cache_overlay - uses: runs-on/cache@v4 + uses: actions/cache@v4 with: save-always: true path: | From e78549efaf3ef6f289e69eba2c9831255002bd97 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 22:00:49 -0500 Subject: [PATCH 09/64] Roll back RunsOn runner tags --- .github/workflows/build_test_integration.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_test_integration.yaml b/.github/workflows/build_test_integration.yaml index 44ee25dab0..029fbd1c27 100644 --- a/.github/workflows/build_test_integration.yaml +++ b/.github/workflows/build_test_integration.yaml @@ -14,7 +14,7 @@ on: runs_on: required: false type: string - default: runs-on,run-id=${{ github.run_id }},image=ecr_login_image + default: ubuntu-latest workflow_dispatch: inputs: integration_ref: @@ -41,7 +41,7 @@ jobs: overlay_ws: ${{ env.OVERLAY_WS }} tooler_image: ${{ steps.bake_base_stages.outputs.tooler_image }} validator_image: ${{ steps.bake_base_stages.outputs.validator_image }} - runs-on: ${{ inputs.runs_on }},runner=2cpu-linux-x64 + runs-on: ${{ inputs.runs_on }} steps: - name: Checkout Integration Repo id: checkout_integration_repo @@ -76,7 +76,7 @@ jobs: metadata: ${{ needs.build_base_images.outputs.metadata }} overlay_cache_sha: ${{ needs.build_base_images.outputs.overlay_cache_sha }} overlay_ws: ${{ needs.build_base_images.outputs.overlay_ws }} - runs_on: ${{ inputs.runs_on }},runner=4cpu-linux-x64 + runs_on: ${{ inputs.runs_on }} tooler_image: ${{ needs.build_base_images.outputs.tooler_image }} validator_image: ${{ needs.build_base_images.outputs.validator_image }} @@ -93,4 +93,4 @@ jobs: metadata: ${{ needs.build_base_images.outputs.metadata }} overlay_cache_key: ${{ needs.colcon_build_test.outputs.overlay_cache_key }} overlay_ws: ${{ needs.build_base_images.outputs.overlay_ws }} - runs_on: ${{ inputs.runs_on }},runner=2cpu-linux-x64 + runs_on: ${{ inputs.runs_on }} From e9c2769be19b9665ac28f105176bcda2f877c717 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 22:15:46 -0500 Subject: [PATCH 10/64] Roll back AWS ECR changes to use GHCR --- .github/actions/bake-base-stages/action.yml | 41 ++++------- .../bake-base-stages/lifecycle-policy.json | 17 ----- .../bake-base-stages/repository-policy.json | 26 ------- .github/actions/bake-prod-stages/action.yml | 27 ++++--- .github/workflows/ecr_retention.yaml | 72 ------------------- .github/workflows/ghcr_retention.yaml | 46 ++++++++++++ 6 files changed, 72 insertions(+), 157 deletions(-) delete mode 100644 .github/actions/bake-base-stages/lifecycle-policy.json delete mode 100644 .github/actions/bake-base-stages/repository-policy.json delete mode 100644 .github/workflows/ecr_retention.yaml create mode 100644 .github/workflows/ghcr_retention.yaml diff --git a/.github/actions/bake-base-stages/action.yml b/.github/actions/bake-base-stages/action.yml index e3eb10aa5c..ed012c85dd 100644 --- a/.github/actions/bake-base-stages/action.yml +++ b/.github/actions/bake-base-stages/action.yml @@ -47,39 +47,24 @@ runs: [worker.containerd] gc = false - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 with: - aws-region: ${{ env.RUNS_ON_AWS_REGION }} - - name: AWS ECR Login - id: login-ecr - uses: aws-actions/amazon-ecr-login@v2 - - name: AWS ECR Info + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ inputs.token }} + - name: GHCR Info shell: bash run: | - echo "ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }}" >> $GITHUB_ENV + echo "GHCR_REGISTRY=ghcr.io" >> $GITHUB_ENV echo "INTEGRATION_REPO=$(basename ${{ inputs.integration_repo }})" >> $GITHUB_ENV - echo "ECR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV - - name: AWS ECR Init - shell: bash - run: | - REPO_EXISTS=$(aws ecr describe-repositories --repository-names ${{ env.ECR_REPO }} 2>&1 || true) - if echo "${REPO_EXISTS}" | grep -q 'RepositoryNotFoundException'; then - aws ecr create-repository \ - --repository-name ${{ env.ECR_REPO }} - aws ecr put-lifecycle-policy \ - --repository-name ${{ env.ECR_REPO }} \ - --lifecycle-policy-text file://${{ github.action_path }}/lifecycle-policy.json - aws ecr set-repository-policy \ - --repository-name ${{ env.ECR_REPO }} \ - --policy-text file://${{ github.action_path }}/repository-policy.json - fi + echo "GHCR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV - name: Docker validator meta id: docker_meta_validator uses: docker/metadata-action@v5 with: - images: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPO }} + images: ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_REPO }} flavor: suffix=-validator bake-target: validator tags: type=raw,value=${{ github.head_ref || github.ref_name }} @@ -87,7 +72,7 @@ runs: id: docker_meta_tooler uses: docker/metadata-action@v5 with: - images: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPO }} + images: ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_REPO }} flavor: suffix=-tooler bake-target: tooler tags: type=raw,value=${{ github.head_ref || github.ref_name }} @@ -98,12 +83,12 @@ runs: run: | { echo 'EXTRA_BAKE_SET<> $GITHUB_ENV + echo "GHCR_REGISTRY=ghcr.io" >> $GITHUB_ENV echo "INTEGRATION_REPO=$(basename ${{ inputs.integration_repo }})" >> $GITHUB_ENV - echo "ECR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV + echo "GHCR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV - name: Docker debugger meta id: docker_meta_debugger uses: docker/metadata-action@v5 with: - images: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPO }} + images: ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_REPO }} flavor: suffix=-debugger bake-target: debugger tags: type=raw,value=${{ github.head_ref || github.ref_name }} @@ -71,7 +70,7 @@ runs: id: docker_meta_releaser uses: docker/metadata-action@v5 with: - images: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPO }} + images: ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_REPO }} flavor: suffix=-releaser bake-target: releaser tags: type=raw,value=${{ github.head_ref || github.ref_name }} @@ -82,7 +81,7 @@ runs: run: | { echo 'EXTRA_BAKE_SET<> $GITHUB_ENV - echo "ECR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV - - name: Docker meta - id: docker_meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPO }} - flavor: suffix=- - tags: type=raw,value=${{ github.head_ref || github.ref_name }} - # NOTE: This is convoluted because AWS ECR has no simple way to untag image without deletion - # given we want to leave deletion of untagged image to the ECR repo's own lifecycle policy - # https://stackoverflow.com/questions/70065254/remove-ecr-image-tag-despite-imagereferencedbymanifestlist-error - # https://github.com/aws/containers-roadmap/issues/1567 - - name: AWS ECR Cleanup - shell: bash - run: | - REPO_EXISTS=$(aws ecr describe-repositories --repository-names $ECR_REPO 2>&1 || true) - if echo "${REPO_EXISTS}" | grep -q 'RepositoryNotFoundException'; then - echo "Repository not found, skipping cleanup." - exit 0 - fi - IMAGE_TAGS=$(aws ecr list-images --repository-name $ECR_REPO --query 'imageIds[*].imageTag' --output text) - - docker pull busybox - docker tag busybox $ECR_REGISTRY/$ECR_REPO:_ - docker push $ECR_REGISTRY/$ECR_REPO:_ - - TEMP_IMAGE=$( - aws ecr batch-get-image \ - --repository-name $ECR_REPO \ - --image-ids imageTag=_ ) - TEMP_MANIFEST=$(echo $TEMP_IMAGE | jq -r '.images[].imageManifest') - TEMP_DIGEST=$(echo $TEMP_IMAGE | jq -r '.images[].imageId.imageDigest') - - TAG_PREFIX=$(echo ${{ fromJSON(steps.docker_meta.outputs.json).tags[0] }} | cut -d: -f2) - for TAG in $IMAGE_TAGS - do - if [[ $TAG == $TAG_PREFIX* ]]; then - docker tag busybox $ECR_REGISTRY/$ECR_REPO:$TAG - docker push $ECR_REGISTRY/$ECR_REPO:$TAG - echo "Untaged image $TAG" - fi - done - - # Delete the temporary image by digest - aws ecr batch-delete-image \ - --repository-name $ECR_REPO \ - --image-ids imageDigest=$TEMP_DIGEST diff --git a/.github/workflows/ghcr_retention.yaml b/.github/workflows/ghcr_retention.yaml new file mode 100644 index 0000000000..2a8f65d627 --- /dev/null +++ b/.github/workflows/ghcr_retention.yaml @@ -0,0 +1,46 @@ +name: GHCR Container Retention Policy + +on: + pull_request: + types: + - closed + schedule: + - cron: "0 0 * * *" # every day at midnight + workflow_dispatch: + +jobs: + clean-old-ghcr: + name: Delete old container images + if: github.event_name == 'schedule' + runs-on: ubuntu-latest + steps: + - name: Delete untagged containers + uses: snok/container-retention-policy@v2.2.1 + with: + image-names: navigation2 + cut-off: A day ago UTC + account-type: org + org-name: ros-navigation + # keep-at-least: 0 + untagged-only: true + token: ${{ secrets.GHCR_RETENTION_PAT }} + dry-run: false + clean-unused-ghcr: + name: Delete unused container images + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Delete untagged containers + uses: snok/container-retention-policy@v2.2.1 + with: + image-names: navigation2 + cut-off: now UTC + account-type: org + org-name: ros-navigation + # keep-at-least: 0 + # TODO: come up with a better way to filter out the PRs + # as well as a better tag naming convention + filter-tags: "${{ github.head_ref || github.ref_name }}-*" + untagged-only: false + token: ${{ secrets.GHCR_RETENTION_PAT }} + dry-run: false From 44c45d4cfd41eb2f9158f53fe1d79bd0b034003c Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 22:23:06 -0500 Subject: [PATCH 11/64] Update retention to use sanitized tag names --- .github/workflows/ghcr_retention.yaml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ghcr_retention.yaml b/.github/workflows/ghcr_retention.yaml index 2a8f65d627..42d07ffbb5 100644 --- a/.github/workflows/ghcr_retention.yaml +++ b/.github/workflows/ghcr_retention.yaml @@ -30,6 +30,18 @@ jobs: if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: + - name: GHCR Info + shell: bash + run: | + echo "GHCR_REGISTRY=ghcr.io" >> $GITHUB_ENV + echo "GHCR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV + - name: Docker meta + id: docker_meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_REPO }} + flavor: suffix=- + tags: type=raw,value=${{ github.head_ref || github.ref_name }} - name: Delete untagged containers uses: snok/container-retention-policy@v2.2.1 with: @@ -40,7 +52,7 @@ jobs: # keep-at-least: 0 # TODO: come up with a better way to filter out the PRs # as well as a better tag naming convention - filter-tags: "${{ github.head_ref || github.ref_name }}-*" + filter-tags: "${{ fromJSON(steps.docker_meta.outputs.json).tags[0] }}*" untagged-only: false token: ${{ secrets.GHCR_RETENTION_PAT }} dry-run: false From f27f3a247f7691a9adfca2607220e7b0e2d3471c Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 22:30:25 -0500 Subject: [PATCH 12/64] Add debugger and releaser bake targets --- Dockerfile | 20 ++++++++++++++++++++ docker-bake.hcl | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/Dockerfile b/Dockerfile index a279c2567f..9725d93e38 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,7 @@ ARG DEV_FROM_STAGE=tooler ARG EXPORT_FROM_STAGE=builder ARG PREP_FROM_STAGE=runner +ARG SHIP_FROM_STAGE=runner ARG WS_CACHE_ID=nav2 ARG FROM_IMAGE=base @@ -263,3 +264,22 @@ RUN --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS,readon FROM $EXPORT_FROM_STAGE as exporter COPY --link --from=dancer /dancer/$OVERLAY_WS $OVERLAY_WS + +################################################################################ +# MARK: shipper - setup production images using shared instructions +################################################################################ +FROM $SHIP_FROM_STAGE as shipper + +################################################################################ +# MARK: debugger - stage target for debuggin in production +################################################################################ +FROM shipper as debugger + +COPY --link --from=dancer /dancer/$OVERLAY_WS $OVERLAY_WS + +################################################################################ +# MARK: releaser - stage target for releasing in production +################################################################################ +FROM shipper as releaser + +COPY --link --from=dancer /dancer/$OVERLAY_WS/install $OVERLAY_WS/install \ No newline at end of file diff --git a/docker-bake.hcl b/docker-bake.hcl index be18b67efd..942087d806 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -108,3 +108,38 @@ target "exporter" { target = "exporter" tags = ["nav2:exporter"] } + +################################################################################ +// MARK: Production targets +################################################################################ + +target "shipper" { + inherits = ["dancer"] + target = "shipper" + args = { + } +} + +target "releaser" { + inherits = ["shipper"] + target = "releaser" + tags = ["nav2:releaser"] + args = { + SHIP_FROM_STAGE = "runner", + } + cache-from = [ + // "type=registry,ref=${registry}/${repo}:main-releaser.cache", + ] +} + +target "debugger" { + inherits = ["shipper"] + target = "debugger" + tags = ["nav2:debugger"] + args = { + SHIP_FROM_STAGE = "tooler", + } + cache-from = [ + // "type=registry,ref=${registry}/${repo}:main-debugger.cache", + ] +} From 37887b9367f57e3d4c05119c259af5cddacfe674 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 22:31:40 -0500 Subject: [PATCH 13/64] Clean ECR comments --- .github/workflows/build_test_colcon.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/build_test_colcon.yaml b/.github/workflows/build_test_colcon.yaml index b42c76dac0..2a4989ca0a 100644 --- a/.github/workflows/build_test_colcon.yaml +++ b/.github/workflows/build_test_colcon.yaml @@ -37,11 +37,6 @@ jobs: runs-on: ${{ inputs.runs_on }} container: image: ${{ inputs.tooler_image }} - # NOTE: credentials needed for ECR login are set via RunsOn preinsall script - # https://github.com/runs-on/runs-on/discussions/71#discussioncomment-9280395 - # credentials: - # username: AWS - # password: defaults: run: shell: bash @@ -153,11 +148,6 @@ jobs: - build_colcon_workspace container: image: ${{ inputs.validator_image }} - # NOTE: credentials needed for ECR login are set via RunsOn preinsall script - # https://github.com/runs-on/runs-on/discussions/71#discussioncomment-9280395 - # credentials: - # username: AWS - # password: defaults: run: shell: bash From dc16919d79c450ff2073655fbf799721790a6e7b Mon Sep 17 00:00:00 2001 From: ruffsl Date: Mon, 3 Jun 2024 22:33:43 -0500 Subject: [PATCH 14/64] Remove debugging command for test workflow --- .github/workflows/build_test_colcon.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build_test_colcon.yaml b/.github/workflows/build_test_colcon.yaml index 2a4989ca0a..64cec3561c 100644 --- a/.github/workflows/build_test_colcon.yaml +++ b/.github/workflows/build_test_colcon.yaml @@ -193,8 +193,7 @@ jobs: | xargs) echo TEST_UNFINISHED: $TEST_UNFINISHED colcon test-result \ - --verbose \ - || true + --verbose - name: Upload Logs if: always() uses: actions/upload-artifact@v4 From b4ff763a3a3e324c05d731add5e208f58494215c Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 8 Jun 2024 14:16:04 -0500 Subject: [PATCH 15/64] Move docker stuff into .docker path --- {tools => .docker}/.ccache/ccache.conf | 0 {tools => .docker}/.colcon/defaults.yaml | 0 Dockerfile => .docker/Dockerfile | 0 {tools => .docker}/runner_apt_debs.txt | 0 {tools => .docker}/tooler_apt_deps.txt | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {tools => .docker}/.ccache/ccache.conf (100%) rename {tools => .docker}/.colcon/defaults.yaml (100%) rename Dockerfile => .docker/Dockerfile (100%) rename {tools => .docker}/runner_apt_debs.txt (100%) rename {tools => .docker}/tooler_apt_deps.txt (100%) diff --git a/tools/.ccache/ccache.conf b/.docker/.ccache/ccache.conf similarity index 100% rename from tools/.ccache/ccache.conf rename to .docker/.ccache/ccache.conf diff --git a/tools/.colcon/defaults.yaml b/.docker/.colcon/defaults.yaml similarity index 100% rename from tools/.colcon/defaults.yaml rename to .docker/.colcon/defaults.yaml diff --git a/Dockerfile b/.docker/Dockerfile similarity index 100% rename from Dockerfile rename to .docker/Dockerfile diff --git a/tools/runner_apt_debs.txt b/.docker/runner_apt_debs.txt similarity index 100% rename from tools/runner_apt_debs.txt rename to .docker/runner_apt_debs.txt diff --git a/tools/tooler_apt_deps.txt b/.docker/tooler_apt_deps.txt similarity index 100% rename from tools/tooler_apt_deps.txt rename to .docker/tooler_apt_deps.txt From 2b0bae0b8c4c77b96efe36ef1e35197fd4b9b41b Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 8 Jun 2024 14:22:44 -0500 Subject: [PATCH 16/64] Update docker paths --- .docker/Dockerfile | 8 ++++---- .dockerignore | 5 ++++- docker-bake.hcl | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index 9725d93e38..1061a0784e 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -82,7 +82,7 @@ RUN dep_types=(\ FROM baser as runner # install packages for field work -COPY tools/runner_apt_debs.txt /tmp/runner_apt_debs.txt +COPY .docker/runner_apt_debs.txt /tmp/runner_apt_debs.txt RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ cut -d# -f1 < /tmp/runner_apt_debs.txt | envsubst \ | xargs apt-get install -y --no-install-recommends @@ -134,18 +134,18 @@ RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ < /tmp/rosdep_build_debs.txt xargs apt-get install -y --no-install-recommends # install packages for build work -COPY tools/tooler_apt_deps.txt /tmp/tooler_apt_deps.txt +COPY .docker/tooler_apt_deps.txt /tmp/tooler_apt_deps.txt RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ cut -d# -f1 < /tmp/tooler_apt_deps.txt | envsubst \ | xargs apt-get install -y --no-install-recommends # setup default ccache configuration -COPY tools/.ccache/ccache.conf /opt/.ccache/ +COPY .docker/.ccache/ccache.conf /opt/.ccache/ ENV CCACHE_CONFIGPATH="/opt/.ccache/ccache.conf" ENV CCACHE_DIR="$OVERLAY_WS/.ccache" # setup default colcon configuration -COPY tools/.colcon/defaults.yaml $COLCON_HOME/ +COPY .docker/.colcon/defaults.yaml $COLCON_HOME/ ARG OVERLAY_MIXINS="release ccache lld" ENV OVERLAY_MIXINS=${OVERLAY_MIXINS} diff --git a/.dockerignore b/.dockerignore index 57395a5850..81b138b3df 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,4 +4,7 @@ # First-order allow exception for select directories !/cache !/nav* -!/tools +!/.docker + +# Second-order deny exception for Dockerfile +/.docker/Dockerfile diff --git a/docker-bake.hcl b/docker-bake.hcl index 942087d806..b7da477591 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -21,6 +21,7 @@ target "baser" { cache-from = [ // "type=registry,ref=${registry}/${repo}:main-tooler.cache", ] + dockerfile = ".docker/Dockerfile" } target "cacher" { From 667a8ff2a13abe7d60438acef1e4d141efa99e97 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 8 Jun 2024 14:27:05 -0500 Subject: [PATCH 17/64] Mount user home as volume to persist dotfiles across container lifecycle such as bash history --- .devcontainer/devcontainer.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7cfcc5d358..0b4038398b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -54,6 +54,12 @@ "source": "overlay-${devcontainerId}", "target": "/opt/nav2_ws", "type": "volume" + }, + { + // Mount home dotfiles + "source": "nav2-home", + "target": "/home/ubuntu", + "type": "volume" } ], "features": { From 18bf8a46cf0c0db8fe06525e06bf967dafb1f26b Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 12 Jun 2024 20:37:53 -0500 Subject: [PATCH 18/64] vcs import from underlay.repos file --- .docker/Dockerfile | 5 +++++ .dockerignore | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index 1061a0784e..dd07d7701a 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -48,6 +48,11 @@ RUN rosdep update \ ################################################################################ FROM baser AS cacher +# clone underlay source +COPY ./tools/underlay.repos ./ +RUN mkdir src && \ + vcs import src < underlay.repos + # copy overlay source COPY ./ ./src/nav2 diff --git a/.dockerignore b/.dockerignore index 81b138b3df..5f8a31589d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,9 +2,10 @@ * # First-order allow exception for select directories +!/.docker !/cache !/nav* -!/.docker +!/tools # Second-order deny exception for Dockerfile /.docker/Dockerfile From ba682a18c761f27faf1c02c6b8740aa63a28cecd Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 12:33:32 -0500 Subject: [PATCH 19/64] Simplify given cache should only be saved and doesn't need to be restored for this step --- .github/actions/cache-source-checkout/action.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/cache-source-checkout/action.yml b/.github/actions/cache-source-checkout/action.yml index 7db410e89a..02f62d6ce2 100644 --- a/.github/actions/cache-source-checkout/action.yml +++ b/.github/actions/cache-source-checkout/action.yml @@ -49,9 +49,9 @@ runs: shopt -s dotglob mv ${{ github.workspace }}/* $integration_repo_path - - name: Cache checkout - id: cache_checkout - uses: actions/cache@v4 + - name: Save checkout + id: save_checkout + uses: actions/cache/save@v4 with: path: ${{ steps.cache_dance_info.outputs.overlay_ws_src }}/ key: ${{ steps.cache_key_info.outputs.checkout_cache_key }} From a6497ad52fcf6b9271b021dec6f95445847b31c9 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 12:34:37 -0500 Subject: [PATCH 20/64] Use separate cache step to save via if always given that `save-always` never officially worked and will be removed from next release - https://github.com/actions/cache/issues/1315#issuecomment-2163822166 --- .github/workflows/build_test_colcon.yaml | 68 +++++++++++++++++------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build_test_colcon.yaml b/.github/workflows/build_test_colcon.yaml index 64cec3561c..97dbebe1c2 100644 --- a/.github/workflows/build_test_colcon.yaml +++ b/.github/workflows/build_test_colcon.yaml @@ -44,23 +44,27 @@ jobs: steps: - name: Restore checkout id: restore_checkout - uses: actions/cache@v4 + uses: actions/cache/restore@v4 with: fail-on-cache-miss: true path: ${{ inputs.overlay_ws }}/src/ key: ${{ inputs.checkout_cache_key }} - - name: Cache ccache - id: cache_ccache - uses: actions/cache@v4 + - name: Cache ccache info + id: cache_ccache_info + run: | + ccache_cache_key="ccache-v1"\ + "-${{ github.ref }}"\ + "-${{ github.run_id }}"\ + "-${{ github.run_number }}"\ + "-${{ github.run_attempt }}" + echo "ccache_cache_key=${ccache_cache_key}" >> $GITHUB_OUTPUT + - name: Restore ccache + id: restore_ccache + uses: actions/cache/restore@v4 with: - save-always: true path: | ${{ inputs.overlay_ws }}/.ccache - key: "ccache-v1\ - -${{ github.ref }}\ - -${{ github.run_id }}\ - -${{ github.run_number }}\ - -${{ github.run_attempt }}" + key: ${{ steps.cache_ccache_info.outputs.ccache_cache_key }} restore-keys: | ccache-v1-${{ github.ref }} ccache-v1-refs/heads/${{ github.head_ref }} @@ -75,11 +79,10 @@ jobs: "-${{ github.run_number }}"\ "-${{ github.run_attempt }}" echo "overlay_cache_key=${overlay_cache_key}" >> $GITHUB_OUTPUT - - name: Cache overlay - id: cache_overlay - uses: actions/cache@v4 + - name: Restore overlay + id: restore_overlay + uses: actions/cache/restore@v4 with: - save-always: true path: | ${{ inputs.overlay_ws }}/build ${{ inputs.overlay_ws }}/install @@ -138,6 +141,24 @@ jobs: with: name: build-logs path: ${{ inputs.overlay_ws }}/log/ + - name: Save ccache + id: save_ccache + uses: actions/cache/save@v4 + if: always() + with: + path: | + ${{ inputs.overlay_ws }}/.ccache + key: ${{ steps.cache_ccache_info.outputs.ccache_cache_key }} + - name: Save overlay + id: save_overlay + uses: actions/cache/save@v4 + if: always() + with: + path: | + ${{ inputs.overlay_ws }}/build + ${{ inputs.overlay_ws }}/install + ${{ inputs.overlay_ws }}/test_results + key: ${{ steps.cache_overlay_info.outputs.overlay_cache_key }} test_colcon_workspace: name: Test Workspace @@ -155,16 +176,15 @@ jobs: steps: - name: Restore checkout id: restore_checkout - uses: actions/cache@v4 + uses: actions/cache/restore@v4 with: fail-on-cache-miss: true path: ${{ inputs.overlay_ws }}/src/ key: ${{ inputs.checkout_cache_key }} - - name: Cache overlay - id: cache_overlay - uses: actions/cache@v4 + - name: Restore overlay + id: restore_overlay + uses: actions/cache/restore@v4 with: - save-always: true path: | ${{ inputs.overlay_ws }}/build ${{ inputs.overlay_ws }}/install @@ -206,3 +226,13 @@ jobs: with: name: test-results path: ${{ inputs.overlay_ws }}/test_results/ + - name: Save overlay + id: save_overlay + uses: actions/cache/save@v4 + if: always() + with: + path: | + ${{ inputs.overlay_ws }}/build + ${{ inputs.overlay_ws }}/install + ${{ inputs.overlay_ws }}/test_results + key: ${{ needs.build_colcon_workspace.outputs.overlay_cache_key }}-${{ github.run_attempt }} From c1a9aab2f1ec64dee84805e791ea02e0bcf9cc25 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 12:38:26 -0500 Subject: [PATCH 21/64] Update docker bake action from v4 to v5 to tryout build summary feature --- .github/actions/bake-base-stages/action.yml | 2 +- .github/actions/bake-prod-stages/action.yml | 2 +- .github/actions/get-layer-metadata/README.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/bake-base-stages/action.yml b/.github/actions/bake-base-stages/action.yml index ed012c85dd..9f0765d5bf 100644 --- a/.github/actions/bake-base-stages/action.yml +++ b/.github/actions/bake-base-stages/action.yml @@ -95,7 +95,7 @@ runs: } >> "$GITHUB_ENV" - name: Bake base stages id: bake_base_stages - uses: docker/bake-action@v4 + uses: docker/bake-action@v5 with: pull: true push: true diff --git a/.github/actions/bake-prod-stages/action.yml b/.github/actions/bake-prod-stages/action.yml index 5f57e3eb79..1b564ea959 100644 --- a/.github/actions/bake-prod-stages/action.yml +++ b/.github/actions/bake-prod-stages/action.yml @@ -96,7 +96,7 @@ runs: } >> "$GITHUB_ENV" - name: Bake prod stages id: bake_prod_stages - uses: docker/bake-action@v4 + uses: docker/bake-action@v5 with: pull: true push: true diff --git a/.github/actions/get-layer-metadata/README.md b/.github/actions/get-layer-metadata/README.md index 50369591e4..c6cfdd6f4e 100644 --- a/.github/actions/get-layer-metadata/README.md +++ b/.github/actions/get-layer-metadata/README.md @@ -14,7 +14,7 @@ jobs: - name: Build and load id: docker_bake_load - uses: docker/bake-action@v4 + uses: docker/bake-action@v5 with: push: false load: true @@ -27,7 +27,7 @@ jobs: - name: Build and push id: docker_bake_push - uses: docker/bake-action@v4 + uses: docker/bake-action@v5 with: push: true load: false From 76110c01b4493750ee42ee676002ca2ded243dbd Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 12:44:19 -0500 Subject: [PATCH 22/64] Fix FromAsCasing warnings - https://docs.docker.com/reference/build-checks/from-as-casing/ --- .docker/Dockerfile | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index dd07d7701a..176a53df39 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -7,12 +7,12 @@ ARG WS_CACHE_ID=nav2 ARG FROM_IMAGE=base # Stage from full image tag name for dependabot detection -FROM ros:rolling as base +FROM ros:rolling AS base ################################################################################ # MARK: baser - setup base image using snapshots ################################################################################ -FROM $FROM_IMAGE as baser +FROM $FROM_IMAGE AS baser ENV FROM_IMAGE=${FROM_IMAGE} # Configure ubuntu snapshot @@ -84,7 +84,7 @@ RUN dep_types=(\ ################################################################################ # MARK: runner - setup runtime dependencies for deployment ################################################################################ -FROM baser as runner +FROM baser AS runner # install packages for field work COPY .docker/runner_apt_debs.txt /tmp/runner_apt_debs.txt @@ -99,7 +99,7 @@ RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ ################################################################################ # MARK: prepper - bootstrap general dependencies for development ################################################################################ -FROM $PREP_FROM_STAGE as prepper +FROM $PREP_FROM_STAGE AS prepper # install bootstrap tools RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ @@ -123,7 +123,7 @@ RUN colcon mixin add default \ ################################################################################ # MARK: validator - setup test dependencies for validation ################################################################################ -FROM prepper as validator +FROM prepper AS validator COPY --from=cacher /tmp/rosdep_test_debs.txt /tmp/rosdep_test_debs.txt RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ @@ -132,7 +132,7 @@ RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ ################################################################################ # MARK: tooler - setup build dependencies for compilation ################################################################################ -FROM validator as tooler +FROM validator AS tooler COPY --from=cacher /tmp/rosdep_build_debs.txt /tmp/ RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ @@ -160,7 +160,7 @@ RUN env > /tmp/env.txt ################################################################################ # MARK: seeder - seed workspace artifacts for caching ################################################################################ -FROM baser as seeder +FROM baser AS seeder ARG WS_CACHE_ID ARG CLEAR_WS_CACHE @@ -189,7 +189,7 @@ RUN --mount=type=cache,from=cacher,target=/cacher \ ################################################################################ # MARK: builder - build workspace artifacts for deployment ################################################################################ -FROM tooler as builder +FROM tooler AS builder ARG WS_CACHE_ID # build overlay source @@ -223,7 +223,7 @@ RUN --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS \ ################################################################################ # MARK: dever - setup user account for development ################################################################################ -FROM $DEV_FROM_STAGE as dever +FROM $DEV_FROM_STAGE AS dever # add default user for devcontainer ENV DEV_USER=ubuntu @@ -232,7 +232,7 @@ RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers ################################################################################ # MARK: tester - test workspace artifacts for development ################################################################################ -FROM validator as tester +FROM validator AS tester ARG WS_CACHE_ID # test overlay build @@ -254,7 +254,7 @@ RUN --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS \ ################################################################################ # MARK: dancer - multi-stage for caches dancing ################################################################################ -FROM $EXPORT_FROM_STAGE as dancer +FROM $EXPORT_FROM_STAGE AS dancer ARG WS_CACHE_ID RUN --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS,readonly \ @@ -266,25 +266,25 @@ RUN --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS,readon ################################################################################ # MARK: exporter - multi-stage for exporting caches ################################################################################ -FROM $EXPORT_FROM_STAGE as exporter +FROM $EXPORT_FROM_STAGE AS exporter COPY --link --from=dancer /dancer/$OVERLAY_WS $OVERLAY_WS ################################################################################ # MARK: shipper - setup production images using shared instructions ################################################################################ -FROM $SHIP_FROM_STAGE as shipper +FROM $SHIP_FROM_STAGE AS shipper ################################################################################ # MARK: debugger - stage target for debuggin in production ################################################################################ -FROM shipper as debugger +FROM shipper AS debugger COPY --link --from=dancer /dancer/$OVERLAY_WS $OVERLAY_WS ################################################################################ # MARK: releaser - stage target for releasing in production ################################################################################ -FROM shipper as releaser +FROM shipper AS releaser COPY --link --from=dancer /dancer/$OVERLAY_WS/install $OVERLAY_WS/install \ No newline at end of file From a2652cdafc4919dece9e65b251dd884bafa8050e Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 13:14:12 -0500 Subject: [PATCH 23/64] Set ccache key via septate step --- .github/workflows/build_test_colcon.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build_test_colcon.yaml b/.github/workflows/build_test_colcon.yaml index 97dbebe1c2..90853fb1d8 100644 --- a/.github/workflows/build_test_colcon.yaml +++ b/.github/workflows/build_test_colcon.yaml @@ -25,6 +25,8 @@ on: required: true type: string outputs: + ccache_cache_key: + value: ${{ jobs.build_colcon_workspace.outputs.ccache_cache_key }} overlay_cache_key: value: ${{ jobs.test_colcon_workspace.outputs.overlay_cache_key }} @@ -32,6 +34,7 @@ jobs: build_colcon_workspace: name: Build Workspace outputs: + ccache_cache_key: ${{ steps.cache_ccache_info.outputs.ccache_cache_key }} overlay_cache_key: ${{ steps.cache_overlay_info.outputs.overlay_cache_key }} build_packages: ${{ steps.check_differential.outputs.build_packages }} runs-on: ${{ inputs.runs_on }} From cee6ac0ef3b369134c56dd0010fcf776c41999af Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 13:14:25 -0500 Subject: [PATCH 24/64] Pass ccache_cache_key between jobs --- .github/workflows/build_test_integration.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_test_integration.yaml b/.github/workflows/build_test_integration.yaml index 029fbd1c27..4ba2333cab 100644 --- a/.github/workflows/build_test_integration.yaml +++ b/.github/workflows/build_test_integration.yaml @@ -89,6 +89,7 @@ jobs: - colcon_build_test with: cache_image: ${{ needs.build_base_images.outputs.tooler_image }} + ccache_cache_key: ${{ needs.colcon_build_test.outputs.ccache_cache_key }} checkout_cache_key: ${{ needs.build_base_images.outputs.checkout_cache_key }} metadata: ${{ needs.build_base_images.outputs.metadata }} overlay_cache_key: ${{ needs.colcon_build_test.outputs.overlay_cache_key }} From 3df9fb0bb4e5a93cd5a34594194608b3ffb6c055 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 13:14:47 -0500 Subject: [PATCH 25/64] Restore ccache for build prod image jobs to bake ccache store into debugger stage --- .github/workflows/build_prod_images.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/build_prod_images.yaml b/.github/workflows/build_prod_images.yaml index dc0ba54d1b..d8c215f554 100644 --- a/.github/workflows/build_prod_images.yaml +++ b/.github/workflows/build_prod_images.yaml @@ -3,6 +3,9 @@ name: Build Prod Images on: workflow_call: inputs: + ccache_cache_key: + required: true + type: string checkout_cache_key: required: true type: string @@ -52,6 +55,14 @@ jobs: fail-on-cache-miss: true path: ${{ inputs.overlay_ws }}/src/ key: ${{ inputs.checkout_cache_key }} + - name: Restore ccache + id: restore_ccache + uses: actions/cache/restore@v4 + with: + fail-on-cache-miss: true + path: | + ${{ inputs.overlay_ws }}/.ccache + key: ${{ inputs.ccache_cache_key }} - name: Restore overlay id: restore_overlay uses: actions/cache/restore@v4 From 248b33c2b4100f2aa1a2a499ba7b14ae31dd165c Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 13:17:15 -0500 Subject: [PATCH 26/64] Update path to Dockerfile --- .github/workflows/build_test.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_test.yaml b/.github/workflows/build_test.yaml index 6e7bf1cb45..25fd714a63 100644 --- a/.github/workflows/build_test.yaml +++ b/.github/workflows/build_test.yaml @@ -5,21 +5,21 @@ on: # branches: # - main # paths: + # - '.docker/Dockerfile' # - '.github/workflows/build_prod_images.yaml' # - '.github/workflows/build_test_colcon.yaml' # - '.github/workflows/build_test_integration.yaml' # - '.github/workflows/build_test.yaml' # - 'docker-bake.hcl' - # - 'Dockerfile' # - 'nav*/**' # pull_request: # paths: + # - '.docker/Dockerfile' # - '.github/workflows/build_prod_images.yaml' # - '.github/workflows/build_test_colcon.yaml' # - '.github/workflows/build_test_integration.yaml' # - '.github/workflows/build_test.yaml' # - 'docker-bake.hcl' - # - 'Dockerfile' # - 'nav*/**' workflow_dispatch: From 5736762292ee04855b2488955279ea9e8661a02e Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 13:18:46 -0500 Subject: [PATCH 27/64] Uncomment main caller workflow --- .github/workflows/build_test.yaml | 40 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build_test.yaml b/.github/workflows/build_test.yaml index 25fd714a63..b80cb9b52a 100644 --- a/.github/workflows/build_test.yaml +++ b/.github/workflows/build_test.yaml @@ -1,26 +1,26 @@ name: Call on: - # push: - # branches: - # - main - # paths: - # - '.docker/Dockerfile' - # - '.github/workflows/build_prod_images.yaml' - # - '.github/workflows/build_test_colcon.yaml' - # - '.github/workflows/build_test_integration.yaml' - # - '.github/workflows/build_test.yaml' - # - 'docker-bake.hcl' - # - 'nav*/**' - # pull_request: - # paths: - # - '.docker/Dockerfile' - # - '.github/workflows/build_prod_images.yaml' - # - '.github/workflows/build_test_colcon.yaml' - # - '.github/workflows/build_test_integration.yaml' - # - '.github/workflows/build_test.yaml' - # - 'docker-bake.hcl' - # - 'nav*/**' + push: + branches: + - main + paths: + - '.docker/Dockerfile' + - '.github/workflows/build_prod_images.yaml' + - '.github/workflows/build_test_colcon.yaml' + - '.github/workflows/build_test_integration.yaml' + - '.github/workflows/build_test.yaml' + - 'docker-bake.hcl' + - 'nav*/**' + pull_request: + paths: + - '.docker/Dockerfile' + - '.github/workflows/build_prod_images.yaml' + - '.github/workflows/build_test_colcon.yaml' + - '.github/workflows/build_test_integration.yaml' + - '.github/workflows/build_test.yaml' + - 'docker-bake.hcl' + - 'nav*/**' workflow_dispatch: jobs: From df9842a79b1f03aead3f8dfd426fd7dbafae2101 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 13:19:48 -0500 Subject: [PATCH 28/64] Trigger on any change to the .docker path --- .github/workflows/build_test.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_test.yaml b/.github/workflows/build_test.yaml index b80cb9b52a..30b00e51e8 100644 --- a/.github/workflows/build_test.yaml +++ b/.github/workflows/build_test.yaml @@ -5,7 +5,7 @@ on: branches: - main paths: - - '.docker/Dockerfile' + - '.docker/**' - '.github/workflows/build_prod_images.yaml' - '.github/workflows/build_test_colcon.yaml' - '.github/workflows/build_test_integration.yaml' @@ -14,7 +14,7 @@ on: - 'nav*/**' pull_request: paths: - - '.docker/Dockerfile' + - '.docker/**' - '.github/workflows/build_prod_images.yaml' - '.github/workflows/build_test_colcon.yaml' - '.github/workflows/build_test_integration.yaml' From eb26b415d1d35ba2ae54f20e3006d1bf663ecda5 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 13:21:10 -0500 Subject: [PATCH 29/64] Change workflow action to current branch to test CI --- .github/actions/bake-base-stages/action.yml | 2 +- .github/actions/get-layer-metadata/README.md | 4 ++-- .github/workflows/build_prod_images.yaml | 2 +- .github/workflows/build_test.yaml | 2 +- .github/workflows/build_test_integration.yaml | 8 ++++---- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/actions/bake-base-stages/action.yml b/.github/actions/bake-base-stages/action.yml index 9f0765d5bf..8135e12ecc 100644 --- a/.github/actions/bake-base-stages/action.yml +++ b/.github/actions/bake-base-stages/action.yml @@ -116,7 +116,7 @@ runs: - name: Get Layer Metadata id: get_layer_metadata - uses: ros-navigation/navigation2/.github/actions/get-layer-metadata@main + uses: ros-navigation/navigation2/.github/actions/get-layer-metadata@buildkit with: metadata: ${{ steps.bake_base_stages.outputs.metadata }} load: false diff --git a/.github/actions/get-layer-metadata/README.md b/.github/actions/get-layer-metadata/README.md index c6cfdd6f4e..06fcfed24e 100644 --- a/.github/actions/get-layer-metadata/README.md +++ b/.github/actions/get-layer-metadata/README.md @@ -20,7 +20,7 @@ jobs: load: true - name: Get Layer Metadata Locally id: get_layer_metadata_local - uses: ros-navigation/navigation2/.github/actions/get-layer-metadata@main + uses: ros-navigation/navigation2/.github/actions/get-layer-metadata@buildkit with: metadata: ${{ steps.docker_bake_load.outputs.metadata }} load: true @@ -33,7 +33,7 @@ jobs: load: false - name: Get Layer Metadata Remotely id: get_layer_metadata_remote - uses: ros-navigation/navigation2/.github/actions/get-layer-metadata@main + uses: ros-navigation/navigation2/.github/actions/get-layer-metadata@buildkit with: metadata: ${{ steps.docker_bake_push.outputs.metadata }} load: false diff --git a/.github/workflows/build_prod_images.yaml b/.github/workflows/build_prod_images.yaml index d8c215f554..5d264539b7 100644 --- a/.github/workflows/build_prod_images.yaml +++ b/.github/workflows/build_prod_images.yaml @@ -99,7 +99,7 @@ jobs: - name: Bake prod stages id: bake_prod_stages - uses: ros-navigation/navigation2/.github/actions/bake-prod-stages@main + uses: ros-navigation/navigation2/.github/actions/bake-prod-stages@buildkit with: cache_image: ${{ inputs.cache_image }} integration_repo: ${{ github.repository }} diff --git a/.github/workflows/build_test.yaml b/.github/workflows/build_test.yaml index 30b00e51e8..1543f9fa90 100644 --- a/.github/workflows/build_test.yaml +++ b/.github/workflows/build_test.yaml @@ -26,5 +26,5 @@ on: jobs: integration: name: Integration - uses: ros-navigation/navigation2/.github/workflows/build_test_integration.yaml@main + uses: ros-navigation/navigation2/.github/workflows/build_test_integration.yaml@buildkit secrets: inherit diff --git a/.github/workflows/build_test_integration.yaml b/.github/workflows/build_test_integration.yaml index 4ba2333cab..73516e114c 100644 --- a/.github/workflows/build_test_integration.yaml +++ b/.github/workflows/build_test_integration.yaml @@ -54,21 +54,21 @@ jobs: - name: Bake base stages id: bake_base_stages - uses: ros-navigation/navigation2/.github/actions/bake-base-stages@main + uses: ros-navigation/navigation2/.github/actions/bake-base-stages@buildkit with: integration_repo: ${{ inputs.integration_repo }} token: ${{ secrets.GITHUB_TOKEN }} - name: Cache source checkout id: cache_source_checkout - uses: ros-navigation/navigation2/.github/actions/cache-source-checkout@main + uses: ros-navigation/navigation2/.github/actions/cache-source-checkout@buildkit with: integration_repo: ${{ inputs.integration_repo }} overlay_ws: ${{ env.OVERLAY_WS }} colcon_build_test: name: Colcon - uses: ros-navigation/navigation2/.github/workflows/build_test_colcon.yaml@main + uses: ros-navigation/navigation2/.github/workflows/build_test_colcon.yaml@buildkit secrets: inherit needs: build_base_images with: @@ -82,7 +82,7 @@ jobs: build_prod_images: name: Prod - uses: ros-navigation/navigation2/.github/workflows/build_prod_images.yaml@main + uses: ros-navigation/navigation2/.github/workflows/build_prod_images.yaml@buildkit secrets: inherit needs: - build_base_images From 894126cf05748134cf3b1a60b19a76579bf8d513 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 13:25:22 -0500 Subject: [PATCH 30/64] Fix typo to use GITHUB_TOKEN --- .github/workflows/build_test_integration.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_test_integration.yaml b/.github/workflows/build_test_integration.yaml index 73516e114c..aaeb8af797 100644 --- a/.github/workflows/build_test_integration.yaml +++ b/.github/workflows/build_test_integration.yaml @@ -49,7 +49,7 @@ jobs: with: ref: ${{ inputs.integration_ref }} repository: ${{ inputs.integration_repo }} - token: ${{ secrets.GIT_CHECKOUT_PAT }} + token: ${{ secrets.GITHUB_TOKEN }} submodules: 'recursive' - name: Bake base stages From aef79ad9ab5de766edc9c2729aae33d38b391eae Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 13:37:36 -0500 Subject: [PATCH 31/64] Omit OCI configuration used for AWS ECR given this may conflict with GHCR using classic docker format? --- .github/actions/bake-base-stages/action.yml | 2 +- .github/actions/bake-prod-stages/action.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/bake-base-stages/action.yml b/.github/actions/bake-base-stages/action.yml index 8135e12ecc..d29e395eb2 100644 --- a/.github/actions/bake-base-stages/action.yml +++ b/.github/actions/bake-base-stages/action.yml @@ -86,7 +86,7 @@ runs: if [ "$INTEGRATION_REPO" == "$GHCR_REPO" ]; then tooler_ref=${{ fromJSON(steps.docker_meta_tooler.outputs.json).tags[0] }} echo *.cache-from=type=registry,ref=${tooler_ref}.cache - echo tooler.cache-to=type=registry,ref=${tooler_ref}.cache,mode=max,image-manifest=true,oci-mediatypes=true + echo tooler.cache-to=type=registry,ref=${tooler_ref}.cache,mode=max fi if [ "${{ github.head_ref || github.ref_name }}" != "main" ] || [ "$INTEGRATION_REPO" != "$GHCR_REPO" ]; then echo *.cache-from=type=s3,blobs_prefix=cache/${{ env.INTEGRATION_REPO }}/,manifests_prefix=cache/${{ env.INTEGRATION_REPO }}/,region=${{ env.RUNS_ON_AWS_REGION }},bucket=${{ env.RUNS_ON_S3_BUCKET_CACHE }} diff --git a/.github/actions/bake-prod-stages/action.yml b/.github/actions/bake-prod-stages/action.yml index 1b564ea959..a2f8a52525 100644 --- a/.github/actions/bake-prod-stages/action.yml +++ b/.github/actions/bake-prod-stages/action.yml @@ -85,9 +85,9 @@ runs: debugger_ref=${{ fromJSON(steps.docker_meta_debugger.outputs.json).tags[0] }} releaser_ref=${{ fromJSON(steps.docker_meta_releaser.outputs.json).tags[0] }} echo debugger.cache-from=type=registry,ref=${debugger_ref}.cache - echo debugger.cache-to=type=registry,ref=${debugger_ref}.cache,mode=min,image-manifest=true,oci-mediatypes=true + echo debugger.cache-to=type=registry,ref=${debugger_ref}.cache,mode=min echo releaser.cache-from=type=registry,ref=${releaser_ref}.cache - echo releaser.cache-to=type=registry,ref=${releaser_ref}.cache,mode=min,image-manifest=true,oci-mediatypes=true + echo releaser.cache-to=type=registry,ref=${releaser_ref}.cache,mode=min fi cache_image="${{ inputs.cache_image }}" cache_image="${cache_image%@*}" From 5d8c00f5627b05205797d556eb32adeed4a5566d Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 13:51:52 -0500 Subject: [PATCH 32/64] Image images using org + repo name given GHCR uses a global namespace for its registry --- .github/actions/bake-base-stages/action.yml | 4 ++-- .github/actions/bake-prod-stages/action.yml | 4 ++-- .github/workflows/ghcr_retention.yaml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/bake-base-stages/action.yml b/.github/actions/bake-base-stages/action.yml index d29e395eb2..408b784f19 100644 --- a/.github/actions/bake-base-stages/action.yml +++ b/.github/actions/bake-base-stages/action.yml @@ -57,8 +57,8 @@ runs: shell: bash run: | echo "GHCR_REGISTRY=ghcr.io" >> $GITHUB_ENV - echo "INTEGRATION_REPO=$(basename ${{ inputs.integration_repo }})" >> $GITHUB_ENV - echo "GHCR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV + echo "INTEGRATION_REPO=${{ inputs.integration_repo }}" >> $GITHUB_ENV + echo "GHCR_REPO=${{ github.repository }}" >> $GITHUB_ENV - name: Docker validator meta id: docker_meta_validator diff --git a/.github/actions/bake-prod-stages/action.yml b/.github/actions/bake-prod-stages/action.yml index a2f8a52525..c922302252 100644 --- a/.github/actions/bake-prod-stages/action.yml +++ b/.github/actions/bake-prod-stages/action.yml @@ -55,8 +55,8 @@ runs: shell: bash run: | echo "GHCR_REGISTRY=ghcr.io" >> $GITHUB_ENV - echo "INTEGRATION_REPO=$(basename ${{ inputs.integration_repo }})" >> $GITHUB_ENV - echo "GHCR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV + echo "INTEGRATION_REPO=${{ inputs.integration_repo }}" >> $GITHUB_ENV + echo "GHCR_REPO=${{ github.repository }}" >> $GITHUB_ENV - name: Docker debugger meta id: docker_meta_debugger diff --git a/.github/workflows/ghcr_retention.yaml b/.github/workflows/ghcr_retention.yaml index 42d07ffbb5..db4c276213 100644 --- a/.github/workflows/ghcr_retention.yaml +++ b/.github/workflows/ghcr_retention.yaml @@ -34,7 +34,7 @@ jobs: shell: bash run: | echo "GHCR_REGISTRY=ghcr.io" >> $GITHUB_ENV - echo "GHCR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV + echo "GHCR_REPO=${{ github.repository }}" >> $GITHUB_ENV - name: Docker meta id: docker_meta uses: docker/metadata-action@v5 From ae8a2744e2ba1d9db5877594ddddca1d40b3e583 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 14:00:19 -0500 Subject: [PATCH 33/64] Use gha for buildkit cache backend instead of S3 - https://docs.docker.com/build/cache/backends/gha/ --- .github/actions/bake-base-stages/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/bake-base-stages/action.yml b/.github/actions/bake-base-stages/action.yml index 408b784f19..76e0573a09 100644 --- a/.github/actions/bake-base-stages/action.yml +++ b/.github/actions/bake-base-stages/action.yml @@ -89,7 +89,7 @@ runs: echo tooler.cache-to=type=registry,ref=${tooler_ref}.cache,mode=max fi if [ "${{ github.head_ref || github.ref_name }}" != "main" ] || [ "$INTEGRATION_REPO" != "$GHCR_REPO" ]; then - echo *.cache-from=type=s3,blobs_prefix=cache/${{ env.INTEGRATION_REPO }}/,manifests_prefix=cache/${{ env.INTEGRATION_REPO }}/,region=${{ env.RUNS_ON_AWS_REGION }},bucket=${{ env.RUNS_ON_S3_BUCKET_CACHE }} + echo *.cache-from=type=gha fi echo EOF } >> "$GITHUB_ENV" @@ -107,7 +107,7 @@ runs: validator set: | *.cache-from=type=registry,ref=${{ env.GHCR_REGISTRY }}/${{ env.INTEGRATION_REPO }}:main-tooler.cache - *.cache-to=type=s3,blobs_prefix=cache/${{ env.INTEGRATION_REPO }}/,manifests_prefix=cache/${{ env.INTEGRATION_REPO }}/,region=${{ env.RUNS_ON_AWS_REGION }},bucket=${{ env.RUNS_ON_S3_BUCKET_CACHE }},mode=max + *.cache-to=type=gha,mode=max ${{ env.EXTRA_BAKE_SET }} files: | ./docker-bake.hcl From de79d04005846a19e4f579edd8bf37c9b516060b Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 16:12:14 -0500 Subject: [PATCH 34/64] Bake underlay source into base image --- .docker/Dockerfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index 176a53df39..ef5604df27 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -50,8 +50,8 @@ FROM baser AS cacher # clone underlay source COPY ./tools/underlay.repos ./ -RUN mkdir src && \ - vcs import src < underlay.repos +RUN mkdir -p src/underlay && \ + vcs import src/underlay < underlay.repos # copy overlay source COPY ./ ./src/nav2 @@ -154,6 +154,9 @@ COPY .docker/.colcon/defaults.yaml $COLCON_HOME/ ARG OVERLAY_MIXINS="release ccache lld" ENV OVERLAY_MIXINS=${OVERLAY_MIXINS} +# copy underlay source +COPY --from=cacher $OVERLAY_WS/src/underlay $OVERLAY_WS/src/underlay + # capture environment to modify layer digest RUN env > /tmp/env.txt From 45f00f24202f7c290108a9b45453e2765d371500 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 16:12:25 -0500 Subject: [PATCH 35/64] Revert "Bake underlay source into base image" This reverts commit de79d04005846a19e4f579edd8bf37c9b516060b. --- .docker/Dockerfile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index ef5604df27..176a53df39 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -50,8 +50,8 @@ FROM baser AS cacher # clone underlay source COPY ./tools/underlay.repos ./ -RUN mkdir -p src/underlay && \ - vcs import src/underlay < underlay.repos +RUN mkdir src && \ + vcs import src < underlay.repos # copy overlay source COPY ./ ./src/nav2 @@ -154,9 +154,6 @@ COPY .docker/.colcon/defaults.yaml $COLCON_HOME/ ARG OVERLAY_MIXINS="release ccache lld" ENV OVERLAY_MIXINS=${OVERLAY_MIXINS} -# copy underlay source -COPY --from=cacher $OVERLAY_WS/src/underlay $OVERLAY_WS/src/underlay - # capture environment to modify layer digest RUN env > /tmp/env.txt From 140d1b3b396c9b9cdfcd17793e4c150cc9d925d7 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 16:30:50 -0500 Subject: [PATCH 36/64] Add nav2_minimal_turtlebot_simulation as submodules instead of using repos file to track upstream --- .gitmodules | 3 +++ tools/underlay/nav2_minimal_turtlebot_simulation | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 tools/underlay/nav2_minimal_turtlebot_simulation diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..9ccb2025a0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "nav2_minimal_turtlebot_simulation"] + path = tools/underlay/nav2_minimal_turtlebot_simulation + url = https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git diff --git a/tools/underlay/nav2_minimal_turtlebot_simulation b/tools/underlay/nav2_minimal_turtlebot_simulation new file mode 160000 index 0000000000..6b64127f0e --- /dev/null +++ b/tools/underlay/nav2_minimal_turtlebot_simulation @@ -0,0 +1 @@ +Subproject commit 6b64127f0e0d677ecdaa458bce57b89119cb08ee From 27e8ceb86d3e3dd7612324efab7f12700be10bb2 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sat, 6 Jul 2024 16:32:47 -0500 Subject: [PATCH 37/64] Remove clone step using vcstool --- .docker/Dockerfile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index 176a53df39..9f76b97e23 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -48,11 +48,6 @@ RUN rosdep update \ ################################################################################ FROM baser AS cacher -# clone underlay source -COPY ./tools/underlay.repos ./ -RUN mkdir src && \ - vcs import src < underlay.repos - # copy overlay source COPY ./ ./src/nav2 From 54f57aa20279754b3883de6a4303bfc4588213a4 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sun, 7 Jul 2024 00:18:22 -0500 Subject: [PATCH 38/64] Fix OVERLAY_WS ENV to match Dockerfile --- .github/workflows/build_test_integration.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_test_integration.yaml b/.github/workflows/build_test_integration.yaml index aaeb8af797..7bb8d8193a 100644 --- a/.github/workflows/build_test_integration.yaml +++ b/.github/workflows/build_test_integration.yaml @@ -29,7 +29,7 @@ on: type: string env: - OVERLAY_WS: /opt/auto_ws + OVERLAY_WS: /opt/nav2_ws jobs: build_base_images: From c09f7461cca52de94c36775f1ba9574daa156151 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Sun, 7 Jul 2024 10:53:39 -0500 Subject: [PATCH 39/64] Try building prod image regardless of test results given they are currently flaky --- .github/workflows/build_test_colcon.yaml | 4 ++++ .github/workflows/build_test_integration.yaml | 1 + 2 files changed, 5 insertions(+) diff --git a/.github/workflows/build_test_colcon.yaml b/.github/workflows/build_test_colcon.yaml index 90853fb1d8..600f1ef370 100644 --- a/.github/workflows/build_test_colcon.yaml +++ b/.github/workflows/build_test_colcon.yaml @@ -25,10 +25,14 @@ on: required: true type: string outputs: + build_result: + value: ${{ jobs.build_colcon_workspace.result }} ccache_cache_key: value: ${{ jobs.build_colcon_workspace.outputs.ccache_cache_key }} overlay_cache_key: value: ${{ jobs.test_colcon_workspace.outputs.overlay_cache_key }} + test_result: + value: ${{ jobs.test_colcon_workspace.result }} jobs: build_colcon_workspace: diff --git a/.github/workflows/build_test_integration.yaml b/.github/workflows/build_test_integration.yaml index 7bb8d8193a..168edfc14c 100644 --- a/.github/workflows/build_test_integration.yaml +++ b/.github/workflows/build_test_integration.yaml @@ -83,6 +83,7 @@ jobs: build_prod_images: name: Prod uses: ros-navigation/navigation2/.github/workflows/build_prod_images.yaml@buildkit + if: needs.colcon_build_test.outputs.build_result == 'success' secrets: inherit needs: - build_base_images From 5121a3058126061b10c959592b96f2fc68d61cd9 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 20:55:37 +0000 Subject: [PATCH 40/64] Enable docker-outside-docker --- .devcontainer/devcontainer.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 0b4038398b..eae6142dd1 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -60,11 +60,17 @@ "source": "nav2-home", "target": "/home/ubuntu", "type": "volume" + }, + { + // Mount docker socket + "source": "/var/run/docker.sock", + "target": "/var/run/docker-host.sock", + "type": "bind" } ], "features": { // "ghcr.io/devcontainers/features/desktop-lite:1": {}, - // "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}, + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}, // "ghcr.io/devcontainers/features/github-cli:1": {} }, "customizations": { @@ -81,7 +87,7 @@ "esbenp.prettier-vscode", "GitHub.copilot", "hashicorp.hcl", - // "ms-azuretools.vscode-docker", + "ms-azuretools.vscode-docker", "ms-iot.vscode-ros", "streetsidesoftware.code-spell-checker", "twxs.cmake" From 2c8bcc33e3b96ddd3188da5cd82e591582554bbf Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 20:57:34 +0000 Subject: [PATCH 41/64] Reorder mounts --- .devcontainer/devcontainer.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index eae6142dd1..753e689e45 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -29,14 +29,6 @@ }, "remoteUser": "ubuntu", "mounts": [ - { - // Explicitly mount X11 socket for NVIDIA Container Toolkit - // as setting NVIDIA_DRIVER_CAPABILITIES to include `graphics` - // interferes with VSCode's default X11 forwarding behavior - "source": "/tmp/.X11-unix", - "target": "/tmp/.X11-unix", - "type": "bind" - }, { // Cache apt downloads "source": "apt-cache", @@ -66,6 +58,14 @@ "source": "/var/run/docker.sock", "target": "/var/run/docker-host.sock", "type": "bind" + }, + { + // Explicitly mount X11 socket for NVIDIA Container Toolkit + // as setting NVIDIA_DRIVER_CAPABILITIES to include `graphics` + // interferes with VSCode's default X11 forwarding behavior + "source": "/tmp/.X11-unix", + "target": "/tmp/.X11-unix", + "type": "bind" } ], "features": { From 65c0194829cb4d8c9b684e053d721115f4e26bf3 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 20:58:06 +0000 Subject: [PATCH 42/64] Enable gh CLI --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 753e689e45..dce3053ba6 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -71,7 +71,7 @@ "features": { // "ghcr.io/devcontainers/features/desktop-lite:1": {}, "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}, - // "ghcr.io/devcontainers/features/github-cli:1": {} + "ghcr.io/devcontainers/features/github-cli:1": {}, }, "customizations": { "codespaces": { From f22b3cb7f12b2f43a62cda64c4ba97b36f58af9a Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 21:00:25 +0000 Subject: [PATCH 43/64] Add svg extension to view Dockerfile graphs --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index dce3053ba6..b96b058606 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -90,7 +90,7 @@ "ms-azuretools.vscode-docker", "ms-iot.vscode-ros", "streetsidesoftware.code-spell-checker", - "twxs.cmake" + "vitaliymaz.vscode-svg-previewer", ] } } From 50b8f7c3c02f9bb9a7a52c6727d3f1f9c32f8d23 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 21:01:44 +0000 Subject: [PATCH 44/64] Rename nav2 ws volume to be more descriptive --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b96b058606..c5ef7f0bf7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -43,7 +43,7 @@ }, { // Cache colcon workspace - "source": "overlay-${devcontainerId}", + "source": "nav2-ws-${devcontainerId}", "target": "/opt/nav2_ws", "type": "volume" }, From bab8da7ccc3d5a92f2fb8540e9cfae53c9f4e654 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 21:02:51 +0000 Subject: [PATCH 45/64] Postfix home by use friendly for multi user hosts envs --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c5ef7f0bf7..5db1c1618b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -49,7 +49,7 @@ }, { // Mount home dotfiles - "source": "nav2-home", + "source": "nav2-home-${localEnv:USER}", "target": "/home/ubuntu", "type": "volume" }, From 7af09f7f4e6e3c8293993b423e8ae46e170a1e3e Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 21:05:02 +0000 Subject: [PATCH 46/64] Add bind volume to user home to make it simple to share files such as ros bags and artifacts --- .devcontainer/devcontainer.json | 6 ++++++ .devcontainer/initialize-command.sh | 2 ++ 2 files changed, 8 insertions(+) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5db1c1618b..0de9cf2b0f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -53,6 +53,12 @@ "target": "/home/ubuntu", "type": "volume" }, + { + // Mount home nav2 + "source": "${localEnv:HOME}/nav2/", + "target": "/home/ubuntu/nav2", + "type": "bind" + }, { // Mount docker socket "source": "/var/run/docker.sock", diff --git a/.devcontainer/initialize-command.sh b/.devcontainer/initialize-command.sh index 1bb56e66ec..03d7014ad8 100755 --- a/.devcontainer/initialize-command.sh +++ b/.devcontainer/initialize-command.sh @@ -15,3 +15,5 @@ docker buildx bake --load \ --file docker-bake.hcl \ --set $target.tags=nav2:devcontainer \ $target + +mkdir -p $HOME/nav2 From 922b91dff4c9ccc732ca4a09c8066866ca353718 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 21:06:23 +0000 Subject: [PATCH 47/64] Comment out home bind mount by default to avoid being to intrusive to user home dir --- .devcontainer/devcontainer.json | 12 ++++++------ .devcontainer/initialize-command.sh | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 0de9cf2b0f..a04debd60a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -53,12 +53,12 @@ "target": "/home/ubuntu", "type": "volume" }, - { - // Mount home nav2 - "source": "${localEnv:HOME}/nav2/", - "target": "/home/ubuntu/nav2", - "type": "bind" - }, + // { + // // Mount home nav2 + // "source": "${localEnv:HOME}/nav2/", + // "target": "/home/ubuntu/nav2", + // "type": "bind" + // }, { // Mount docker socket "source": "/var/run/docker.sock", diff --git a/.devcontainer/initialize-command.sh b/.devcontainer/initialize-command.sh index 03d7014ad8..14aaba3a3b 100755 --- a/.devcontainer/initialize-command.sh +++ b/.devcontainer/initialize-command.sh @@ -16,4 +16,4 @@ docker buildx bake --load \ --set $target.tags=nav2:devcontainer \ $target -mkdir -p $HOME/nav2 +# mkdir -p $HOME/nav2 From ea6f72dfefe7c13067a21bb09d5b6fc6c6540657 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 21:07:32 +0000 Subject: [PATCH 48/64] Add mark comments for readability and sort purposes for each mount --- .devcontainer/devcontainer.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a04debd60a..d2c575a4eb 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -29,6 +29,9 @@ }, "remoteUser": "ubuntu", "mounts": [ + // ################################################################################ + // # MARK: Cache mounts - for development + // ################################################################################ { // Cache apt downloads "source": "apt-cache", @@ -47,6 +50,9 @@ "target": "/opt/nav2_ws", "type": "volume" }, + // ################################################################################ + // # MARK: Personal mounts - for convenience + // ################################################################################ { // Mount home dotfiles "source": "nav2-home-${localEnv:USER}", @@ -59,6 +65,9 @@ // "target": "/home/ubuntu/nav2", // "type": "bind" // }, + // ################################################################################ + // # MARK: Socket mounts - for tooling + // ################################################################################ { // Mount docker socket "source": "/var/run/docker.sock", From 93d7a92ffaa33471014e7cea338deb7f1f56c781 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 21:15:36 +0000 Subject: [PATCH 49/64] Sort ENVs --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index d2c575a4eb..0403da68d7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -22,10 +22,10 @@ "updateContentCommand": ".devcontainer/update-content-command.sh", "postCreateCommand": ".devcontainer/post-create-command.sh", "remoteEnv": { - "OVERLAY_MIXINS": "release ccache lld", "CCACHE_DIR": "/opt/nav2_ws/.ccache", // Explicitly set DISPLAY for NVIDIA Container Toolkit "DISPLAY": "${localEnv:DISPLAY}", + "OVERLAY_MIXINS": "release ccache lld", }, "remoteUser": "ubuntu", "mounts": [ From 0de7df3c6debcf5d188619c013e710533989738e Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 21:19:42 +0000 Subject: [PATCH 50/64] Explicitly set SSH_AUTH_SOCK for devcontainer CLI as this is normally done automatically via VSCode however this feature is still exclusive to MS remote extension and has not yet been upstream to the FOSS CLI - https://github.com/devcontainers/cli/issues/441#issuecomment-1554277737 --- .devcontainer/devcontainer.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 0403da68d7..adf6d9ce3f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -26,6 +26,8 @@ // Explicitly set DISPLAY for NVIDIA Container Toolkit "DISPLAY": "${localEnv:DISPLAY}", "OVERLAY_MIXINS": "release ccache lld", + // Explicitly set SSH_AUTH_SOCK for devcontainer CLI + "SSH_AUTH_SOCK": "${localEnv:SSH_AUTH_SOCK}", }, "remoteUser": "ubuntu", "mounts": [ @@ -81,6 +83,12 @@ "source": "/tmp/.X11-unix", "target": "/tmp/.X11-unix", "type": "bind" + }, + { + // Explicitly mount SSH socket for devcontainer CLI + "source": "${localEnv:SSH_AUTH_SOCK}", + "target": "${localEnv:SSH_AUTH_SOCK}", + "type": "bind" } ], "features": { From 94faf5b0e7f37d27475d1762f9dad9325ac48d8c Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 21:27:21 +0000 Subject: [PATCH 51/64] Alway return 1 to avoid halting dev container build --- .devcontainer/update-content-command.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.devcontainer/update-content-command.sh b/.devcontainer/update-content-command.sh index f4c0428e14..a5f5dafe9a 100755 --- a/.devcontainer/update-content-command.sh +++ b/.devcontainer/update-content-command.sh @@ -59,4 +59,5 @@ echo BUILD_PACKAGES: $BUILD_PACKAGES colcon build \ --symlink-install \ --mixin $OVERLAY_MIXINS \ - --packages-select ${BUILD_PACKAGES} + --packages-select ${BUILD_PACKAGES} \ + || true From 00fdbc88dd350c8e11014d49959bb48363729538 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 21:27:55 +0000 Subject: [PATCH 52/64] Formatting --- .devcontainer/update-content-command.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.devcontainer/update-content-command.sh b/.devcontainer/update-content-command.sh index a5f5dafe9a..8b5b5c324a 100755 --- a/.devcontainer/update-content-command.sh +++ b/.devcontainer/update-content-command.sh @@ -42,9 +42,9 @@ then colcon list \ --names-only \ --packages-above \ - $BUILD_UNFINISHED \ - $BUILD_FAILED \ - $BUILD_INVALID \ + $BUILD_UNFINISHED \ + $BUILD_FAILED \ + $BUILD_INVALID \ | xargs) fi echo BUILD_PACKAGES: $BUILD_PACKAGES From 39ca8653b819ffa11c4fc45c9c61ddb32fa7589e Mon Sep 17 00:00:00 2001 From: ruffsl Date: Tue, 9 Jul 2024 21:54:44 +0000 Subject: [PATCH 53/64] Install GUI tools into dever stage --- .docker/Dockerfile | 10 ++++++++-- .docker/dever_apt_debs.txt | 4 ++++ .docker/{tooler_apt_deps.txt => tooler_apt_debs.txt} | 3 --- 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 .docker/dever_apt_debs.txt rename .docker/{tooler_apt_deps.txt => tooler_apt_debs.txt} (70%) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index 9f76b97e23..8a18d81b9f 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -134,9 +134,9 @@ RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ < /tmp/rosdep_build_debs.txt xargs apt-get install -y --no-install-recommends # install packages for build work -COPY .docker/tooler_apt_deps.txt /tmp/tooler_apt_deps.txt +COPY .docker/tooler_apt_debs.txt /tmp/tooler_apt_debs.txt RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ - cut -d# -f1 < /tmp/tooler_apt_deps.txt | envsubst \ + cut -d# -f1 < /tmp/tooler_apt_debs.txt | envsubst \ | xargs apt-get install -y --no-install-recommends # setup default ccache configuration @@ -220,6 +220,12 @@ RUN --mount=type=cache,id=$WS_CACHE_ID,sharing=private,target=$OVERLAY_WS \ ################################################################################ FROM $DEV_FROM_STAGE AS dever +# install packages for development work +COPY .docker/dever_apt_debs.txt /tmp/dever_apt_debs.txt +RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ + cut -d# -f1 < /tmp/dever_apt_debs.txt | envsubst \ + | xargs apt-get install -y --no-install-recommends + # add default user for devcontainer ENV DEV_USER=ubuntu RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers diff --git a/.docker/dever_apt_debs.txt b/.docker/dever_apt_debs.txt new file mode 100644 index 0000000000..62103367bf --- /dev/null +++ b/.docker/dever_apt_debs.txt @@ -0,0 +1,4 @@ +# ROS tools +ros-${ROS_DISTRO}-rqt-common-plugins +ros-${ROS_DISTRO}-rviz-common +ros-${ROS_DISTRO}-rviz2 diff --git a/.docker/tooler_apt_deps.txt b/.docker/tooler_apt_debs.txt similarity index 70% rename from .docker/tooler_apt_deps.txt rename to .docker/tooler_apt_debs.txt index 6d73ae3f86..5d746b71d8 100644 --- a/.docker/tooler_apt_deps.txt +++ b/.docker/tooler_apt_debs.txt @@ -12,6 +12,3 @@ nano unzip valgrind yadm - -# ROS tools -ros-${ROS_DISTRO}-rqt-common-plugins From 6126f1f510f878a26c6064cbf3f47784eac83fa2 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 10 Jul 2024 15:09:02 +0000 Subject: [PATCH 54/64] Use always() in if condition to force github actions to complete workflow --- .github/workflows/build_test_integration.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_test_integration.yaml b/.github/workflows/build_test_integration.yaml index 168edfc14c..c3f3f0011e 100644 --- a/.github/workflows/build_test_integration.yaml +++ b/.github/workflows/build_test_integration.yaml @@ -83,7 +83,7 @@ jobs: build_prod_images: name: Prod uses: ros-navigation/navigation2/.github/workflows/build_prod_images.yaml@buildkit - if: needs.colcon_build_test.outputs.build_result == 'success' + if: ${{ always() && (needs.colcon_build_test.outputs.build_result == 'success') }} secrets: inherit needs: - build_base_images From 75b849b3dd04c0da9c2f47910c5cd3ad733c2676 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 10 Jul 2024 10:39:00 -0500 Subject: [PATCH 55/64] Add shim to build dever stage from debugger image to create dev container from CI images with pre-built artifacts --- .devcontainer/initialize-command.sh | 12 ++++++++++++ docker-bake.hcl | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/.devcontainer/initialize-command.sh b/.devcontainer/initialize-command.sh index 14aaba3a3b..2995ee4492 100755 --- a/.devcontainer/initialize-command.sh +++ b/.devcontainer/initialize-command.sh @@ -10,6 +10,18 @@ set -eo pipefail # Use first argument as target name target=$1 +################################################################################ +# MARK: Pull image - download image from CI and AWS ECR for local dev container +# REFERENCE_IMAGE=ghcr.io/ros-navigation/navigation2:main-debugger +# docker pull $REFERENCE_IMAGE +# export DEV_FROM_STAGE=$REFERENCE_IMAGE +################################################################################ + +################################################################################ +# MARK: Build image - bake image using local Dockerfile for local dev container +unset DEV_FROM_STAGE +################################################################################ + # Bake the target and export locally to static tag docker buildx bake --load \ --file docker-bake.hcl \ diff --git a/docker-bake.hcl b/docker-bake.hcl index b7da477591..c1cc5301a1 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -58,10 +58,17 @@ target "tooler" { // MARK: Development targets ################################################################################ +variable "DEV_FROM_STAGE" { + default = "tooler" +} + target "dever" { inherits = ["tooler"] target = "dever" tags = ["nav2:dever"] + args = { + DEV_FROM_STAGE = "${DEV_FROM_STAGE}", + } } target "seeder" { From 090be7f68e553780323dd42a9d2631472157cfb1 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 10 Jul 2024 10:49:51 -0500 Subject: [PATCH 56/64] Fix src folder to use full repo name for self constancy with dev container config and with CI images --- .docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index 8a18d81b9f..8613efebff 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -49,7 +49,7 @@ RUN rosdep update \ FROM baser AS cacher # copy overlay source -COPY ./ ./src/nav2 +COPY ./ ./src/navigation2 SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN dep_types=(\ From fd8409127a7629617864488b69b2966b81b58f68 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 10 Jul 2024 10:52:40 -0500 Subject: [PATCH 57/64] Remove --symlink-install from default script to readily re-use CI debugger image that build colcon workspace without it so that colcon install can be standalone --- .devcontainer/update-content-command.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/.devcontainer/update-content-command.sh b/.devcontainer/update-content-command.sh index 8b5b5c324a..7597c63285 100755 --- a/.devcontainer/update-content-command.sh +++ b/.devcontainer/update-content-command.sh @@ -57,7 +57,6 @@ echo BUILD_PACKAGES: $BUILD_PACKAGES # OPTOINAL: Uncomment to build packages upon update . /opt/ros/$ROS_DISTRO/setup.sh colcon build \ - --symlink-install \ --mixin $OVERLAY_MIXINS \ --packages-select ${BUILD_PACKAGES} \ || true From 23fe6ec93ff4c872b20ee59f8fd6444f29957e6e Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 10 Jul 2024 16:05:54 +0000 Subject: [PATCH 58/64] Simplify by removing unnecessary unset allowing it to be set from global env as well --- .devcontainer/initialize-command.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.devcontainer/initialize-command.sh b/.devcontainer/initialize-command.sh index 2995ee4492..4df29eecb5 100755 --- a/.devcontainer/initialize-command.sh +++ b/.devcontainer/initialize-command.sh @@ -17,11 +17,6 @@ target=$1 # export DEV_FROM_STAGE=$REFERENCE_IMAGE ################################################################################ -################################################################################ -# MARK: Build image - bake image using local Dockerfile for local dev container -unset DEV_FROM_STAGE -################################################################################ - # Bake the target and export locally to static tag docker buildx bake --load \ --file docker-bake.hcl \ From 17b9464e2f92ebf98777571c0cb48be7b0b48a6a Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 10 Jul 2024 16:06:50 +0000 Subject: [PATCH 59/64] Correct comment --- .devcontainer/initialize-command.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/initialize-command.sh b/.devcontainer/initialize-command.sh index 4df29eecb5..79546fe52b 100755 --- a/.devcontainer/initialize-command.sh +++ b/.devcontainer/initialize-command.sh @@ -11,7 +11,7 @@ set -eo pipefail target=$1 ################################################################################ -# MARK: Pull image - download image from CI and AWS ECR for local dev container +# MARK: Pull image - download image from CI and GHCR for local dev container # REFERENCE_IMAGE=ghcr.io/ros-navigation/navigation2:main-debugger # docker pull $REFERENCE_IMAGE # export DEV_FROM_STAGE=$REFERENCE_IMAGE From 3fd241a0bb04a038d639f1d8268c7dfb13c806a8 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 10 Jul 2024 16:48:27 +0000 Subject: [PATCH 60/64] Add default gitconfig to recurse over submodules --- .gitconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .gitconfig diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000000..fcb2876001 --- /dev/null +++ b/.gitconfig @@ -0,0 +1,11 @@ +[diff] + submodule = diff +[submodule] + recurse = true + fetchJobs = 8 +[status] + submodulesummary = yes +[advice] + addIgnoredFile = false +[alias] + rinse = !git clean -xfd && git submodule foreach --recursive git clean -xfd && git reset --hard && git submodule foreach --recursive git reset --hard && git submodule update --init --recursive From e3501fed39384cd9a4b34fba504192b316f0a9b8 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 10 Jul 2024 16:50:52 +0000 Subject: [PATCH 61/64] Add readme with quick start guide --- .devcontainer/README.md | 127 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 .devcontainer/README.md diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 0000000000..25fc667963 --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,127 @@ +# Dev Containers + +This folder contains the necessary files to build and run development containers for the Navigation2 project. The containers are based on the ROS 2 Rolling distribution and include all necessary dependencies to build and run the Navigation2 stack. + +## Quick Start + +To get started, follow the instructions below. + +### Prerequisites + +First, ensure your using a recent enough version of Docker Engine that supports [BuildKit](https://docs.docker.com/build/buildkit/). If you plan on running robot simulations locally, Hardware Acceleration for sensor raytracing and 3D rendering is also recommended. While other compatible devcontainer tools may be used, Visual Studio Code is recommended for simplicity. + +#### System Software +- [Docker Engine](https://docs.docker.com/engine/install/) + - https://get.docker.com - simple universal install script + - [Linux post-installation](https://docs.docker.com/engine/install/linux-postinstall/) - manage Docker as a non-root user +- [Git LFS](https://git-lfs.github.com/) - optional for managing large assets + - Use for version controlling media such as figures +- [NVIDIA Container Toolkit](https://github.com/NVIDIA/nvidia-container-toolkit) - optional for enabling Hardware Acceleration + - [Installing the Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) - only necessary host running Docker Engine + +#### Development Tools +- [Visual Studio Code](https://code.visualstudio.com/) - alternative to Dev Containers CLI + - [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) - via SSH, Tunnels, Containers, WSL + - [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) - specific to just Containers + - [Docker extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) - for introspecting Docker daemon + - [Using SSH keys](https://code.visualstudio.com/remote/advancedcontainers/sharing-git-credentials#_using-ssh-keys) - sharing Git credentials with container +- [Dev Container CLI](https://github.com/devcontainers/cli) - alternative to VSCode + - [Installation via NPM](https://github.com/devcontainers/cli?tab=readme-ov-file#npm-install) - for custom install setup + - [Installation via VSCode](https://code.visualstudio.com/docs/devcontainers/devcontainer-cli) - for simple install setup + - Note: CLI installed via VSCode is warped but bugged, install via NPM is recommended for now + - https://github.com/devcontainers/cli/issues/799 +- [GitHub CLI](https://cli.github.com/) - optional for interacting with CI Workflows + - [Installation](https://github.com/cli/cli#installation) - specifically [for Linux](https://github.com/cli/cli/blob/trunk/docs/install_linux.md) + - [Configuration](https://cli.github.com/manual/) - login authentication and setup + +### Environment Setup + +Once you've setup your ssh keys for GitHub and account credentials for the CLI, you can add your private SSH key to the SSH agent if you'd like to use your local credentials for Git operations inside the dev container: + +```shell +# Add your SSH key to the SSH agent +ssh-add ~/.ssh/ +``` + +You may also configure Docker to use those credentials when interacting with the GitHub Container Registry (GHCR). This setup is optional, but can be useful to avoid rate limiting issues when pulling images from a popular public IP address. This can be done by using docker login with the GitHub CLI: + +```shell +# Login to GitHub Container Registry +gh auth token | docker login ghcr.io --username --password-stdin +``` + +### Cloning, Building and Running + +Next, recursively clone this repository and included submodules, bake default image tags using buildx, and then simply run containers using the build docker image. + +```shell +# Clone the repository and submodules +git clone --recurse-submodules -j8 \ + git@github.com:ros-navigation/navigation2.git + +# Change into the repository directory +cd navigation2 + +# Configure the local git include path +git config --local include.path ../.gitconfig + +# Bake the tooler image tag as a test +docker buildx bake tooler + +# Run container from image as a test +docker run -it --rm auto:tooler bash +``` + +### Launching Development Containers + +Note: using Dev Containers from a remote host is also possible: + +- [Open a folder on a remote SSH host in a container](https://code.visualstudio.com/docs/devcontainers/containers#_open-a-folder-on-a-remote-ssh-host-in-a-container) +- [Open a folder on a remote Tunnel host in a container](https://code.visualstudio.com/docs/devcontainers/containers#_open-a-folder-on-a-remote-tunnel-host-in-a-container) + +#### Visual Studio Code +Finally, open VSCode and use the Remote Containers extension: + +```shell +code . +# Press Ctrl+Shift+P to open the Command Palette +# Type and select `Dev Containers: Reopen in Container` +``` + +#### Dev Containers CLI +Alternatively, use the CLI to bring up and exec into the Dev Container: + +```shell +devcontainer up --workspace-folder . +devcontainer exec --workspace-folder . bash +``` + +### Verifying Development Containers + +To verify the dev container is setup correctly, i.e. hardware acceleration and display forwarding is working as expected, you can run simulation examples to check: + +```shell +# Included alias to source overlay workspace +sows +# Launch simulation example with GUIs enabled +ros2 launch nav2_bringup tb4_simulation_launch.py headless:=False +``` + +## Further Reading and Concepts + +Afterwards, you may want to further familiarize yourself more with the following topics: + +- Git Submodules + - https://git-scm.com/book/en/Git-Tools-Submodules + - https://git-scm.com/docs/git-submodule +- Docker + - Multi-stage + - https://docs.docker.com/build/building/multi-stage/ + - BuildKit + - https://docs.docker.com/build/buildkit/ + - Bake + - https://docs.docker.com/build/bake/ +- Development Containers + - https://navigation.ros.org/development_guides/devcontainer_docs/index.html + - https://containers.dev/ + - https://code.visualstudio.com/docs/devcontainers/containers From 1081d476319072854d91f69284a1bd7f41adace5 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 10 Jul 2024 16:53:03 +0000 Subject: [PATCH 62/64] Add alias to source underlay workspace i.e. the installed ROS distro --- .devcontainer/post-create-command.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.devcontainer/post-create-command.sh b/.devcontainer/post-create-command.sh index 34680fef2d..02cc2c89fb 100755 --- a/.devcontainer/post-create-command.sh +++ b/.devcontainer/post-create-command.sh @@ -15,3 +15,4 @@ echo "source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash" >> ~/.b # Add aliases to .bashrc echo "alias sows='source $OVERLAY_WS/install/setup.bash'" >> ~/.bashrc +echo "alias suws='source $ROS_DISTRO/setup.bash'" >> ~/.bashrc From c695baa48abe8437da4fbbbd4a61cbf1045f6af9 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 10 Jul 2024 17:40:17 +0000 Subject: [PATCH 63/64] Extend docs on build locally or pulling remotely such as re-using generated CI image to start dev containers with pre-built workspaces --- .devcontainer/README.md | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/.devcontainer/README.md b/.devcontainer/README.md index 25fc667963..164f8747dc 100644 --- a/.devcontainer/README.md +++ b/.devcontainer/README.md @@ -50,9 +50,9 @@ You may also configure Docker to use those credentials when interacting with the gh auth token | docker login ghcr.io --username --password-stdin ``` -### Cloning, Building and Running +### Submodule Setup -Next, recursively clone this repository and included submodules, bake default image tags using buildx, and then simply run containers using the build docker image. +Next, recursively clone this repository and included submodules. ```shell # Clone the repository and submodules @@ -64,14 +64,36 @@ cd navigation2 # Configure the local git include path git config --local include.path ../.gitconfig +``` + +### Images Setup + +To create the base image for the container, one can either build the image locally, or pull CI image layers cached remotely. If you need to modify the base image during the development process, such as adding or removing dependencies, you can build images locally before opening any PRs. If you want to evaluate modifications to the base image during the review process, you could then also pull pre-built CI images from an opened PR. -# Bake the tooler image tag as a test -docker buildx bake tooler +#### Building Locally + +Building locally leverages various caching strategies to speedup subsequent docker rebuilds, such as caching apt package downloads, incremental build artifacts, and multi-stage optimizations for image layer reuse. You can either let the dev container's initialization lifecycle script build the image for you, or you can pre-build the image manually: + +```shell +# Bake the dever image tag as a test +docker buildx bake dever # Run container from image as a test -docker run -it --rm auto:tooler bash +docker run -it --rm nav2:tooler bash ``` +#### Pulling Remotely + +Alternatively, you can pull the CI image layers from the GitHub Container Registry (GHCR) to bootstrap the dev container. While this method may be faster or slower depending on your local network connection, it remains particularly useful for downloading pre-built colcon workspaces built by CI and baked into the debugger stage, avoiding the need to build the image layers or re-compile a PR locally. Simply use the `DEV_FROM_STAGE` environment variable to shortcut the build process to use a given reference image, as commented from the initialization script: + +```shell +REFERENCE_IMAGE=ghcr.io/ros-navigation/navigation2:main-debugger +docker pull $REFERENCE_IMAGE +export DEV_FROM_STAGE=$REFERENCE_IMAGE +``` + +> Note: you may want to clean or create new named volumes as defined in the dev container config, given cached volumes only initialize from their first attached container. I.e. to switch between different PRs, you'll want to avoid using a named volume that was seeded from a different/older docker image. + ### Launching Development Containers Note: using Dev Containers from a remote host is also possible: From 0314c34b3280493190af06debcdce85c8c4e0853 Mon Sep 17 00:00:00 2001 From: ruffsl Date: Wed, 10 Jul 2024 18:46:52 +0000 Subject: [PATCH 64/64] Fix typo --- .devcontainer/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/README.md b/.devcontainer/README.md index 164f8747dc..b16924accd 100644 --- a/.devcontainer/README.md +++ b/.devcontainer/README.md @@ -79,7 +79,7 @@ Building locally leverages various caching strategies to speedup subsequent dock docker buildx bake dever # Run container from image as a test -docker run -it --rm nav2:tooler bash +docker run -it --rm nav2:dever bash ``` #### Pulling Remotely