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
12 changes: 12 additions & 0 deletions .github/workflows/check-ros-distribution.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
#
# ./check-ros-distribution.sh <ROS distribution>
# ROS distribution must match the directory name for this distribution
# in /opt. E.g. melodic.

readonly ROS_DISTRIBUTION="$1"

# GitHub Action is erroneously setting PYTHONHOME to C:\python37
unset PYTHONHOME
source "/opt/ros/${ROS_DISTRIBUTION}/setup.bash"
rosstack list
10 changes: 10 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
schedule:
# Run the CI automatically twice per day to look for flakyness.
- cron: "0 */12 * * *"
workflow_dispatch:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What's the intent behind this?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It just lets us trigger the test workflow manually, which was handy for checking the ROS-O matrix. Happy to drop it if you'd prefer to keep it out of this PR.


defaults:
run:
Expand Down Expand Up @@ -114,6 +115,15 @@ jobs:
# Platforms are defined in REP 3: https://ros.org/reps/rep-0003.html
include:

# ROS-O (ROS One) - ROS 1 for Ubuntu 20.04+
- docker_image: ubuntu:jammy
ros_distribution: one
ros_version: 1

- docker_image: ubuntu:noble
ros_distribution: one
ros_version: 1

# Humble Hawksbill (May 2022 - May 2027)
- docker_image: ubuntu:jammy
ros_distribution: humble
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ It also performs the following actions:
- Setting the locale to `en_US.UTF-8` and, the timezone to UTC
- GCC and clang default APT packages
- Registering the Open Robotics APT repository
- For ROS-O (`one`), packages are installed from a separate APT repository
(`ros.packages.techfak.net`) maintained by the ROS-O community at CITEC
Bielefeld, not from the Open Robotics APT repository.
- Installing ROS and ROS 2 system dependencies using APT
- On macOS:
- Installing ROS and ROS 2 system dependencies using [Homebrew] and [pip]
Expand Down
1 change: 1 addition & 0 deletions __test__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ describe("required-ros-distributions/noetic workflow tests", () => {
describe("validate distribution test", () => {
it("test valid", async () => {
await expect(utils.validateDistro(["noetic"])).toBe(true);
await expect(utils.validateDistro(["one"])).toBe(true);
await expect(utils.validateDistro(["humble"])).toBe(true);
await expect(utils.validateDistro(["iron"])).toBe(true);
await expect(utils.validateDistro(["jazzy"])).toBe(true);
Expand Down
65 changes: 64 additions & 1 deletion dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34607,6 +34607,7 @@ const pip3Packages = [
"colcon-recursive-crawl==0.2.1",
"colcon-ros==0.3.23",
"colcon-test-result==0.3.8",
"meson>=0.60.0,<0.64.0",
"coverage",
"cryptography",
"empy<4",
Expand Down Expand Up @@ -35073,6 +35074,23 @@ function installRosAptSourcePackageIfNeeded(ubuntuCodename, use_ros2_testing) {
}
});
}
/**
* Add ROS-O (ROS One) APT repository key.
*
* Downloads and installs the GPG key for the ROS-O repository.
*/
function addRosOneAptRepoKey() {
return __awaiter(this, void 0, void 0, function* () {
// Ensure the keyrings directory exists and ca-certificates is up to date
yield utils.exec("sudo", ["mkdir", "-p", "/etc/apt/keyrings"]);
yield utils.exec("sudo", ["update-ca-certificates"]);
yield utils.exec("sudo", [
"bash",
"-c",
"curl -sSL https://ros.packages.techfak.net/gpg.key -o /etc/apt/keyrings/ros-one-keyring.gpg",
]);
});
}
// Ubuntu distribution for ROS 1
const ros1UbuntuVersion = "focal";
/**
Expand All @@ -35087,6 +35105,24 @@ function determineAptSourcePackageName(ubuntuCodename, use_ros2_testing) {
}
return `ros2${use_ros2_testing ? "-testing" : ""}-apt-source`;
}
/**
* Add ROS-O (ROS One) APT repository.
*
* @param ubuntuCodename the Ubuntu version codename
* @param use_testing whether to use the testing repository
*/
function addRosOneAptRepo(ubuntuCodename, use_testing) {
return __awaiter(this, void 0, void 0, function* () {
const arch = yield utils.getArch();
const repo = use_testing ? `${ubuntuCodename}-testing` : ubuntuCodename;
yield utils.exec("sudo", [
"bash",
"-c",
`echo "deb [arch=${arch} signed-by=/etc/apt/keyrings/ros-one-keyring.gpg] https://ros.packages.techfak.net ${repo} main" > /etc/apt/sources.list.d/ros-one.list`,
]);
yield utils.exec("sudo", ["apt-get", "update"]);
});
}
/**
* Initialize rosdep.
*/
Expand All @@ -35104,6 +35140,20 @@ function rosdepInit() {
yield utils.exec("sudo", ["rosdep", "init"]);
});
}
/**
* Configure rosdep for ROS-O (ROS One).
*
* Adds custom rosdep source for ROS-O packages.
*/
function configureRosOneRosdep() {
return __awaiter(this, void 0, void 0, function* () {
yield utils.exec("sudo", [
"bash",
"-c",
'echo "yaml https://ros.packages.techfak.net/ros-one.yaml one" > /etc/ros/rosdep/sources.list.d/1-ros-one.list',
]);
});
}
/**
* Install ROS 1 or 2 (development packages and/or ROS binaries) on a Linux worker.
*/
Expand All @@ -35112,9 +35162,17 @@ function runLinux() {
// Get user input & validate
const use_ros2_testing = core.getInput("use-ros2-testing") === "true";
const installConnext = core.getInput("install-connext") === "true";
const requiredDistros = utils.getRequiredRosDistributions();
// ROS-O "one" uses a separate repository (ros.packages.techfak.net).
const needsRosOne = requiredDistros.includes("one");
yield configOs();
const ubuntuCodename = yield utils.determineDistribCodename();
yield installRosAptSourcePackageIfNeeded(ubuntuCodename, use_ros2_testing);
// Add ROS-O repository if needed
if (needsRosOne) {
yield addRosOneAptRepoKey();
yield addRosOneAptRepo(ubuntuCodename, use_ros2_testing);
}
if ("noble" !== ubuntuCodename && "resolute" !== ubuntuCodename) {
// Temporary fix to avoid error mount: /var/lib/grub/esp: special device (...) does not exist.
const arch = yield utils.getArch();
Expand All @@ -35131,7 +35189,11 @@ function runLinux() {
yield pip.installPython3Dependencies();
}
yield rosdepInit();
for (const rosDistro of utils.getRequiredRosDistributions()) {
// Configure rosdep for ROS-O if needed
if (needsRosOne) {
yield configureRosOneRosdep();
}
for (const rosDistro of requiredDistros) {
yield apt.runAptGetInstall([`ros-${rosDistro}-desktop`]);
}
});
Expand Down Expand Up @@ -35463,6 +35525,7 @@ function getRequiredRosDistributions() {
//list of valid linux distributions
const validDistro = [
"noetic",
"one",
"humble",
"iron",
"jazzy",
Expand Down
1 change: 1 addition & 0 deletions src/package_manager/pip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const pip3Packages: string[] = [
"colcon-recursive-crawl==0.2.1",
"colcon-ros==0.3.23",
"colcon-test-result==0.3.8",
"meson>=0.60.0,<0.64.0",
"coverage",
"cryptography",
"empy<4",
Expand Down
66 changes: 65 additions & 1 deletion src/setup-ros-ubuntu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,22 @@ async function installRosAptSourcePackageIfNeeded(
}
}

/**
* Add ROS-O (ROS One) APT repository key.
*
* Downloads and installs the GPG key for the ROS-O repository.
*/
async function addRosOneAptRepoKey(): Promise<void> {
// Ensure the keyrings directory exists and ca-certificates is up to date
await utils.exec("sudo", ["mkdir", "-p", "/etc/apt/keyrings"]);
await utils.exec("sudo", ["update-ca-certificates"]);
await utils.exec("sudo", [
"bash",
"-c",
"curl -sSL https://ros.packages.techfak.net/gpg.key -o /etc/apt/keyrings/ros-one-keyring.gpg",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

who is behind this key and the repo?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Packages for this specific repository are build through https://github.com/ubi-agni/ros-builder-action/ and owned by @rhaschke at CITEC Bielefeld. It is pretty much the go-to repository for anyone to "just install ROS-O" these days.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the info!

I would just mention this in the README so that people know that ROS-O debs are downloaded from a separate apt repo and not the usual Open Robotics apt repo. @iory can you add that?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done — added a note to the README in the latest commit.
22b0ef7

]);
}

// Ubuntu distribution for ROS 1
const ros1UbuntuVersion = "focal";

Expand All @@ -121,6 +137,26 @@ function determineAptSourcePackageName(
return `ros2${use_ros2_testing ? "-testing" : ""}-apt-source`;
}

/**
* Add ROS-O (ROS One) APT repository.
*
* @param ubuntuCodename the Ubuntu version codename
* @param use_testing whether to use the testing repository
*/
async function addRosOneAptRepo(
ubuntuCodename: string,
use_testing: boolean,
): Promise<void> {
const arch = await utils.getArch();
const repo = use_testing ? `${ubuntuCodename}-testing` : ubuntuCodename;
await utils.exec("sudo", [
"bash",
"-c",
`echo "deb [arch=${arch} signed-by=/etc/apt/keyrings/ros-one-keyring.gpg] https://ros.packages.techfak.net ${repo} main" > /etc/apt/sources.list.d/ros-one.list`,
]);
await utils.exec("sudo", ["apt-get", "update"]);
}

/**
* Initialize rosdep.
*/
Expand All @@ -137,6 +173,19 @@ async function rosdepInit(): Promise<void> {
await utils.exec("sudo", ["rosdep", "init"]);
}

/**
* Configure rosdep for ROS-O (ROS One).
*
* Adds custom rosdep source for ROS-O packages.
*/
async function configureRosOneRosdep(): Promise<void> {
await utils.exec("sudo", [
"bash",
"-c",
'echo "yaml https://ros.packages.techfak.net/ros-one.yaml one" > /etc/ros/rosdep/sources.list.d/1-ros-one.list',
]);
}

/**
* Install ROS 1 or 2 (development packages and/or ROS binaries) on a Linux worker.
*/
Expand All @@ -145,11 +194,21 @@ export async function runLinux(): Promise<void> {
const use_ros2_testing = core.getInput("use-ros2-testing") === "true";
const installConnext = core.getInput("install-connext") === "true";

const requiredDistros = utils.getRequiredRosDistributions();
// ROS-O "one" uses a separate repository (ros.packages.techfak.net).
const needsRosOne = requiredDistros.includes("one");

await configOs();

const ubuntuCodename = await utils.determineDistribCodename();
await installRosAptSourcePackageIfNeeded(ubuntuCodename, use_ros2_testing);

// Add ROS-O repository if needed
if (needsRosOne) {
await addRosOneAptRepoKey();
await addRosOneAptRepo(ubuntuCodename, use_ros2_testing);
}

if ("noble" !== ubuntuCodename && "resolute" !== ubuntuCodename) {
// Temporary fix to avoid error mount: /var/lib/grub/esp: special device (...) does not exist.
const arch = await utils.getArch();
Expand All @@ -170,7 +229,12 @@ export async function runLinux(): Promise<void> {

await rosdepInit();

for (const rosDistro of utils.getRequiredRosDistributions()) {
// Configure rosdep for ROS-O if needed
if (needsRosOne) {
await configureRosOneRosdep();
}

for (const rosDistro of requiredDistros) {
await apt.runAptGetInstall([`ros-${rosDistro}-desktop`]);
}
}
1 change: 1 addition & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export function getRequiredRosDistributions(): string[] {
//list of valid linux distributions
const validDistro: string[] = [
"noetic",
"one",
"humble",
"iron",
"jazzy",
Expand Down