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

Fail workflow at the first colcon list if a bad package name is specified #486

Merged
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
53 changes: 37 additions & 16 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10609,6 +10609,37 @@ function validateDistros(ros1Distro, ros2Distro) {
return true;
}
exports.validateDistros = validateDistros;
/**
* Install ROS dependencies for given packages in the workspace, for all ROS distros being used.
*/
function installRosdeps(upToPackages, workspaceDir, ros1Distro, ros2Distro) {
return __awaiter(this, void 0, void 0, function* () {
const scriptName = "install_rosdeps.sh";
const scriptPath = path.join(workspaceDir, scriptName);
const scriptContent = `#!/bin/bash
set -euxo pipefail
if [ $# != 1 ]; then
echo "Specify rosdistro name as single argument to this script"
exit 1
fi
DISTRO=$1
package_paths=$(colcon list --paths-only --packages-up-to ${upToPackages})
# suppress errors from unresolved install keys to preserve backwards compatibility
# due to difficulty reading names of some non-catkin dependencies in the ros2 core
# see https://index.ros.org/doc/ros2/Installation/Foxy/Linux-Development-Setup/#install-dependencies-using-rosdep
DEBIAN_FRONTEND=noninteractive RTI_NC_LICENSE_ACCEPTED=yes rosdep install -r --from-paths $package_paths --ignore-src --rosdistro $DISTRO -y || true`;
fs_1.default.writeFileSync(scriptPath, scriptContent, { mode: 0o766 });
let exitCode = 0;
const options = { cwd: workspaceDir };
if (ros1Distro) {
exitCode += yield execBashCommand(`./${scriptName} ${ros1Distro}`, "", options);
}
if (ros2Distro) {
exitCode += yield execBashCommand(`./${scriptName} ${ros2Distro}`, "", options);
}
return exitCode;
});
}
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
Expand All @@ -10619,8 +10650,7 @@ function run() {
const extraCmakeArgs = core.getInput("extra-cmake-args");
const colconExtraArgs = core.getInput("colcon-extra-args");
const importToken = core.getInput("import-token");
const packageName = core.getInput("package-name", { required: true });
const packageNameList = packageName.split(RegExp("\\s"));
const packageNames = core.getInput("package-name", { required: true }).split(RegExp("\\s")).join(" ");
const rosWorkspaceName = "ros_ws";
core.setOutput("ros-workspace-directory-name", rosWorkspaceName);
const rosWorkspaceDir = path.join(workspace, rosWorkspaceName);
Expand Down Expand Up @@ -10684,16 +10714,7 @@ function run() {
version: '${commitRef}'`;
fs_1.default.writeFileSync(repoFilePath, repoFileContent);
yield execBashCommand("vcs import --force --recursive src/ < package.repo", undefined, options);
// Remove all repositories the package under test does not depend on, to
// avoid having rosdep installing unrequired dependencies.
yield execBashCommand(`diff --new-line-format="" --unchanged-line-format="" <(colcon list -p) <(colcon list --packages-up-to ${packageNameList.join(" ")} -p) | xargs rm -rf`, undefined, options);
// Install ROS dependencies for each distribution being sourced
if (targetRos1Distro) {
yield execBashCommand(`DEBIAN_FRONTEND=noninteractive RTI_NC_LICENSE_ACCEPTED=yes rosdep install -r --from-paths src --ignore-src --rosdistro ${targetRos1Distro} -y || true`, undefined, options);
}
if (targetRos2Distro) {
yield execBashCommand(`DEBIAN_FRONTEND=noninteractive RTI_NC_LICENSE_ACCEPTED=yes rosdep install -r --from-paths src --ignore-src --rosdistro ${targetRos2Distro} -y || true`, undefined, options);
}
yield installRosdeps(packageNames, rosWorkspaceDir, targetRos1Distro, targetRos2Distro);
if (colconMixinName !== "" && colconMixinRepo !== "") {
yield execBashCommand(`colcon mixin add default '${colconMixinRepo}'`);
yield execBashCommand("colcon mixin update default");
Expand Down Expand Up @@ -10747,7 +10768,7 @@ function run() {
let colconBuildCmd = [
`colcon build`,
`--event-handlers console_cohesion+`,
`--packages-up-to ${packageNameList.join(" ")}`,
`--packages-up-to ${packageNames}`,
`${extra_options.join(" ")}`,
`--cmake-args ${extraCmakeArgs}`,
].join(" ");
Expand All @@ -10767,23 +10788,23 @@ function run() {
`--event-handlers console_cohesion+`,
`--pytest-with-coverage`,
`--return-code-on-test-failure`,
`--packages-select ${packageNameList.join(" ")}`,
`--packages-select ${packageNames}`,
`${extra_options.join(" ")}`,
].join(" ");
yield execBashCommand(colconTestCmd, colconCommandPrefix, options);
// ignoreReturnCode, check comment above in --initial
const colconLcovResultCmd = [
`colcon lcov-result`,
`--filter ${coverageIgnorePattern}`,
`--packages-select ${packageNameList.join(" ")}`,
`--packages-select ${packageNames}`,
].join(" ");
yield execBashCommand(colconLcovResultCmd, colconCommandPrefix, {
cwd: rosWorkspaceDir,
ignoreReturnCode: true,
});
const colconCoveragepyResultCmd = [
`colcon coveragepy-result`,
`--packages-select ${packageNameList.join(" ")}`,
`--packages-select ${packageNames}`,
].join(" ");
yield execBashCommand(colconCoveragepyResultCmd, colconCommandPrefix, options);
core.setOutput("ros-workspace-directory-name", rosWorkspaceName);
Expand Down
13 changes: 10 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 42 additions & 31 deletions src/action-ros-ci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,42 @@ export function validateDistros(
return true;
}

/**
* Install ROS dependencies for given packages in the workspace, for all ROS distros being used.
*/
async function installRosdeps(
upToPackages: string,
workspaceDir: string,
ros1Distro?: string,
ros2Distro?: string,
): Promise<number> {
const scriptName = "install_rosdeps.sh";
const scriptPath = path.join(workspaceDir, scriptName);
const scriptContent = `#!/bin/bash
set -euxo pipefail
if [ $# != 1 ]; then
echo "Specify rosdistro name as single argument to this script"
exit 1
fi
DISTRO=$1
package_paths=$(colcon list --paths-only --packages-up-to ${upToPackages})
# suppress errors from unresolved install keys to preserve backwards compatibility
# due to difficulty reading names of some non-catkin dependencies in the ros2 core
# see https://index.ros.org/doc/ros2/Installation/Foxy/Linux-Development-Setup/#install-dependencies-using-rosdep
DEBIAN_FRONTEND=noninteractive RTI_NC_LICENSE_ACCEPTED=yes rosdep install -r --from-paths $package_paths --ignore-src --rosdistro $DISTRO -y || true`;
fs.writeFileSync(scriptPath, scriptContent, {mode: 0o766});

let exitCode = 0;
const options = {cwd: workspaceDir};
if (ros1Distro) {
exitCode += await execBashCommand(`./${scriptName} ${ros1Distro}`, "", options);
}
if (ros2Distro) {
exitCode += await execBashCommand(`./${scriptName} ${ros2Distro}`, "", options);
}
return exitCode;
}

async function run() {
try {
const repo = github.context.repo;
Expand All @@ -154,8 +190,7 @@ async function run() {
const extraCmakeArgs = core.getInput("extra-cmake-args");
const colconExtraArgs = core.getInput("colcon-extra-args");
const importToken = core.getInput("import-token");
const packageName = core.getInput("package-name", { required: true });
const packageNameList = packageName.split(RegExp("\\s"));
const packageNames = core.getInput("package-name", { required: true }).split(RegExp("\\s")).join(" ");
const rosWorkspaceName = "ros_ws";
core.setOutput("ros-workspace-directory-name", rosWorkspaceName);
const rosWorkspaceDir = path.join(workspace, rosWorkspaceName);
Expand Down Expand Up @@ -244,31 +279,7 @@ async function run() {
options
);

// Remove all repositories the package under test does not depend on, to
// avoid having rosdep installing unrequired dependencies.
await execBashCommand(
`diff --new-line-format="" --unchanged-line-format="" <(colcon list -p) <(colcon list --packages-up-to ${packageNameList.join(
" "
)} -p) | xargs rm -rf`,
undefined,
options
);

// Install ROS dependencies for each distribution being sourced
if (targetRos1Distro) {
await execBashCommand(
`DEBIAN_FRONTEND=noninteractive RTI_NC_LICENSE_ACCEPTED=yes rosdep install -r --from-paths src --ignore-src --rosdistro ${targetRos1Distro} -y || true`,
undefined,
options
);
}
if (targetRos2Distro) {
await execBashCommand(
`DEBIAN_FRONTEND=noninteractive RTI_NC_LICENSE_ACCEPTED=yes rosdep install -r --from-paths src --ignore-src --rosdistro ${targetRos2Distro} -y || true`,
undefined,
options
);
}
await installRosdeps(packageNames, rosWorkspaceDir, targetRos1Distro, targetRos2Distro);

if (colconMixinName !== "" && colconMixinRepo !== "") {
await execBashCommand(`colcon mixin add default '${colconMixinRepo}'`);
Expand Down Expand Up @@ -326,7 +337,7 @@ async function run() {
let colconBuildCmd = [
`colcon build`,
`--event-handlers console_cohesion+`,
`--packages-up-to ${packageNameList.join(" ")}`,
`--packages-up-to ${packageNames}`,
`${extra_options.join(" ")}`,
`--cmake-args ${extraCmakeArgs}`,
].join(" ");
Expand All @@ -348,7 +359,7 @@ async function run() {
`--event-handlers console_cohesion+`,
`--pytest-with-coverage`,
`--return-code-on-test-failure`,
`--packages-select ${packageNameList.join(" ")}`,
`--packages-select ${packageNames}`,
`${extra_options.join(" ")}`,
].join(" ");
await execBashCommand(colconTestCmd, colconCommandPrefix, options);
Expand All @@ -357,7 +368,7 @@ async function run() {
const colconLcovResultCmd = [
`colcon lcov-result`,
`--filter ${coverageIgnorePattern}`,
`--packages-select ${packageNameList.join(" ")}`,
`--packages-select ${packageNames}`,
].join(" ");
await execBashCommand(colconLcovResultCmd, colconCommandPrefix, {
cwd: rosWorkspaceDir,
Expand All @@ -366,7 +377,7 @@ async function run() {

const colconCoveragepyResultCmd = [
`colcon coveragepy-result`,
`--packages-select ${packageNameList.join(" ")}`,
`--packages-select ${packageNames}`,
].join(" ");
await execBashCommand(
colconCoveragepyResultCmd,
Expand Down