Skip to content

ci: run the ROS jobs on ros-base images so nothing fetches rosdep's sources list - #682

Open
bburda wants to merge 3 commits into
mainfrom
ros-base-images
Open

ci: run the ROS jobs on ros-base images so nothing fetches rosdep's sources list#682
bburda wants to merge 3 commits into
mainfrom
ros-base-images

Conversation

@bburda

@bburda bburda commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Pull Request

Summary

Every container job in ci.yml, quality.yml and opcua-plugin.yml runs on a bare ubuntu:<codename> image and installs ROS with ros-tooling/setup-ros@v0.7. That action removes /etc/ros/rosdep/sources.list.d/20-default.list and then runs sudo rosdep init with no retry around it (src/setup-ros-ubuntu.ts:135-137 in the action). rosdep init downloads that file from raw.githubusercontent.com, which is the host that has failed jobs here before, and it happens before the step that does have a retry loop. A uses: step cannot be wrapped in a loop, so the fetch cannot be protected where it is.

The 11 jobs now run on ros:<distro>-ros-base. Those images ship ROS, rosdep already initialised with its sources cache filled, the ROS apt source configured, and colcon, rosdep, git, gpg, curl and vcstool. With that, setup-ros has nothing left to do and the download stops happening. The ros-apt-source composite action goes with it: it existed only so setup-ros would skip its own rate-limited lookup. The per-job Install Git steps go too, since all three images carry git.

Two follow-on changes are in here because the first one requires them. The ros-base images ship no apt package index, and the deleted steps were where the index came from, so each step that runs apt-get install now runs apt-get update first. And the coverage job's gpg install carried a comment about the Codecov action needing it; that upload happens in coverage-merge, which has its own gpg and is untouched, and nothing else in the coverage job uses gpg, so the install is gone.

coverage-merge keeps its plain ubuntu:noble image. It never used ROS.


Issue

  • none: CI configuration only, no change to the repository's code

Type

  • Bug fix
  • New feature or tests
  • Breaking change
  • Documentation only

Testing

ros-base is narrower than the ros-<distro>-desktop metapackage that setup-ros installed. The difference is rviz2, demo_nodes, turtlesim, examples and rqt, and nothing in the workspace depends on any of them. A grep over the workspace finds no reference to them, and a second check goes further. The three step bodies of the jazzy-test job were read out of the YAML and run verbatim inside a real ros:jazzy-ros-base container, with no apt-get update added beyond the ones the workflow itself carries. Result: 18 packages built, ros2_medkit_gateway unit suite 2886 tests, 0 errors, 0 failures.

Mechanical checks on the branch: every workflow still parses as YAML; no setup-ros@ reference remains; no ros-apt-source reference remains and the directory is gone; 16 image values across the 11 jobs name a ros:*-ros-base image; exactly one image: ubuntu:noble remains, in coverage-merge; and of the 24 step bodies that run apt-get install, every one also runs apt-get update.

Measured on all three images, so the apt change is not guesswork: /var/lib/apt/lists is empty and apt-get install -y --simulate ccache exits 100 on ros:humble-ros-base, ros:jazzy-ros-base and ros:lyrical-ros-base.

Two things only CI can show, and reviewers should read the first run with them in mind:

  • humble and lyrical were not built locally. Only jazzy was.
  • the first run compiles cold in every job. The images set LANG=C.UTF-8 where setup-ros exported en_US.UTF-8, and ccache includes the locale in its hash, which was confirmed by compiling the same file twice under the two locales in ros:jazzy-ros-base with ccache 4.9.1: the second compile missed. The Actions cache archive still restores, but its entries do not match, so the first run pays a full build and later runs are warm again. Cache keys are deliberately unchanged, because renaming them would save only the archive download and not the cold build.

One weakness was found and deliberately left alone: ctcache's hash covers the preprocessed input, the dumped configuration and the arguments, but not the identity of the clang-tidy binary, so a changed analyser could return an old clean result. This change does not trigger it. ubuntu:noble and ros:jazzy-ros-base offer the same clang-tidy candidate (1:18.0-59~exp2) from the same apt suites, so the analyser is the same before and after.


Checklist

  • Breaking changes are clearly described (and announced in docs / changelog if needed)
  • Tests were added or updated if needed
  • Docs were updated if behavior or public API changed

Switch the 11 container-based CI jobs across ci.yml, quality.yml and
opcua-plugin.yml from `ubuntu:<codename>` + ros-tooling/setup-ros to
ros:<distro>-ros-base directly, and drop the Pre-install ROS 2 apt source
step and the ros-apt-source composite action along with it.

setup-ros removes /etc/ros/rosdep/sources.list.d/20-default.list and runs
sudo rosdep init with no retry, which fetches that file from
raw.githubusercontent.com before the step that has a retry loop around it.
The ros-base images already ship rosdep initialized with sources.cache
filled, the ROS apt source configured, and colcon, rosdep, git, gpg, curl
and vcstool installed, so there is nothing left for setup-ros or the
apt-source action to do, and the download that has caused outages before
never happens.

ros-base is narrower than the desktop metapackage setup-ros installs (no
rviz2, demo_nodes, turtlesim, examples, rqt); nothing in the workspace
depends on any of them, confirmed by building and running the full unit
suite for ros2_medkit_gateway inside a real ros:jazzy-ros-base container
(2886 tests, 0 failures). The coverage-merge job, which never used ROS,
keeps its plain ubuntu:noble image untouched.

The per-job "Install Git" steps are also removed: all three ros-base
images carry git already.
The ros-base images carry no apt package index at all, unlike the
ubuntu:<codename> images setup-ros used to run against. Removing the
Install Git step (apt-get update; apt-get install -y git) and setup-ros
(which ran its own update as part of installing ROS) left 11 step bodies
across ci.yml, quality.yml and opcua-plugin.yml with an apt-get install
and no update anywhere in that body: the "Install ccache" step in every
container job, "Install ccache and clang-tidy" and "Install clang-tidy-
cache (ctcache)" in quality.yml's clang-tidy job. Every "Install
dependencies" step already opened with its own apt-get update and needed
no change.

Add apt-get update to each of those 11 step bodies, before the install,
so each step carries its own index and does not depend on an update
happening to run earlier in the job.
The coverage job's "Install dependencies" step installed gpg with a
comment saying codecov/codecov-action needed it, but this job never
uploads to Codecov - that happens in coverage-merge, which has its own
gpg install and is untouched by this change. Nothing else in the
coverage job (build, test, lcov report generation, tracefile upload)
uses gpg either, so the package was dead weight justified by a reason
that belonged to a different job. The install goes with the comment.
@bburda bburda self-assigned this Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant