Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a GitHub action to install a Gazebo release in an appropriate linux distribution #3

Merged
merged 24 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0c3bb4b
Adding gazebo key and testing garden installation
sauk2 Jun 1, 2024
65378fb
Built package to update index.js
sauk2 Jun 1, 2024
1b8726c
Changed gpg key filepath
sauk2 Jun 1, 2024
b90cfdf
Updated dist
sauk2 Jun 1, 2024
a0aef20
Changed method to get gpg key
sauk2 Jun 1, 2024
ca92b71
Added no cert check in wget of gazebo gpg key
sauk2 Jun 1, 2024
d03611c
Missing backslashes
sauk2 Jun 1, 2024
1996322
Changed to a non interactive install command
sauk2 Jun 1, 2024
56dd9f6
Added gz distro input functionality
sauk2 Jun 1, 2024
02de3a4
Installing gz distro from user input
sauk2 Jun 1, 2024
fa6e479
Added exception in case no gz distro is specified
sauk2 Jun 1, 2024
ce3973a
Updated test workflow with inputs
sauk2 Jun 1, 2024
1c7d499
Updated test workflow with multiple cases
sauk2 Jun 1, 2024
9290cea
Resolved job errors
sauk2 Jun 1, 2024
41fcded
Changed images for harmonic and garden in test workflow
sauk2 Jun 1, 2024
edd283c
Changed job names for better visibility
sauk2 Jun 1, 2024
aef0570
Changed testing to use matrix combinations
sauk2 Jun 2, 2024
d273ff5
Changed the test command to run in a single line
sauk2 Jun 3, 2024
0162761
Merge branch 'main' into feat/linux-setup
sauk2 Jun 3, 2024
1e3888d
Added default value to action input to prevent warning
sauk2 Jun 3, 2024
084ee97
Fixed indentation. Added ca certificate check while getting gz key
sauk2 Jun 3, 2024
e525dc3
Configured workflow to run on PRs/push
sauk2 Jun 4, 2024
66b9d4b
Removed ROS related variable in apt install script
sauk2 Jun 4, 2024
f469121
Installing ca certificates to resolve wget error
sauk2 Jun 4, 2024
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
48 changes: 41 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,51 @@ name: 'Test setup-gazebo'
on:
workflow_dispatch:
sauk2 marked this conversation as resolved.
Show resolved Hide resolved
jobs:
test_linux:
test_gazebo_install_ubuntu:
name: 'Check installation of Gazebo on Ubuntu'
runs-on: ubuntu-latest
container:
image: ${{ matrix.docker_image }}
strategy:
fail-fast: false
matrix:
docker_image:
- ubuntu:20.04
- ubuntu:22.04
gazebo_distribution:
- citadel
- fortress
- garden
- harmonic
include:
# Gazebo Citadel (Dec 2019 - Dec 2024)
- docker_image: ubuntu:focal
gazebo_distribution: citadel

# Gazebo Fortress (Sep 2021 - Sep 2026)
- docker_image: ubuntu:focal
gazebo_distribution: fortress

# Gazebo Garden (Sep 2022 - Nov 2024)
- docker_image: ubuntu:focal
gazebo_distribution: garden

# Gazebo Harmonic (Sep 2023 - Sep 2028)
- docker_image: ubuntu:jammy
gazebo_distribution: harmonic
steps:
- uses: actions/checkout@v2
- name: 'Linux setup'
uses: ./
- uses: actions/checkout@v4
- uses: actions/[email protected]
with:
node-version: "20.x"
- name: 'Check Gazebo installation on Ubuntu runner'
uses: ./
with:
required-gazebo-distributions: ${{ matrix.gazebo_distribution }}
- name: 'Test Gazebo installation'
run: |
if command -v ign > /dev/null; then
ign gazebo --versions
elif command -v gz > /dev/null; then
gz sim --versions
else
echo "Neither ign nor gz command found"
exit 1
fi
14 changes: 14 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
name: 'Setup Gazebo release'
description: |
Install a Gazebo release on a Linux system
required-gazebo-distributions:
description: |
List of Gazebo distributions to be installed.

Allowed Gazebo distributions
- citadel
- fortress
- garden
- harmonic

