Skip to content

Commit d78532a

Browse files
ojasjoshiojasjosh
andauthored
Add colcon bundle retry (#22)
* Adding exponential backoff to colcon bundle * Update action commit hash in andstor/file-existence-action test workflow * NCC re-build Co-authored-by: ojasjosh <[email protected]>
1 parent e89687a commit d78532a

File tree

5 files changed

+72
-22
lines changed

5 files changed

+72
-22
lines changed

.github/workflows/test-ros2.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ jobs:
7070
# Expectation: bundle file, build files, and dependencies all exist
7171
- name: Check robot_ws file existence
7272
id: check_robot_ws_files
73-
uses: andstor/file-existence-action@87d74d4
73+
uses: andstor/file-existence-action@87d74d4732ddb824259d80c8a508c0124bf1c673
7474
with:
7575
files: "./robot_ws.tar, ./robot_ws/build, ./robot_ws/install, ./robot_ws/src/deps"
7676
allow_failure: true
@@ -86,15 +86,15 @@ jobs:
8686
# Expectation: bundle file, build files, and dependencies all exist
8787
- name: Check simulation_ws file existence
8888
id: check_simulation_ws_files
89-
uses: andstor/file-existence-action@87d74d4
89+
uses: andstor/file-existence-action@87d74d4732ddb824259d80c8a508c0124bf1c673
9090
with:
9191
files: "./simulation_ws.tar, ./simulation_ws/build, ./simulation_ws/install, ./simulation_ws/src/deps"
9292
allow_failure: true
9393

9494
# Expectation: source files exist
9595
- name: Check source file existence
9696
id: check_source_files
97-
uses: andstor/file-existence-action@87d74d4
97+
uses: andstor/file-existence-action@87d74d4732ddb824259d80c8a508c0124bf1c673
9898
with:
9999
files: "./sources.zip, ./sources.tar.gz"
100100

.github/workflows/test.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ jobs:
8080
# Expectation: bundle file, build files, and dependencies all exist
8181
- name: Check robot_ws file existence
8282
id: check_robot_ws_files
83-
uses: andstor/file-existence-action@87d74d4
83+
uses: andstor/file-existence-action@87d74d4732ddb824259d80c8a508c0124bf1c673
8484
with:
8585
files: "./robot_ws.tar, ./robot_ws/build, ./robot_ws/install, ./robot_ws/src/deps"
8686
allow_failure: true
@@ -96,15 +96,15 @@ jobs:
9696
# Expectation: bundle file, build files, and dependencies all exist
9797
- name: Check simulation_ws file existence
9898
id: check_simulation_ws_files
99-
uses: andstor/file-existence-action@87d74d4
99+
uses: andstor/file-existence-action@87d74d4732ddb824259d80c8a508c0124bf1c673
100100
with:
101101
files: "./simulation_ws.tar, ./simulation_ws/build, ./simulation_ws/install, ./simulation_ws/src/deps"
102102
allow_failure: true
103103

104104
# Expectation: source files exist
105105
- name: Check source file existence
106106
id: check_source_files
107-
uses: andstor/file-existence-action@87d74d4
107+
uses: andstor/file-existence-action@87d74d4732ddb824259d80c8a508c0124bf1c673
108108
with:
109109
files: "./sources.zip, ./sources.tar.gz"
110110

robomaker-sample-app-ci/action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ inputs:
1313
generate-sources:
1414
description: 'Whether or not to generate sources.zip and sources.tar.gz files [true|false]'
1515
default: false
16+
colcon-bundle-retries:
17+
description: 'Number of times colcon bundle should be re-tried with exponential backoff in case of failure [0-9]'
18+
default: 0
19+
1620
outputs:
1721
ros-distro:
1822
description: 'Distribution of ROS to use [kinetic|melodic|dashing]'

robomaker-sample-app-ci/dist/index.js

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,12 @@ const WORKSPACE_DIRECTORY = core.getInput('workspace-dir');
671671
const GENERATE_SOURCES = core.getInput('generate-sources');
672672
let PACKAGES = "none";
673673
const ROS_ENV_VARIABLES = {};
674+
const COLCON_BUNDLE_RETRIES = Number.parseInt(core.getInput('colcon-bundle-retries'), 10);
675+
const MINIMUM_BACKOFF_TIME_SECONDS = 32; // delay for the first retry in seconds
676+
const MAXIMUM_BACKOFF_TIME_SECONDS = 128; // maximum delay for a retry in seconds
677+
function delay(ms) {
678+
return new Promise( resolve => setTimeout(resolve, ms) );
679+
}
674680
function loadROSEnvVariables() {
675681
return __awaiter(this, void 0, void 0, function* () {
676682
const options = {
@@ -852,14 +858,25 @@ function build() {
852858
}
853859
function bundle() {
854860
return __awaiter(this, void 0, void 0, function* () {
855-
try {
856-
const bundleFilename = path.basename(WORKSPACE_DIRECTORY);
857-
yield exec.exec("colcon", ["bundle", "--build-base", "build", "--install-base", "install", "--bundle-base", "bundle"], getWorkingDirExecOptions());
858-
yield exec.exec("mv", ["bundle/output.tar", `../${bundleFilename}.tar`], getWorkingDirExecOptions());
859-
yield exec.exec("rm", ["-rf", "bundle"], getWorkingDirExecOptions()); // github actions have been failing with no disk space
860-
}
861-
catch (error) {
862-
core.setFailed(error.message);
861+
let delay_ms = 1000 * MINIMUM_BACKOFF_TIME_SECONDS;
862+
// indexed from 0 because COLCON_BUNDLE_RETRIES is the number of retries AFTER the initial try
863+
for (let i = 0; i <= COLCON_BUNDLE_RETRIES; i++) {
864+
try {
865+
const bundleFilename = path.basename(WORKSPACE_DIRECTORY);
866+
yield exec.exec("colcon", ["bundle", "--build-base", "build", "--install-base", "install", "--bundle-base", "bundle"], getWorkingDirExecOptions());
867+
yield exec.exec("mv", ["bundle/output.tar", `../${bundleFilename}.tar`], getWorkingDirExecOptions());
868+
yield exec.exec("rm", ["-rf", "bundle"], getWorkingDirExecOptions()); // github actions have been failing with no disk space
869+
break; // break if colcon bundle passes
870+
} catch (error) {
871+
yield exec.exec("rm", ["-rf", "bundle"], getWorkingDirExecOptions()); // remove erred bundle assets
872+
if (i == COLCON_BUNDLE_RETRIES){
873+
core.setFailed(error.message); // set action to Failed if the colcon bundle fails even after COLCON_BUNDLE_RETRIES number of retries
874+
break;
875+
}
876+
console.log(`Colcon bundle failed.. retrying in ${delay_ms} milliseconds`);
877+
yield delay(delay_ms); // wait for next retry per the current exponential backoff delay
878+
delay_ms = Math.min(delay_ms * 2, MAXIMUM_BACKOFF_TIME_SECONDS); // double the delay for the next retry, truncate if required
879+
}
863880
}
864881
});
865882
}
@@ -869,6 +886,11 @@ function run() {
869886
console.log(`GAZEBO_VERSION: ${GAZEBO_VERSION}`);
870887
console.log(`WORKSPACE_DIRECTORY: ${WORKSPACE_DIRECTORY}`);
871888
console.log(`GENERATE_SOURCES: ${GENERATE_SOURCES}`);
889+
console.log(`COLCON_BUNDLE_RETRIES: ${COLCON_BUNDLE_RETRIES}`);
890+
// check if COLCON_BUNDLE_RETRIES is valid (i.e. 0<) and not too large (i.e. <10)
891+
if (COLCON_BUNDLE_RETRIES<0 || 9<COLCON_BUNDLE_RETRIES){
892+
core.setFailed(`Invalid number of colcon bundle retries. Must be between 0-9 inclusive`);
893+
}
872894
yield setup();
873895
if (ROS_DISTRO == "kinetic" && (GAZEBO_VERSION == "" || GAZEBO_VERSION == "7")) {
874896
GAZEBO_VERSION = "7";

robomaker-sample-app-ci/src/aws-robomaker-sample-application-ci.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ const WORKSPACE_DIRECTORY = core.getInput('workspace-dir');
1212
const GENERATE_SOURCES = core.getInput('generate-sources');
1313
let PACKAGES = "none"
1414
const ROS_ENV_VARIABLES: any = {};
15+
const COLCON_BUNDLE_RETRIES = Number.parseInt(core.getInput('colcon-bundle-retries'), 10);
16+
const MINIMUM_BACKOFF_TIME_SECONDS = 32; // delay for the first retry in seconds
17+
const MAXIMUM_BACKOFF_TIME_SECONDS = 128; // maximum delay for a retry in seconds
18+
19+
function delay(ms: number) {
20+
return new Promise( resolve => setTimeout(resolve, ms) );
21+
}
1522

1623
async function loadROSEnvVariables() {
1724
const options = {
@@ -184,7 +191,6 @@ async function prepare_sources() {
184191
async function build() {
185192
try {
186193
await exec.exec("rosdep", ["install", "--from-paths", ".", "--ignore-src", "-r", "-y", "--rosdistro", ROS_DISTRO], getWorkingDirExecOptions());
187-
188194
console.log(`Building the following packages: ${PACKAGES}`);
189195
await exec.exec("colcon", ["build", "--build-base", "build", "--install-base", "install"], getWorkingDirExecOptions());
190196
} catch (error) {
@@ -193,13 +199,25 @@ async function build() {
193199
}
194200

195201
async function bundle() {
196-
try {
197-
const bundleFilename = path.basename(WORKSPACE_DIRECTORY);
198-
await exec.exec("colcon", ["bundle", "--build-base", "build", "--install-base", "install", "--bundle-base", "bundle"], getWorkingDirExecOptions());
199-
await exec.exec("mv", ["bundle/output.tar", `../${bundleFilename}.tar`], getWorkingDirExecOptions());
200-
await exec.exec("rm", ["-rf", "bundle"], getWorkingDirExecOptions()); // github actions have been failing with no disk space
201-
} catch (error) {
202-
core.setFailed(error.message);
202+
let delay_ms = 1000 * MINIMUM_BACKOFF_TIME_SECONDS;
203+
// indexed from 0 because COLCON_BUNDLE_RETRIES is the number of retries AFTER the initial try
204+
for (let i = 0; i <= COLCON_BUNDLE_RETRIES; i++) {
205+
try {
206+
const bundleFilename = path.basename(WORKSPACE_DIRECTORY);
207+
await exec.exec("colcon", ["bundle", "--build-base", "build", "--install-base", "install", "--bundle-base", "bundle"], getWorkingDirExecOptions());
208+
await exec.exec("mv", ["bundle/output.tar", `../${bundleFilename}.tar`], getWorkingDirExecOptions());
209+
await exec.exec("rm", ["-rf", "bundle"], getWorkingDirExecOptions()); // github actions have been failing with no disk space
210+
break; // break if colcon bundle passes
211+
} catch (error) {
212+
await exec.exec("rm", ["-rf", "bundle"], getWorkingDirExecOptions()); // remove erred bundle assets
213+
if (i == COLCON_BUNDLE_RETRIES){
214+
core.setFailed(error.message); // set action to Failed if the colcon bundle fails even after COLCON_BUNDLE_RETRIES number of retries
215+
break;
216+
}
217+
console.log(`Colcon bundle failed.. retrying in ${delay_ms} milliseconds`);
218+
await delay(delay_ms); // wait for next retry per the current exponential backoff delay
219+
delay_ms = Math.min(delay_ms * 2, MAXIMUM_BACKOFF_TIME_SECONDS); // double the delay for the next retry, truncate if required
220+
}
203221
}
204222
}
205223

@@ -208,6 +226,12 @@ async function run() {
208226
console.log(`GAZEBO_VERSION: ${GAZEBO_VERSION}`);
209227
console.log(`WORKSPACE_DIRECTORY: ${WORKSPACE_DIRECTORY}`);
210228
console.log(`GENERATE_SOURCES: ${GENERATE_SOURCES}`);
229+
console.log(`COLCON_BUNDLE_RETRIES: ${COLCON_BUNDLE_RETRIES}`);
230+
231+
// check if COLCON_BUNDLE_RETRIES is valid (i.e. 0<) and not too large (i.e. <10)
232+
if (COLCON_BUNDLE_RETRIES<0 || 9<COLCON_BUNDLE_RETRIES){
233+
core.setFailed(`Invalid number of colcon bundle retries. Must be between 0-9 inclusive`);
234+
}
211235

212236
await setup();
213237
if (ROS_DISTRO == "kinetic" && (GAZEBO_VERSION == "" || GAZEBO_VERSION == "7")) {

0 commit comments

Comments
 (0)