Skip to content

Commit

Permalink
Add colcon-defaults input (#570)
Browse files Browse the repository at this point in the history
Relates to #525, #526, #555

This adds a `colcon-defaults` input. The JSON content is validated and then
written to `COLCON_DEFAULTS_FILE`

Signed-off-by: Christophe Bedard <bedard.christophe@gmail.com>
  • Loading branch information
christophebedard authored Mar 10, 2021
1 parent f846414 commit 07b0bef
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 17 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,22 @@ jobs:
target-ros2-distro: ${{ matrix.ros_distribution }}
- run: test -d "${{ steps.test_repo.outputs.ros-workspace-directory-name }}/install/ament_copyright"

- uses: ./
id: test_colcon_defaults
name: "Test single package, with colcon defaults"
with:
colcon-defaults: |
{
"build": {
"build-base": "build-custom"
}
}
package-name: ament_copyright
target-ros2-distro: ${{ matrix.ros_distribution }}
vcs-repo-file-url: ${{ env.DISTRO_REPOS_URL }}
- run: test -d "${{ steps.test_colcon_defaults.outputs.ros-workspace-directory-name }}/install/ament_copyright"
- run: test -d "${{ steps.test_colcon_defaults.outputs.ros-workspace-directory-name }}/build-custom"

# The second repo file is ignored, but will get vcs-import'ed anyway.
# This test case just run basic testing on the action logic, making
# sure the for-loop is implemented correctly.
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,30 @@ steps:
target-ros1-distro: melodic
```

### Use a `colcon` `defaults.yaml` file

To use a [`colcon` `defaults.yaml` file](https://colcon.readthedocs.io/en/released/user/configuration.html#defaults-yaml), provide a valid JSON string through the `colcon-defaults` input.
This allows using a `colcon` option/argument that is not exposed by this action's inputs.

```yaml
steps:
- uses: ros-tooling/setup-ros@v0.1
with:
required-ros-distributions: foxy
- uses: ros-tooling/action-ros-ci@v0.1
with:
package-name: my_package
target-ros2-distro: foxy
colcon-defaults: |
{
"build": {
"cmake-args": [
"-DMY_CUSTOM_OPTION=ON"
]
}
}
```

### Enable Address Sanitizer to automatically report memory issues

[ASan][addresssanitizer] is an open-source tool developed to automatically report
Expand Down
7 changes: 7 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ branding:
icon: "activity"
color: "gray-dark"
inputs:
colcon-defaults:
default: ""
description: |
Valid JSON content to use as a colcon defaults.yaml file.
Use a pipe to provide a multiline string.
See: https://colcon.readthedocs.io/en/released/user/configuration.html#defaults-yaml
required: false
colcon-mixin-name:
default: ""
description: "Colcon mixin to be used to compile and test (empty means no mixin)"
Expand Down
46 changes: 35 additions & 11 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10874,6 +10874,21 @@ const targetROS1DistroInput = "target-ros1-distro";
const targetROS2DistroInput = "target-ros2-distro";
const isLinux = process.platform == "linux";
const isWindows = process.platform == "win32";
/**
* Check if a string is a valid JSON string.
*
* @param str the string to validate
* @returns `true` if valid, `false` otherwise
*/
function isValidJson(str) {
try {
JSON.parse(str);
}
catch (e) {
return false;
}
return true;
}
/**
* Convert local paths to URLs.
*
Expand Down Expand Up @@ -10993,6 +11008,7 @@ function run() {
try {
const repo = github.context.repo;
const workspace = process.env.GITHUB_WORKSPACE;
const colconDefaults = core.getInput("colcon-defaults");
const colconMixinName = core.getInput("colcon-mixin-name");
const colconMixinRepo = core.getInput("colcon-mixin-repository");
const extraCmakeArgs = core.getInput("extra-cmake-args");
Expand Down Expand Up @@ -11045,8 +11061,17 @@ function run() {
retries: 3,
});
}
// Reset colcon configuration.
// Reset colcon configuration and create defaults file if one was provided.
yield io.rmRF(path.join(os.homedir(), ".colcon"));
let colconDefaultsFile = "";
if (colconDefaults.length > 0) {
if (!isValidJson(colconDefaults)) {
core.setFailed(`colcon-defaults value is not a valid JSON string:\n${colconDefaults}`);
return;
}
colconDefaultsFile = path.join(fs_1.default.mkdtempSync(path.join(os.tmpdir(), "colcon-defaults-")), "defaults.yaml");
fs_1.default.writeFileSync(colconDefaultsFile, colconDefaults);
}
// Wipe out the workspace directory to ensure the workspace is always
// identical.
yield io.rmRF(rosWorkspaceDir);
Expand All @@ -11063,6 +11088,11 @@ function run() {
const options = {
cwd: rosWorkspaceDir,
};
if (colconDefaultsFile !== "") {
options.env = {
COLCON_DEFAULTS_FILE: colconDefaultsFile,
};
}
const curlFlags = curlFlagsArray.join(" ");
for (const vcsRepoFileUrl of vcsRepoFileUrlListResolved) {
yield execBashCommand(`curl ${curlFlags} '${vcsRepoFileUrl}' | vcs import --force --recursive src/`, undefined, options);
Expand Down Expand Up @@ -11098,8 +11128,8 @@ function run() {
yield execBashCommand("vcs log -l1 src/", undefined, options);
yield installRosdeps(packageNames, rosWorkspaceDir, targetRos1Distro, targetRos2Distro);
if (colconMixinName !== "" && colconMixinRepo !== "") {
yield execBashCommand(`colcon mixin add default '${colconMixinRepo}'`);
yield execBashCommand("colcon mixin update default");
yield execBashCommand(`colcon mixin add default '${colconMixinRepo}'`, undefined, options);
yield execBashCommand("colcon mixin update default", undefined, options);
}
let extra_options = [];
if (colconMixinName !== "") {
Expand Down Expand Up @@ -11161,10 +11191,7 @@ function run() {
// ignoreReturnCode is set to true to avoid having a lack of coverage
// data fail the build.
const colconLcovInitialCmd = "colcon lcov-result --initial";
yield execBashCommand(colconLcovInitialCmd, colconCommandPrefix, {
cwd: rosWorkspaceDir,
ignoreReturnCode: true,
});
yield execBashCommand(colconLcovInitialCmd, colconCommandPrefix, Object.assign(Object.assign({}, options), { ignoreReturnCode: true }));
const colconTestCmd = [
`colcon test`,
`--event-handlers console_cohesion+`,
Expand All @@ -11180,10 +11207,7 @@ function run() {
`--filter ${coverageIgnorePattern}`,
`--packages-select ${packageNames}`,
].join(" ");
yield execBashCommand(colconLcovResultCmd, colconCommandPrefix, {
cwd: rosWorkspaceDir,
ignoreReturnCode: true,
});
yield execBashCommand(colconLcovResultCmd, colconCommandPrefix, Object.assign(Object.assign({}, options), { ignoreReturnCode: true }));
const colconCoveragepyResultCmd = [
`colcon coveragepy-result`,
`--packages-select ${packageNames}`,
Expand Down
51 changes: 45 additions & 6 deletions src/action-ros-ci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ const targetROS2DistroInput: string = "target-ros2-distro";
const isLinux: boolean = process.platform == "linux";
const isWindows: boolean = process.platform == "win32";

/**
* Check if a string is a valid JSON string.
*
* @param str the string to validate
* @returns `true` if valid, `false` otherwise
*/
function isValidJson(str: string): boolean {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}

/**
* Convert local paths to URLs.
*
Expand Down Expand Up @@ -195,6 +210,7 @@ async function run() {
const repo = github.context.repo;
const workspace = process.env.GITHUB_WORKSPACE as string;

const colconDefaults = core.getInput("colcon-defaults");
const colconMixinName = core.getInput("colcon-mixin-name");
const colconMixinRepo = core.getInput("colcon-mixin-repository");
const extraCmakeArgs = core.getInput("extra-cmake-args");
Expand Down Expand Up @@ -268,8 +284,22 @@ async function run() {
);
}

// Reset colcon configuration.
// Reset colcon configuration and create defaults file if one was provided.
await io.rmRF(path.join(os.homedir(), ".colcon"));
let colconDefaultsFile = "";
if (colconDefaults.length > 0) {
if (!isValidJson(colconDefaults)) {
core.setFailed(
`colcon-defaults value is not a valid JSON string:\n${colconDefaults}`
);
return;
}
colconDefaultsFile = path.join(
fs.mkdtempSync(path.join(os.tmpdir(), "colcon-defaults-")),
"defaults.yaml"
);
fs.writeFileSync(colconDefaultsFile, colconDefaults);
}

// Wipe out the workspace directory to ensure the workspace is always
// identical.
Expand All @@ -287,9 +317,14 @@ async function run() {
fs.appendFileSync(path.join(os.homedir(), ".gitconfig"), config);
}

const options = {
const options: im.ExecOptions = {
cwd: rosWorkspaceDir,
};
if (colconDefaultsFile !== "") {
options.env = {
COLCON_DEFAULTS_FILE: colconDefaultsFile,
};
}

const curlFlags = curlFlagsArray.join(" ");
for (const vcsRepoFileUrl of vcsRepoFileUrlListResolved) {
Expand Down Expand Up @@ -346,8 +381,12 @@ async function run() {
);

if (colconMixinName !== "" && colconMixinRepo !== "") {
await execBashCommand(`colcon mixin add default '${colconMixinRepo}'`);
await execBashCommand("colcon mixin update default");
await execBashCommand(
`colcon mixin add default '${colconMixinRepo}'`,
undefined,
options
);
await execBashCommand("colcon mixin update default", undefined, options);
}

let extra_options: string[] = [];
Expand Down Expand Up @@ -414,7 +453,7 @@ async function run() {
// data fail the build.
const colconLcovInitialCmd = "colcon lcov-result --initial";
await execBashCommand(colconLcovInitialCmd, colconCommandPrefix, {
cwd: rosWorkspaceDir,
...options,
ignoreReturnCode: true,
});

Expand All @@ -435,7 +474,7 @@ async function run() {
`--packages-select ${packageNames}`,
].join(" ");
await execBashCommand(colconLcovResultCmd, colconCommandPrefix, {
cwd: rosWorkspaceDir,
...options,
ignoreReturnCode: true,
});

Expand Down

0 comments on commit 07b0bef

Please sign in to comment.