Multiple values can be passed using a whitespace delimited list
"fortress garden".
required: false
default: ''
runs:
using: node20
main: dist/index.js
81 changes: 79 additions & 2 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26286,7 +26286,7 @@ function configOs() {
yield utils.exec("sudo", ["bash", "-c", "echo 'Etc/UTC' > /etc/timezone"]);
yield utils.exec("sudo", ["apt-get", "update"]);
// Install tools required to configure the worker system.
yield apt.runAptGetInstall(["curl", "gnupg2", "locales", "lsb-release"]);
yield apt.runAptGetInstall(["wget", "curl", "gnupg2", "locales", "lsb-release"]);
// Select a locale supporting Unicode.
yield utils.exec("sudo", ["locale-gen", "en_US", "en_US.UTF-8"]);
core.exportVariable("LANG", "en_US.UTF-8");
Expand All @@ -26301,12 +26301,51 @@ function configOs() {
yield apt.runAptGetInstall(["tzdata"]);
});
}
/**
* Add OSRF APT repository key.
*
* This is necessary even when building from source to install colcon, vcs, etc.
*/
function addAptRepoKey() {
return __awaiter(this, void 0, void 0, function* () {
yield utils.exec("sudo", [
"bash",
"-c",
`wget --no-check-certificate https://packages.osrfoundation.org/gazebo.gpg -O \
/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg`,
]);
});
}
/**
* Add OSRF APT repository.
*
* @param ubuntuCodename the Ubuntu version codename
*/
function addAptRepo(ubuntuCodename) {
return __awaiter(this, void 0, void 0, function* () {
yield utils.exec("sudo", [
"bash",
"-c",
`echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] \
http://packages.osrfoundation.org/gazebo/ubuntu-stable ${ubuntuCodename} main" | \
sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null`,
]);
yield utils.exec("sudo", ["apt-get", "update"]);
});
}
/**
* Install Gazebo on a Linux worker.
*/
function runLinux() {
return __awaiter(this, void 0, void 0, function* () {
yield configOs();
yield addAptRepoKey();
// Add repo according to Ubuntu version
const ubuntuCodename = yield utils.determineDistribCodename();
yield addAptRepo(ubuntuCodename);
for (const gazeboDistro of utils.getRequiredGazeboDistributions()) {
yield apt.runAptGetInstall([`gz-${gazeboDistro}`]);
}
});
}
exports.runLinux = runLinux;
Expand Down Expand Up @@ -26411,7 +26450,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.determineDistribCodename = exports.exec = void 0;
exports.getRequiredGazeboDistributions = exports.validateDistro = exports.determineDistribCodename = exports.exec = void 0;
const actions_exec = __importStar(__nccwpck_require__(1514));
const core = __importStar(__nccwpck_require__(2186));
/**
Expand Down Expand Up @@ -26455,6 +26494,44 @@ function determineDistribCodename() {
});
}
exports.determineDistribCodename = determineDistribCodename;
// List of valid Gazebo distributions
const validDistro = ["citadel", "fortress", "garden", "harmonic"];
/**
* Validate all Gazebo input distribution names
*
* @param requiredGazeboDistributionsList
* @returns boolean Validity of Gazebo distribution
*/
function validateDistro(requiredGazeboDistributionsList) {
for (const gazeboDistro of requiredGazeboDistributionsList) {
if (validDistro.indexOf(gazeboDistro) <= -1) {
return false;
}
}
return true;
}
exports.validateDistro = validateDistro;
/**
* Gets the input of the Gazebo distributions to be installed and
* validates them
*
* @returns string[] List of validated Gazebo distributions
*/
function getRequiredGazeboDistributions() {
let requiredGazeboDistributionsList = [];
const requiredGazeboDistributions = core.getInput("required-gazebo-distributions");
if (requiredGazeboDistributions) {
requiredGazeboDistributionsList = requiredGazeboDistributions.split(RegExp("\\s"));
}
else {
throw new Error("Input cannot be empty.");
}
if (!validateDistro(requiredGazeboDistributionsList)) {
throw new Error("Input has invalid distribution names.");
}
return requiredGazeboDistributionsList;
}
exports.getRequiredGazeboDistributions = getRequiredGazeboDistributions;


/***/ }),
Expand Down
16 changes: 8 additions & 8 deletions src/package_manager/apt.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import * as utils from "../utils";

const aptCommandLine: string[] = [
"DEBIAN_FRONTEND=noninteractive",
"RTI_NC_LICENSE_ACCEPTED=yes",
"apt-get",
"install",
"--no-install-recommends",
"--quiet",
"--yes",
"DEBIAN_FRONTEND=noninteractive",
"RTI_NC_LICENSE_ACCEPTED=yes",
sauk2 marked this conversation as resolved.
Show resolved Hide resolved
"apt-get",
"install",
"--no-install-recommends",
"--quiet",
"--yes",
];

