From eff671a750924e158db1b7e03c217c60cac18e1f Mon Sep 17 00:00:00 2001 From: Nathan Brooks Date: Mon, 3 Aug 2026 00:20:52 -0600 Subject: [PATCH] ci: skip the tutorial rebuild on unrelated PRs, and unfreeze its ccache tutorial-source is the long pole on every moveit2 PR. Measured across eight consecutive runs: 43m33s, 53m32s, 56m41s, 54m22s, 60m58s, 51m10s, 54m01s, 57m40s. It ran the full ~55 min on #3809, a PR touching four launch .test.py files. Two independent causes. 1. It runs on every pull_request with no path filter The job rebuilds moveit2 + moveit2_tutorials + all upstream deps from source. Changes to test fixtures, markdown, or other workflows cannot affect the tutorial image, but still trigger a full rebuild. Add a path filter so those PRs skip it. Uses `paths` with `!` rather than `paths-ignore`: negation is only supported in `paths`, and the two filters cannot be combined for a single event. The filter still runs the job when this workflow or the tutorial-source Dockerfile itself changes. Safe to skip -- verified tutorial-source (jazzy) is not a required status check on main (the required set is Format, humble-ci, jazzy-ci, rolling-ci + ikfast + clang-tidy (delta), rolling-ci + ccov), and .github/mergify.yml contains only label-driven backport rules with no check-success conditions. So a skipped run cannot block a merge and no no-op fallback job is needed. 2. The ccache was frozen after its first save key: docker-tutorial-ccache-${{ matrix.ROS_DISTRO }}-${{ hashFiles(...) }} A static key with no restore-keys. actions/cache skips its save step on an exact-key hit, so the entry is written once and never refreshed -- every build after the first restores a stale ccache and recompiles whatever changed since, indefinitely. The key only rotates when the Dockerfile changes, which is rare. Switch to the rolling-key pattern used elsewhere in this repo: make the key unique per run and fall back to the stable prefixes, so each run restores the newest entry and saves an updated one. Not addressed here, but worth follow-up: the Dockerfile does COPY . src/moveit2 above the expensive RUN (with .dockerignore deliberately removed), so any source change busts the layer; gazebo install, the tutorials clone, vcs import, rosdep and colcon build share one monolithic RUN; and the moveit2_tutorials clone is not shallow. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/tutorial_docker.yaml | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tutorial_docker.yaml b/.github/workflows/tutorial_docker.yaml index 830694cce8..c4a86c2295 100644 --- a/.github/workflows/tutorial_docker.yaml +++ b/.github/workflows/tutorial_docker.yaml @@ -6,6 +6,20 @@ on: - cron: '0 17 * * 6' workflow_dispatch: pull_request: + # This job rebuilds moveit2 + moveit2_tutorials + upstream deps from source + # and takes 45-60 min, so skip PRs that cannot affect the tutorial image. + # `paths` with `!` rather than `paths-ignore`, because negation is only + # supported in `paths` and the two cannot be combined for one event. + # Order matters: later patterns override earlier ones. + paths: + - '**' + - '!**/test/**' + - '!**/*.test.py' + - '!**.md' + - '!.github/**' + - '.github/workflows/tutorial_docker.yaml' + - '!.docker/**' + - '.docker/tutorial-source/**' merge_group: push: branches: @@ -49,7 +63,15 @@ jobs: uses: actions/cache@v5 with: path: .ccache - key: docker-tutorial-ccache-${{ matrix.ROS_DISTRO }}-${{ hashFiles( '.docker/tutorial-source/Dockerfile' ) }} + # actions/cache skips its save step on an exact-key hit, so a static key + # is written once and never refreshed -- every later build reuses a + # frozen ccache. Make the key unique per run and fall back to the + # stable prefix, so each run restores the newest entry and saves an + # updated one. + key: docker-tutorial-ccache-${{ matrix.ROS_DISTRO }}-${{ hashFiles( '.docker/tutorial-source/Dockerfile' ) }}-${{ github.run_id }} + restore-keys: | + docker-tutorial-ccache-${{ matrix.ROS_DISTRO }}-${{ hashFiles( '.docker/tutorial-source/Dockerfile' ) }}- + docker-tutorial-ccache-${{ matrix.ROS_DISTRO }}- - name: inject ccache into docker uses: reproducible-containers/buildkit-cache-dance@v3.3.0 with: