Skip to content
Open
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
49 changes: 49 additions & 0 deletions .github/workflows/installers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
- "ros2-humble-**.sh"
- "ros2-jazzy-**.sh"
- "ros2-kilted-**.sh"
- "ros2-lyrical-**.sh"
- ".github/workflows/installers.yml"
pull_request:
branches:
Expand All @@ -15,6 +16,7 @@ on:
- "ros2-humble-**.sh"
- "ros2-jazzy-**.sh"
- "ros2-kilted-**.sh"
- "ros2-lyrical-**.sh"
- ".github/workflows/installers.yml"
schedule:
- cron: "0 1 * * 1"
Expand Down Expand Up @@ -117,3 +119,50 @@ jobs:
run: |
sed -e 's/^\(ROS_DISTRO=.*\)/#\1\nROS_DISTRO=kilted/g' -i tutorial.sh
bash <(head -n -2 ./tutorial.sh)

lyrical-ros-base-main:
runs-on: ubuntu-24.04
container: ubuntu:26.04
defaults:
run:
shell: bash
env:
DEBIAN_FRONTEND: noninteractive
ROS_DISTRO: lyrical
steps:
- name: Install container prerequisites
run: |
apt-get update
apt-get install -y ca-certificates git sudo
- uses: actions/checkout@v6
- name: Run the install script
run: |
./ros2-lyrical-ros-base-main.sh
- name: Run the test script
run: |
sed -e 's/^\(ROS_DISTRO=.*\)/#\1\nROS_DISTRO=lyrical/g' -i tutorial.sh
sed -e 's/^\(source \/opt.*bash\)$/\1\nrosdep install -r -y -i --from-paths ./g' -i tutorial.sh
bash <(head -n -2 ./tutorial.sh)
Comment on lines +141 to +145

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use explicit smoke checks for Lyrical jobs instead of tutorial build flow.

Line 145 and Line 168 still execute tutorial.sh (which performs clone/build/test), so these jobs are not lightweight smoke checks and are likely to be slower/flakier in ubuntu:26.04 containers.

Suggested patch
   lyrical-ros-base-main:
@@
-      - name: Run the test script
+      - name: Run smoke tests
         run: |
-          sed -e 's/^\(ROS_DISTRO=.*\)/#\1\nROS_DISTRO=lyrical/g' -i tutorial.sh
-          sed -e 's/^\(source \/opt.*bash\)$/\1\nrosdep install -r -y -i --from-paths ./g' -i tutorial.sh
-          bash <(head -n -2 ./tutorial.sh)
+          source /opt/ros/lyrical/setup.bash
+          ros2 pkg prefix rclcpp
+          ros2 interface show std_msgs/msg/String

   lyrical-desktop-main:
@@
-      - name: Run the test script
+      - name: Run smoke tests
         run: |
-          sed -e 's/^\(ROS_DISTRO=.*\)/#\1\nROS_DISTRO=lyrical/g' -i tutorial.sh
-          bash <(head -n -2 ./tutorial.sh)
+          source /opt/ros/lyrical/setup.bash
+          ros2 pkg prefix rclcpp
+          ros2 interface show std_msgs/msg/String
+          ros2 pkg prefix rviz2

Also applies to: 165-168

🧰 Tools
🪛 zizmor (1.25.2)

[warning] 123-145: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block

(excessive-permissions)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/installers.yml around lines 141 - 145, Replace the heavy
tutorial build flow invoked in the "Run the test script" step (the sed lines
that edit tutorial.sh and the bash <(head -n -2 ./tutorial.sh) invocation) with
explicit lightweight smoke checks for Lyrical jobs: remove the sed edits and the
tutorial.sh execution and instead run targeted, fast validations (for example: a
minimal colcon build of only lyrical packages or a quick smoke test command such
as running a small unit-test subset or a CLI sanity check) so the job becomes a
fast smoke check rather than cloning/building the full tutorial; update the step
named "Run the test script" to run these explicit smoke commands.


lyrical-desktop-main:
runs-on: ubuntu-24.04
container: ubuntu:26.04
defaults:
run:
shell: bash
env:
DEBIAN_FRONTEND: noninteractive
ROS_DISTRO: lyrical
steps:
- name: Install container prerequisites
run: |
apt-get update
apt-get install -y ca-certificates git sudo
- uses: actions/checkout@v6
- name: Run the install script
run: |
./ros2-lyrical-desktop-main.sh
- name: Run the test script
run: |
sed -e 's/^\(ROS_DISTRO=.*\)/#\1\nROS_DISTRO=lyrical/g' -i tutorial.sh
bash <(head -n -2 ./tutorial.sh)
6 changes: 6 additions & 0 deletions .test/test-os-check-noble.bats
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ setup() {
[ "$status" -eq 1 ]
assert_output --partial "ERROR: This OS (version: noble) is not supported"
}

@test "Lyrical fail on Ubuntu 24.04" {
run ./ros2-lyrical-desktop-main.sh
[ "$status" -eq 1 ]
assert_output --partial "ERROR: This OS (version: noble) is not supported"
}
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ ROS 2 Kilted
* To install `ros-kilted-ros-base`, use [`ros2-kilted-ros-base-main.sh`](./ros2-kilted-ros-base-main.sh) instead of `run.sh`.
* To install `ros-kilted-desktop`, use [`ros2-kilted-desktop-main.sh`](./ros2-kilted-desktop-main.sh) instead of `run.sh`.

ROS 2 Lyrical (LTS)

* To install `ros-lyrical-ros-base`, use [`ros2-lyrical-ros-base-main.sh`](./ros2-lyrical-ros-base-main.sh) instead of `run.sh`.
* To install `ros-lyrical-desktop`, use [`ros2-lyrical-desktop-main.sh`](./ros2-lyrical-desktop-main.sh) instead of `run.sh`.

#### Old versions

ROS 2 Dashing (EOL)
Expand Down Expand Up @@ -75,13 +80,15 @@ Reference: [REP-0003](https://ros.org/reps/rep-0003.html), [REP-2000](https://ro
| Ubuntu 20.04<br>EOL: April 2025[^3] | Noetic<br>EOL: May 2025 | Foxy<br>EOL: May 2023 |
| Ubuntu 22.04<br>EOL: April 2027[^4] | - | Humble<br>EOL: May 2027 |
| Ubuntu 24.04<br>EOL: June 2029[^5] | - | Jazzy<br>EOL: May 2029 |
| Ubuntu 26.04<br>EOL: May 2031[^6] | - | Lyrical<br>EOL: May 2031 |

* Note: Here, EOL for Ubuntu refers to the end of normal support, which is not Ubuntu Pro.

[^2]: https://ubuntu.com//blog/18-04-end-of-standard-support
[^3]: https://wiki.ubuntu.com/FocalFossa/ReleaseNotes
[^4]: https://discourse.ubuntu.com/t/jammy-jellyfish-release-notes/24668
[^5]: https://discourse.ubuntu.com/t/noble-numbat-release-notes/39890
[^6]: https://documentation.ubuntu.com/project/release-team/list-of-releases/

## LICENSE

Expand Down
69 changes: 69 additions & 0 deletions ros2-lyrical-desktop-main.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
set -eu

# Copyright 2019-2026 Tiryoh
# https://github.com/Tiryoh/ros2_setup_scripts_ubuntu
# Licensed under the Apache License, Version 2.0
#
# REF: https://docs.ros.org/en/lyrical/Installation/Ubuntu-Install-Debs.html
# by Open Robotics, licensed under CC-BY-4.0
# source: https://github.com/ros2/ros2_documentation

CHOOSE_ROS_DISTRO=lyrical
INSTALL_PACKAGE=desktop
TARGET_OS=resolute

# Check OS version
if ! which lsb_release > /dev/null ; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using which to check for command existence is non-standard and can behave inconsistently across different POSIX shells or minimal environments. It is recommended to use command -v instead.

Suggested change
if ! which lsb_release > /dev/null ; then
if ! command -v lsb_release > /dev/null ; then

sudo apt-get update
sudo apt-get install -y curl lsb-release
fi

if [[ "$(lsb_release -sc)" == "$TARGET_OS" ]]; then
echo "OS Check Passed"
else
printf '\033[33m%s\033[m\n' "=================================================="
printf '\033[33m%s\033[m\n' "ERROR: This OS (version: $(lsb_release -sc)) is not supported"
printf '\033[33m%s\033[m\n' "=================================================="
exit 1
fi

ARCH=$(dpkg --print-architecture)
if [[ "$ARCH" != "amd64" && "$ARCH" != "arm64" ]]; then
printf '\033[33m%s\033[m\n' "=================================================="
printf '\033[33m%s\033[m\n' "ERROR: This architecture ($ARCH) is not supported"
printf '\033[33m%s\033[m\n' "See https://www.ros.org/reps/rep-2000.html"
printf '\033[33m%s\033[m\n' "=================================================="
exit 1
fi

# Install
sudo apt-get update
sudo apt-get install -y software-properties-common
sudo add-apt-repository -y universe
sudo apt-get install -y curl lsb-release build-essential

ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F'"' '{print $4}')
curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"
Comment on lines +46 to +47

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The curl command lacks error handling. If the GitHub API rate limit is exceeded or a network error occurs, ROS_APT_SOURCE_VERSION will be empty, leading to a subsequent silent failure or a corrupted package download because curl without -f does not return a non-zero exit code on HTTP errors (like 404). Adding -f / --fail and checking if the version string is empty improves robustness.

Suggested change
ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F'"' '{print $4}')
curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"
ROS_APT_SOURCE_VERSION=$(curl -sSf https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F'"' '{print $4}')
if [[ -z "$ROS_APT_SOURCE_VERSION" ]]; then
echo "ERROR: Failed to fetch the latest ros-apt-source version." >&2
exit 1
fi
curl -sSLf -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"

sudo dpkg -i /tmp/ros2-apt-source.deb
sudo apt-get update
sudo apt-get install -y ros-$CHOOSE_ROS_DISTRO-$INSTALL_PACKAGE
Comment on lines +48 to +50

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Restore the pre-install apt upgrade step.

These installers skip the upgrade that the existing distro scripts already perform before installing ROS packages. The current Lyrical Ubuntu-deb instructions still call out upgrading first because ROS packages are built against frequently updated Ubuntu systems; omitting it here makes fresh Resolute installs more fragile. (docs.ros.org)

Suggested fix
 sudo dpkg -i /tmp/ros2-apt-source.deb
 sudo apt-get update
+sudo apt-get upgrade -y
 sudo apt-get install -y ros-$CHOOSE_ROS_DISTRO-$INSTALL_PACKAGE
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sudo dpkg -i /tmp/ros2-apt-source.deb
sudo apt-get update
sudo apt-get install -y ros-$CHOOSE_ROS_DISTRO-$INSTALL_PACKAGE
sudo dpkg -i /tmp/ros2-apt-source.deb
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y ros-$CHOOSE_ROS_DISTRO-$INSTALL_PACKAGE
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ros2-lyrical-desktop-main.sh` around lines 48 - 50, Add back the pre-install
system upgrade step before installing the ROS apt package: after installing
/tmp/ros2-apt-source.deb (the block that uses sudo dpkg -i) and before running
sudo apt-get install -y ros-$CHOOSE_ROS_DISTRO-$INSTALL_PACKAGE, run an apt
update/upgrade sequence (e.g., sudo apt-get update && sudo apt-get -y upgrade)
to ensure the system packages are up-to-date per the Lyrical install docs;
update the script around the sudo dpkg -i and sudo apt-get install lines in
ros2-lyrical-desktop-main.sh so the upgrade runs first and then proceeds to
install the ROS package.

sudo apt-get install -y python3-argcomplete python3-colcon-clean
sudo apt-get install -y python3-colcon-common-extensions
sudo apt-get install -y python3-rosdep python3-vcstool
[ -e /etc/ros/rosdep/sources.list.d/20-default.list ] ||
sudo rosdep init
rosdep update
grep -F "source /opt/ros/$CHOOSE_ROS_DISTRO/setup.bash" ~/.bashrc ||
echo "source /opt/ros/$CHOOSE_ROS_DISTRO/setup.bash" >> ~/.bashrc
# From ROS 2 Iron, it uses ROS_AUTOMATIC_DISCOVERY_RANGE instead of ROS_LOCALHOST_ONLY
# https://docs.ros.org/en/iron/Releases/Release-Iron-Irwini.html#improved-discovery-options
grep -F "export ROS_AUTOMATIC_DISCOVERY_RANGE=" ~/.bashrc ||
echo "# export ROS_AUTOMATIC_DISCOVERY_RANGE=LOCALHOST" >> ~/.bashrc

set +u

source /opt/ros/$CHOOSE_ROS_DISTRO/setup.bash

echo "success installing ROS2 $CHOOSE_ROS_DISTRO"
echo "Run 'source /opt/ros/$CHOOSE_ROS_DISTRO/setup.bash'"
69 changes: 69 additions & 0 deletions ros2-lyrical-ros-base-main.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
set -eu

# Copyright 2019-2026 Tiryoh
# https://github.com/Tiryoh/ros2_setup_scripts_ubuntu
# Licensed under the Apache License, Version 2.0
#
# REF: https://docs.ros.org/en/lyrical/Installation/Ubuntu-Install-Debs.html
# by Open Robotics, licensed under CC-BY-4.0
# source: https://github.com/ros2/ros2_documentation

CHOOSE_ROS_DISTRO=lyrical
INSTALL_PACKAGE=ros-base
TARGET_OS=resolute

# Check OS version
if ! which lsb_release > /dev/null ; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using which to check for command existence is non-standard and can behave inconsistently across different POSIX shells or minimal environments. It is recommended to use command -v instead.

Suggested change
if ! which lsb_release > /dev/null ; then
if ! command -v lsb_release > /dev/null ; then

sudo apt-get update
sudo apt-get install -y curl lsb-release
fi

if [[ "$(lsb_release -sc)" == "$TARGET_OS" ]]; then
echo "OS Check Passed"
else
printf '\033[33m%s\033[m\n' "=================================================="
printf '\033[33m%s\033[m\n' "ERROR: This OS (version: $(lsb_release -sc)) is not supported"
printf '\033[33m%s\033[m\n' "=================================================="
exit 1
fi

ARCH=$(dpkg --print-architecture)
if [[ "$ARCH" != "amd64" && "$ARCH" != "arm64" ]]; then
printf '\033[33m%s\033[m\n' "=================================================="
printf '\033[33m%s\033[m\n' "ERROR: This architecture ($ARCH) is not supported"
printf '\033[33m%s\033[m\n' "See https://www.ros.org/reps/rep-2000.html"
printf '\033[33m%s\033[m\n' "=================================================="
exit 1
fi

# Install
sudo apt-get update
sudo apt-get install -y software-properties-common
sudo add-apt-repository -y universe
sudo apt-get install -y curl lsb-release build-essential

ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F'"' '{print $4}')
curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"
Comment on lines +46 to +47

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The curl command lacks error handling. If the GitHub API rate limit is exceeded or a network error occurs, ROS_APT_SOURCE_VERSION will be empty, leading to a subsequent silent failure or a corrupted package download because curl without -f does not return a non-zero exit code on HTTP errors (like 404). Adding -f / --fail and checking if the version string is empty improves robustness.

Suggested change
ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F'"' '{print $4}')
curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"
ROS_APT_SOURCE_VERSION=$(curl -sSf https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F'"' '{print $4}')
if [[ -z "$ROS_APT_SOURCE_VERSION" ]]; then
echo "ERROR: Failed to fetch the latest ros-apt-source version." >&2
exit 1
fi
curl -sSLf -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"

sudo dpkg -i /tmp/ros2-apt-source.deb
sudo apt-get update
sudo apt-get install -y ros-$CHOOSE_ROS_DISTRO-$INSTALL_PACKAGE
Comment on lines +48 to +50

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Restore the pre-install apt upgrade step.

This variant has the same regression as the desktop installer: it goes straight from apt-get update to apt install ros-lyrical-ros-base. The Lyrical deb-install guide still recommends upgrading first, so skipping it here makes the new installer less reliable on fresh Resolute machines. (docs.ros.org)

Suggested fix
 sudo dpkg -i /tmp/ros2-apt-source.deb
 sudo apt-get update
+sudo apt-get upgrade -y
 sudo apt-get install -y ros-$CHOOSE_ROS_DISTRO-$INSTALL_PACKAGE
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sudo dpkg -i /tmp/ros2-apt-source.deb
sudo apt-get update
sudo apt-get install -y ros-$CHOOSE_ROS_DISTRO-$INSTALL_PACKAGE
sudo dpkg -i /tmp/ros2-apt-source.deb
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y ros-$CHOOSE_ROS_DISTRO-$INSTALL_PACKAGE
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ros2-lyrical-ros-base-main.sh` around lines 48 - 50, Restore the pre-install
upgrade step before installing ROS packages: after running "sudo dpkg -i
/tmp/ros2-apt-source.deb" and immediately following "sudo apt-get update", run
an upgrade (e.g., "sudo apt-get upgrade -y" or the project's preferred upgrade
command) to ensure packages are up-to-date before the "sudo apt-get install -y
ros-$CHOOSE_ROS_DISTRO-$INSTALL_PACKAGE" step; update the script around the
dpkg/update/install block to include this upgrade command.

sudo apt-get install -y python3-argcomplete python3-colcon-clean
sudo apt-get install -y python3-colcon-common-extensions
sudo apt-get install -y python3-rosdep python3-vcstool
[ -e /etc/ros/rosdep/sources.list.d/20-default.list ] ||
sudo rosdep init
rosdep update
grep -F "source /opt/ros/$CHOOSE_ROS_DISTRO/setup.bash" ~/.bashrc ||
echo "source /opt/ros/$CHOOSE_ROS_DISTRO/setup.bash" >> ~/.bashrc
# From ROS 2 Iron, it uses ROS_AUTOMATIC_DISCOVERY_RANGE instead of ROS_LOCALHOST_ONLY
# https://docs.ros.org/en/iron/Releases/Release-Iron-Irwini.html#improved-discovery-options
grep -F "export ROS_AUTOMATIC_DISCOVERY_RANGE=" ~/.bashrc ||
echo "# export ROS_AUTOMATIC_DISCOVERY_RANGE=LOCALHOST" >> ~/.bashrc

set +u

source /opt/ros/$CHOOSE_ROS_DISTRO/setup.bash

echo "success installing ROS2 $CHOOSE_ROS_DISTRO"
echo "Run 'source /opt/ros/$CHOOSE_ROS_DISTRO/setup.bash'"