/**
Expand All @@ -24,5 +24,5 @@ const aptCommandLine: string[] = [
* @returns Promise<number> exit code
*/
export async function runAptGetInstall(packages: string[]): Promise<number> {
return utils.exec("sudo", aptCommandLine.concat(packages));
return utils.exec("sudo", aptCommandLine.concat(packages));
}
112 changes: 73 additions & 39 deletions src/setup-gazebo-linux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,89 @@ import * as io from "@actions/io";
import * as apt from "./package_manager/apt";
import * as utils from "./utils";

import * as path from "path";
import fs from "fs";

/**
* Configure basic OS stuff.
*/
async function configOs(): Promise<void> {
// When this action runs in a Docker image, sudo may be missing.
// This installs sudo to avoid having to handle both cases (action runs as
// root, action does not run as root) everywhere in the action.
try {
await io.which("sudo", true);
} catch (err) {
await utils.exec("apt-get", ["update"]);
await utils.exec("apt-get", [
"install",
"--no-install-recommends",
"--quiet",
"--yes",
"sudo",
]);
}

await utils.exec("sudo", ["bash", "-c", "echo 'Etc/UTC' > /etc/timezone"]);
await utils.exec("sudo", ["apt-get", "update"]);

// Install tools required to configure the worker system.
await apt.runAptGetInstall(["curl", "gnupg2", "locales", "lsb-release"]);

// Select a locale supporting Unicode.
await utils.exec("sudo", ["locale-gen", "en_US", "en_US.UTF-8"]);
core.exportVariable("LANG", "en_US.UTF-8");

// Enforce UTC time for consistency.
await utils.exec("sudo", ["bash", "-c", "echo 'Etc/UTC' > /etc/timezone"]);
await utils.exec("sudo", [
"ln",
"-sf",
"/usr/share/zoneinfo/Etc/UTC",
"/etc/localtime",
]);
await apt.runAptGetInstall(["tzdata"]);
// When this action runs in a Docker image, sudo may be missing.
// This installs sudo to avoid having to handle both cases (action runs as
// root, action does not run as root) everywhere in the action.
try {
await io.which("sudo", true);
} catch (err) {
await utils.exec("apt-get", ["update"]);
await utils.exec("apt-get", [
"install",
"--no-install-recommends",
"--quiet",
"--yes",
"sudo",
]);
}

await utils.exec("sudo", ["bash", "-c", "echo 'Etc/UTC' > /etc/timezone"]);
await utils.exec("sudo", ["apt-get", "update"]);

// Install tools required to configure the worker system.
await apt.runAptGetInstall(["wget", "curl", "gnupg2", "locales", "lsb-release"]);

// Select a locale supporting Unicode.
await utils.exec("sudo", ["locale-gen", "en_US", "en_US.UTF-8"]);
core.exportVariable("LANG", "en_US.UTF-8");

// Enforce UTC time for consistency.
await utils.exec("sudo", ["bash", "-c", "echo 'Etc/UTC' > /etc/timezone"]);
await utils.exec("sudo", [
"ln",
"-sf",
"/usr/share/zoneinfo/Etc/UTC",
"/etc/localtime",
]);
await apt.runAptGetInstall(["tzdata"]);
}

/**
* Add OSRF APT repository key.
*
* This is necessary even when building from source to install colcon, vcs, etc.
*/
async function addAptRepoKey(): Promise<void> {
await utils.exec("sudo", [
"bash",
"-c",
`wget https://packages.osrfoundation.org/gazebo.gpg -O \
/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg`,
]);
}

/**
* Add OSRF APT repository.
*
* @param ubuntuCodename the Ubuntu version codename
*/
async function addAptRepo(ubuntuCodename: string): Promise<void> {
await utils.exec("sudo", [
"bash",
"-c",
`echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] \
http://packages.osrfoundation.org/gazebo/ubuntu-stable ${ubuntuCodename} main" | \
sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null`,
]);
await utils.exec("sudo", ["apt-get", "update"]);
}

/**
* Install Gazebo on a Linux worker.
*/
export async function runLinux(): Promise<void> {
await configOs();
await addAptRepoKey();

await configOs();
// Add repo according to Ubuntu version
const ubuntuCodename = await utils.determineDistribCodename();
await addAptRepo(ubuntuCodename);

for (const gazeboDistro of utils.getRequiredGazeboDistributions()) {
await apt.runAptGetInstall([`gz-${gazeboDistro}`]);
}
}
8 changes: 4 additions & 4 deletions src/setup-gazebo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ async function run() {
}
catch (error) {
let errorMessage = "Unknown error";
if (error instanceof Error) {
errorMessage = error.message;
}
core.setFailed(errorMessage);
if (error instanceof Error) {
errorMessage = error.message;
}
core.setFailed(errorMessage);
}
}

Expand Down
Loading