Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.2.0] - 2025-05-09

### Added
- Added new `dockerfile_templates/python.txt` template where all python related packages are defined. Now python is istalled by default
- Added new oh-my-zsh plugins: zsh-autosuggestions, zsh-completions and zsh-syntax-highlighting
- Added `git-lfs` to `dockerfile_templates/install_common_packages.txt`

### Fixed
- Fixed `zsh` autocompletion issue in ROS2

### Changed
- Introduced `dockerfile_templates/ros2_extra.txt` to explicitly define extra ROS packages and reduced scope of ros2.txt

### Removed
- Removed python installation from `dockerfile_templates/conan.txt` as python is installed by default now
- Removed any pip upgrades from template files as pip is being upgraded by default at `dockerfile_templates/python.txt`

## [3.1.1] - 2025-03-21

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "turludock"
version = "3.1.1"
version = "3.2.0"
description = "Builds ROS docker images that support GUI with either X11 or Wayland."
authors = [
"Athanasios <[email protected]>",
Expand Down
7 changes: 2 additions & 5 deletions turludock/assets/dockerfile_templates/conan.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
# Install conan
RUN apt-get update && apt-get install -y python3-pip && \
apt-get clean && rm -rf /var/lib/apt/lists/*

RUN pip install --no-cache-dir --break-system-packages --upgrade pip || pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir --break-system-packages --ignore-installed PyYAML && \
RUN pip install --no-cache-dir --break-system-packages --ignore-installed PyYAML && \
pip install --no-cache-dir --break-system-packages --ignore-installed distro && \
pip install --no-cache-dir --break-system-packages conan
6 changes: 1 addition & 5 deletions turludock/assets/dockerfile_templates/cpplint.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
# Install cpplint
RUN apt-get update && apt-get install -y python3-pip && \
apt-get clean && rm -rf /var/lib/apt/lists/*

RUN pip install --user --no-cache-dir --break-system-packages --upgrade pip && \
pip install --user --no-cache-dir --break-system-packages cpplint
RUN pip install --user --no-cache-dir --break-system-packages cpplint
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ sudo \
locales \
lsb-release \
git \
git-lfs \
subversion \
nano \
vim \
Expand Down
6 changes: 5 additions & 1 deletion turludock/assets/dockerfile_templates/oh_my_zsh.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,9 @@ RUN apt-get update && apt-get install -y zsh && apt-get clean && rm -rf /var/lib
git clone https://github.com/sindresorhus/pure /root/.oh-my-zsh/custom/pure && \
ln -s /root/.oh-my-zsh/custom/pure/pure.zsh-theme /root/.oh-my-zsh/custom/ && \
ln -s /root/.oh-my-zsh/custom/pure/async.zsh /root/.oh-my-zsh/custom/ && \
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions && \
git clone https://github.com/zsh-users/zsh-completions.git ${ZSH_CUSTOM:-${ZSH:-~/.oh-my-zsh}/custom}/plugins/zsh-completions && \
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting && \
sed -i -e 's/robbyrussell/refined/g' /root/.zshrc && \
sed -i '/plugins=(/c\plugins=(git pyenv)' /root/.zshrc
sed -i '/plugins=(/c\plugins=(git pyenv zsh-autosuggestions zsh-syntax-highlighting)' /root/.zshrc && \
sed -i '/source \$ZSH\/oh-my-zsh\.sh/i # needed for zsh-completions\nfpath+=${ZSH_CUSTOM:-${ZSH:-~/.oh-my-zsh}/custom}/plugins/zsh-completions/src\nautoload -U compinit \&\& compinit\n' ~/.zshrc
5 changes: 5 additions & 0 deletions turludock/assets/dockerfile_templates/python.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Install Python and Python related packages
RUN apt-get update && apt-get install -y python3 python3-dev python3-venv python3-pip && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# Upgrade pip - but not all pip versions support "--break-system-packages"
RUN python3 -m pip install --upgrade pip --break-system-packages --ignore-installed || python3 -m pip install --upgrade pip
6 changes: 2 additions & 4 deletions turludock/assets/dockerfile_templates/ros2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ RUN add-apt-repository -y universe && \

RUN apt-get update && apt-get install -y \
ros-$ros_version_short-desktop \
ros-dev-tools \
ros-$ros_version_short-perception \
libpcl-dev && \
ros-dev-tools && \
apt-get clean && rm -rf /var/lib/apt/lists/*

RUN echo "source /opt/ros/$ros_version_short/setup.bash" >> /root/.bashrc && \
echo "source /opt/ros/$ros_version_short/setup.zsh" >> /root/.zshrc
echo "source /opt/ros/$ros_version_short/setup.zsh" >> /root/.zshrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Fix for argcomplete for ros2 & colcon (https://github.com/ros2/ros2cli/issues/534#issuecomment-957516107)
RUN echo "\n# Fix for argcomplete for ros2 & colcon (https://github.com/ros2/ros2cli/issues/534#issuecomment-957516107)" >> /root/.zshrc && \
echo 'eval "$$(/usr/bin/register-$python_argcomplete ros2)"' >> /root/.zshrc && \
echo 'eval "$$(/usr/bin/register-$python_argcomplete colcon)"' >> /root/.zshrc
21 changes: 21 additions & 0 deletions turludock/assets/dockerfile_templates/ros2_extra.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Extra ROS2 packages
RUN apt-get update && apt-get install -y \
ros-$ros_version_short-rclpy-message-converter \
ros-$ros_version_short-diagnostic-updater \
ros-$ros_version_short-joint-state-publisher \
ros-$ros_version_short-rosbag2-storage-mcap \
ros-$ros_version_short-perception \
ros-$ros_version_short-cv-bridge \
ros-$ros_version_short-pcl-ros \
ros-$ros_version_short-pcl-conversions \
ros-$ros_version_short-point-cloud-transport \
ros-$ros_version_short-visualization-msgs \
ros-$ros_version_short-sensor-msgs \
ros-$ros_version_short-geometry-msgs \
ros-$ros_version_short-mavros-msgs \
ros-$ros_version_short-nmea-msgs \
ros-$ros_version_short-geographic-msgs \
ros-$ros_version_short-vision-msgs \
ros-$ros_version_short-v4l2-camera \
libpcl-dev && \
apt-get clean && rm -rf /var/lib/apt/lists/*
6 changes: 6 additions & 0 deletions turludock/generate_dockerfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
generate_meld,
generate_mesa,
generate_ohmyzsh,
generate_python,
generate_terminator,
generate_vscode,
)
Expand All @@ -31,6 +32,8 @@
generate_header_info,
generate_llvm,
generate_ros,
generate_ros_autocomplete_fix,
generate_ros_extra,
generate_tmux,
)
from turludock.helper_functions import (
Expand Down Expand Up @@ -163,6 +166,7 @@ def generate_dockerfile(yaml_config: Dict[str, Any]) -> str:
# Common configuration for all images
dockerfile += generate_common_env_config()
dockerfile += generate_install_common_packages()
dockerfile += generate_python()
dockerfile += generate_locale()
dockerfile += generate_cmake(_get_package_version(yaml_config, "cmake"))
dockerfile += generate_terminator()
Expand Down Expand Up @@ -208,6 +212,8 @@ def generate_dockerfile(yaml_config: Dict[str, Any]) -> str:

# Add ROS
dockerfile += generate_ros(yaml_config["ros_version"])
dockerfile += generate_ros_extra(yaml_config["ros_version"])
dockerfile += generate_ros_autocomplete_fix(yaml_config["ros_version"])

# Add the extra-packages
extra_packages_label_list = list()
Expand Down
9 changes: 9 additions & 0 deletions turludock/generate_non_templated_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ def generate_install_common_packages() -> str:
return get_non_templated_file("install_common_packages.txt")


def generate_python() -> str:
"""Get python.txt as a string

Returns:
str: The python.txt as a string
"""
return get_non_templated_file("python.txt")


def generate_locale() -> str:
"""Get locale.txt as a string

Expand Down
97 changes: 79 additions & 18 deletions turludock/generate_templated_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
get_cpu_count_for_build,
get_ros_major_version,
get_ubuntu_version,
is_ros_version_supported,
is_version_greater,
is_version_lower,
)
Expand All @@ -29,11 +28,18 @@ def populate_templated_file(mapping: Dict[str, str], templated_file: str) -> str
Returns:
str: The populated templated file.
"""
with importlib.resources.open_text("turludock.assets.dockerfile_templates", templated_file) as f:
src = Template(f.read())
str_output = src.substitute(mapping)
str_output += "\n\n"
return str_output
try:
with importlib.resources.open_text("turludock.assets.dockerfile_templates", templated_file) as f:
src = Template(f.read())
str_output = src.substitute(mapping)
str_output += "\n\n"
return str_output
except FileNotFoundError:
print(f"Template file '{templated_file}' not found.")
except KeyError as e:
print(f"Missing substitution key: {e}")
except Exception as e:
print(f"An unexpected error occurred at function `populate_templated_file`: {e}")


def _get_ubuntu_base_image(version: str, nvidia: bool) -> str:
Expand Down Expand Up @@ -121,10 +127,6 @@ def generate_header_info(docker_label_description: str, ros_version_short: str)
"""
logger.debug(f"Generate 'header_info.txt'. Input: {docker_label_description}, {ros_version_short}")

# Check if provided version is supported
if not is_ros_version_supported(ros_version_short):
raise ValueError(f"ROS version '{ros_version_short}' not supported. Check your configuration.")

# Map the template variables
mapping = {
"docker_label_description": docker_label_description,
Expand Down Expand Up @@ -199,18 +201,15 @@ def generate_llvm(version: str) -> str:


def generate_ros(ros_version_codename: str) -> str:
"""Generates the 'ros1.txt' or 'ros2.txt' templated file, which is responsible for installing ROS 1 or 2
"""Generates the 'rosX.txt' templated file, which is responsible for installing ROS 1 or 2

The selection of ROS 1 or 2 is based on the provided ROS codename.

Args:
ros_version_codename (str): The ROS version as codename.

Returns:
str: The populated 'ros1.txt' file as a string.

Raises:
ValueError: If the provided ROS version is not supported.
str: The populated 'rosX.txt' file as a string.
"""
# Determine if it ROS1 or ROS2
if get_ros_major_version(ros_version_codename) == 1:
Expand All @@ -220,9 +219,32 @@ def generate_ros(ros_version_codename: str) -> str:

logger.debug(f"Generate '{template_file}'. Input: {ros_version_codename}")

# Check if provided version is supported
if not is_ros_version_supported(ros_version_codename):
raise ValueError("ROS version not supported. Check your configuration.")
# Map the template variables
mapping = {"ros_version_short": ros_version_codename}

# Populate the templated file
return populate_templated_file(mapping, template_file)


def generate_ros_extra(ros_version_codename: str) -> str:
"""Generates the 'rosX_extra.txt' templated file, which is responsible for installing extra ROS packages

The selection of ROS 1 or 2 is based on the provided ROS codename.

Args:
ros_version_codename (str): The ROS version as codename.

Returns:
str: The populated 'rosX_extra.txt' file as a string.
"""
# Determine if it ROS1 or ROS2
if get_ros_major_version(ros_version_codename) == 1:
# TODO
return ""
else:
template_file = "ros2_extra.txt"

logger.debug(f"Generate '{template_file}'. Input: {ros_version_codename}")

# Map the template variables
mapping = {"ros_version_short": ros_version_codename}
Expand All @@ -231,6 +253,45 @@ def generate_ros(ros_version_codename: str) -> str:
return populate_templated_file(mapping, template_file)


def generate_ros_autocomplete_fix(ros_version_codename: str) -> str:
"""Generates the 'ros2_autocomplete_fix.txt' templated file as string

This file is responsible for introducing a fix for zsh autocomplete.
https://github.com/ros2/ros2cli/issues/534#issuecomment-957516107

This has the hidden assumption that a ROS2 version is always coupled to a Ubuntu version.
The fix should actually be on the Ubuntu version and not the ROS2 version.

Args:
ros_version_codename (str): The ROS version as codename.

Returns:
str: The populated 'ros2_autocomplete_fix.txt' file as a string.

Raises:
ValueError: If ROS version not supported / not yet added by this function
"""

if get_ros_major_version(ros_version_codename) == 1:
return ""

template_file = "ros2_autocomplete_fix.txt"

# Only apply for Humble
if ros_version_codename == "humble" or ros_version_codename == "iron":
mapping = {"python_argcomplete": "python-argcomplete3"}
elif ros_version_codename == "jazzy":
mapping = {"python_argcomplete": "python-argcomplete"}
else:
raise ValueError(
f"ROS version {ros_version_codename} not yet supported by this function. "
"Ask the developer to add support!"
)

logger.debug(f"Generate '{template_file}'. Input: {ros_version_codename}")
return populate_templated_file(mapping, template_file)


def generate_extra_packages_label(extra_packages_list: List[str]) -> str:
"""Generates the 'extra_packages_label.txt' templated file

Expand Down