Skip to content

Commit

Permalink
rework travis utility functions
Browse files Browse the repository at this point in the history
- more modularization
  - travis_run_simple: no folding
  - travis_run_true: folding, timing, accept failures
  - travis_run: folding, timing, not accepting failures
  - travis_run_wait: +timeout
- support hierarchical folds (with custom fold names and titles)
- travis_wait() to wait for a background process to finish
- limit travis_run_wait's timeout to estimated remaining Travis' build time
- filter() and filter-out() utility functions
- further extended unittests for all these utility functions
  • Loading branch information
rhaschke committed Jan 27, 2019
1 parent a483dfe commit f3ac41d
Show file tree
Hide file tree
Showing 7 changed files with 549 additions and 225 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ env:

# Test BEFORE_SCRIPT and ros vs. ros-shadow-fixed
- ROS_DISTRO=kinetic ROS_REPO=ros BEFORE_SCRIPT="echo first && false; echo second > /dev/null; echo Testing on $ROS_DISTRO"
- ROS_DISTRO=kinetic ROS_REPO=ros-shadow-fixed BEFORE_DOCKER_SCRIPT="wget -nv www.google.com; exit 0"
- ROS_DISTRO=kinetic ROS_REPO=ros-shadow-fixed BEFORE_DOCKER_SCRIPT="wget -nv www.google.com; return 1"

# Build MoveIt repo
- ROS_DISTRO=melodic ROS_REPO=ros-shadow-fixed TEST=clang-tidy-fix
Expand Down
38 changes: 23 additions & 15 deletions check_clang_format.sh
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
# Software License Agreement - BSD License
#
# Author: Dave Coleman

travis_fold start clang.format "Running clang-format check"
travis_run_simple --display "cd to repository source: $CI_SOURCE_PATH" cd $CI_SOURCE_PATH

# Install Dependencies
travis_run apt-get -qq install -y clang-format-3.9

# Change to source directory.
cd $CI_SOURCE_PATH

# This directory can have its own .clang-format config file but if not, MoveIt's will be provided
# Ensure that a .clang-format config file is present, if not download from MoveIt
if [ ! -f .clang-format ]; then
travis_run wget -nv "https://raw.githubusercontent.com/ros-planning/moveit/$ROS_DISTRO-devel/.clang-format"
fi

# Run clang-format
travis_time_start moveit_ci.clang-format "Running clang-format" # start fold
find . -name '*.h' -or -name '*.hpp' -or -name '*.cpp' | xargs clang-format-3.9 -i -style=file
travis_time_end # end fold
cmd="find . -name '*.h' -or -name '*.hpp' -or -name '*.cpp' | xargs clang-format-3.9 -i -style=file"
travis_run --display "Running clang-format${ANSI_RESET}\\n$cmd" "$cmd"

# Make sure no changes have occured in repo
if ! git diff-index --quiet HEAD --; then
# changes
echo -e "\033[31;1mclang-format test failed: The following changes are required to comply to rules:\033[0m"
git --no-pager diff
exit 1 # error
fi
# Check for changes in repo
travis_have_fixes
result=$?

# Finish fold before printing result summary
travis_fold end clang.format

echo -e "\033[32;1mPassed clang-format check\033[0m"
if [ $result -eq 1 ] ; then
echo -e "${ANSI_GREEN}Passed clang-format check${ANSI_RESET}"
else
echo -e "${ANSI_RED}clang-format check failed. Open fold for details.${ANSI_RESET}"
echo -e "Run the following command to fix these issues:\\n$cmd"
exit 2
fi
47 changes: 19 additions & 28 deletions check_clang_tidy.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
# Change to source directory.
pushd $CI_SOURCE_PATH > /dev/null
travis_fold start clang.tidy "Running clang-tidy check"
travis_run_impl --display "cd to repository source: $CI_SOURCE_PATH" cd $CI_SOURCE_PATH

# Find run-clang-tidy script: Xenial and Bionic install them with different names
export RUN_CLANG_TIDY=$(ls -1 /usr/bin/run-clang-tidy* | head -1)


# Run clang-tidy for all packages in CI_SOURCE_PATH
SOURCE_PKGS=$(catkin_topological_order $CI_SOURCE_PATH --only-names 2> /dev/null)

echo -e "\033[33;1mRunning clang-tidy check\033[0m"
TAINTED_PKGS=""
COUNTER=0
(
for file in $(find $CATKIN_WS/build -name compile_commands.json) ; do
Expand All @@ -17,31 +16,23 @@ COUNTER=0
[[ "$SOURCE_PKGS" =~ (^|[[:space:]])$PKG($|[[:space:]]) ]] && continue

let "COUNTER += 1"
travis_time_start clang-tidy.$COUNTER "Processing $PKG"
# Pipe the very verbose output of clang-tidy to /dev/null
$RUN_CLANG_TIDY -fix -p $(dirname $file) > /dev/null 2>&1
travis_time_end
done
) &
cmd_pid=$! # main cmd PID

# Use travis_jigger to generate some '.' outputs to convince Travis, we are not stuck.
travis_jigger $cmd_pid 10 "clang-tidy" &
jigger_pid=$!
travis_fold start clang.tidy.$COUNTER "${ANSI_THIN}Processing $PKG"

# Wait for main command to finish
wait $cmd_pid 2>/dev/null
# Stop travis_jigger in any case
kill $jigger_pid 2> /dev/null && wait $! 2> /dev/null
cmd="$RUN_CLANG_TIDY -fix -p $(dirname $file)"
# Suppress the very verbose output of clang-tidy!
travis_run_impl --timing --display "$cmd" "$cmd > /dev/null 2>&1"
travis_have_fixes && TAINTED_PKGS="$TAINTED_PKGS\\n$PKG"
travis_fold end clang.tidy.$COUNTER
done
) & # run in background to allow timeout monitoring
travis_wait $! $(travis_timeout)

# Finish fold before printing result summary
travis_fold end clang.tidy

# Make sure no changes have occured in repo
if ! git diff-index --quiet HEAD --; then
# changes
echo -e "\033[31;1mclang-tidy test failed: The following changes are required to comply to rules:\033[0m"
git --no-pager diff
exit 1
if [ -z "$TAINTED_PKGS" ] ; then
echo -e "${ANSI_GREEN}Passed clang-tidy check${ANSI_RESET}"
else
echo -e "${ANSI_RED}clang-tidy check failed for the following packages:\\n${ANSI_RESET}$TAINTED_PKGS"
exit 2
fi

echo -e "\033[32;1mPassed clang-tidy check\033[0m"
popd > /dev/null
104 changes: 58 additions & 46 deletions travis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,21 @@ export CI_SOURCE_PATH=$(pwd) # The repository code in this pull request that we
export CI_PARENT_DIR=.moveit_ci # This is the folder name that is used in downstream repositories in order to point to this repo.
export REPOSITORY_NAME=${PWD##*/}
export CATKIN_WS=/root/ws_moveit
echo "---"
echo -e "\033[33;1mTesting branch '$TRAVIS_BRANCH' of '$REPOSITORY_NAME' on ROS '$ROS_DISTRO'\033[0m"
# Travis' default timeout for open source projects is 50 mins
# If your project has a larger timeout, specify this variable in your .travis.yml file!
MOVEIT_CI_TRAVIS_TIMEOUT=${MOVEIT_CI_TRAVIS_TIMEOUT:-45} # 50min minus safety margin

# Helper functions
source ${CI_SOURCE_PATH}/$CI_PARENT_DIR/util.sh

# Run all CI in a Docker container
if ! [ "$IN_DOCKER" ]; then
echo -e "${ANSI_YELLOW}Testing branch '$TRAVIS_BRANCH' of '$REPOSITORY_NAME' on ROS '$ROS_DISTRO'${ANSI_RESET}"
# Run BEFORE_DOCKER_SCRIPT
if [ "${BEFORE_DOCKER_SCRIPT// }" != "" ]; then
travis_run $BEFORE_DOCKER_SCRIPT
travis_run --title "${ANSI_BOLD}Running BEFORE_DOCKER_SCRIPT${ANSI_THIN}" $BEFORE_DOCKER_SCRIPT
result=$?
test $result -ne 0 && echo -e "${ANSI_RED}Script failed with return value: $result. Aborting.${ANSI_RESET}" && exit 2
fi

# Choose the correct CI container to use
Expand All @@ -36,14 +40,14 @@ if ! [ "$IN_DOCKER" ]; then
export DOCKER_IMAGE=moveit/moveit:$ROS_DISTRO-ci
;;
esac
echo "Starting Docker image: $DOCKER_IMAGE"
echo -e "${ANSI_BOLD}Starting Docker image: $DOCKER_IMAGE${ANSI_RESET}"

# Pull first to allow us to hide console output
docker pull $DOCKER_IMAGE > /dev/null
travis_run docker pull $DOCKER_IMAGE

# Start Docker container
docker run \
-e TRAVIS \
-e MOVEIT_CI_TRAVIS_TIMEOUT \
-e ROS_REPO \
-e ROS_DISTRO \
-e BEFORE_SCRIPT \
Expand All @@ -64,11 +68,12 @@ if ! [ "$IN_DOCKER" ]; then
/bin/bash -c "cd /root/$REPOSITORY_NAME; source .moveit_ci/travis.sh;"
return_value=$?

if [ $return_value -eq 0 ]; then
echo -e "\033[32;1mTravis script finished successfully\033[0m"
else
echo -e "\033[31;1mTravis script finished with errors\033[0m"
fi
echo
case $return_value in
0) echo -e "${ANSI_GREEN}Travis script finished successfully.${ANSI_RESET}" ;;
124) echo -e "${ANSI_YELLOW}Timed out, but try again! Having saved cache results, Travis will probably succeed next time.${ANSI_RESET}\\n" ;;
*) echo -e "${ANSI_RED}Travis script finished with errors.${ANSI_RESET}" ;;
esac
exit $return_value
fi

Expand All @@ -78,8 +83,9 @@ echo "Inside Docker container"
# Define CC/CXX defaults and print compiler version info
export CC=${CC:-cc}
export CXX=${CXX:-c++}
$CXX --version
travis_run --title "${ANSI_RESET}$CXX compiler info" $CXX --version

travis_fold start update "Updating system packages"
# Update the sources
travis_run apt-get -qq update

Expand All @@ -90,6 +96,7 @@ travis_run apt-get -qq dist-upgrade
for t in $TEST; do
case "$t" in
clang-format)
travis_fold end update
source ${CI_SOURCE_PATH}/$CI_PARENT_DIR/check_clang_format.sh || exit 1
exit 0 # This runs as an independent job, do not run regular travis test
;;
Expand All @@ -106,7 +113,7 @@ for t in $TEST; do
CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
;;
*)
echo "Unknown TEST: $t"
echo -e "${ANSI_RED}Unknown TEST: $t${ANSI_RESET}"
exit 1
;;
esac
Expand All @@ -122,18 +129,23 @@ fi
travis_run apt-get -qq install ccache
export PATH=/usr/lib/ccache:$PATH

# Setup rosdep - note: "rosdep init" is already setup in base ROS Docker image
travis_run rosdep update

travis_fold end update

# Install and run xvfb to allow for X11-based unittests on DISPLAY :99
travis_fold start xvfb "Starting virtual X11 server to allow for X11-based unit tests"
travis_run apt-get -qq install xvfb mesa-utils
Xvfb -screen 0 640x480x24 :99 &
travis_run "Xvfb -screen 0 640x480x24 :99 &"
export DISPLAY=:99.0
travis_run_true glxinfo

# Setup rosdep - note: "rosdep init" is already setup in base ROS Docker image
travis_run rosdep update
travis_fold end xvfb

# Create workspace
travis_run mkdir -p $CATKIN_WS/src
travis_run cd $CATKIN_WS/src
travis_fold start catkin.ws "Setting up catkin workspace"
travis_run_simple mkdir -p $CATKIN_WS/src
travis_run_simple cd $CATKIN_WS/src

# Install dependencies necessary to run build using .rosinstall files
if [ ! "$UPSTREAM_WORKSPACE" ]; then
Expand All @@ -149,7 +161,7 @@ case "$UPSTREAM_WORKSPACE" in
( # parentheses ensure that IFS is automatically reset
IFS=',' # Multiple URLs can be given separated by comma.
for rosinstall in $UPSTREAM_WORKSPACE; do
travis_run wstool merge -k $rosinstall
(IFS=' '; travis_run wstool merge -k $rosinstall)
done
)
;;
Expand All @@ -159,8 +171,8 @@ case "$UPSTREAM_WORKSPACE" in
# install (maybe unreleased version) dependencies from source
travis_run wstool merge file://$CI_SOURCE_PATH/$UPSTREAM_WORKSPACE
else
echo "Didn't find rosinstall file: $CI_SOURCE_PATH/$UPSTREAM_WORKSPACE. Aborting"
exit 1
echo -e "${ANSI_RED}Didn't find rosinstall file: $CI_SOURCE_PATH/$UPSTREAM_WORKSPACE. Aborting.${ANSI_RESET}"
exit 2
fi
;;
esac
Expand All @@ -170,67 +182,67 @@ if [ -e .rosinstall ]; then
# ensure that the downstream is not in .rosinstall
travis_run_true wstool rm $REPOSITORY_NAME
# perform shallow checkout: only possible with wstool init
travis_run mv .rosinstall rosinstall
travis_run_simple mv .rosinstall rosinstall
travis_run cat rosinstall
travis_run wstool init --shallow . rosinstall
fi

# link in the repo we are testing
travis_run ln -s $CI_SOURCE_PATH .
travis_run_simple --title "${ANSI_RESET}Symlinking to-be-tested repo $CI_SOURCE_PATH into catkin workspace" \
ln -s $CI_SOURCE_PATH .

# Debug: see the files in current folder
travis_run ls -a
travis_run --title "${ANSI_RESET}List files catkin workspace's source folder" ls -a

# Run BEFORE_SCRIPT
if [ "${BEFORE_SCRIPT// }" != "" ]; then
travis_run $BEFORE_SCRIPT
travis_run --title "${ANSI_BOLD}Running BEFORE_SCRIPT${ANSI_THIN}" $BEFORE_SCRIPT
result=$?
test $result -ne 0 && echo -e "${ANSI_RED}Script failed with return value: $result. Aborting.${ANSI_RESET}" && exit 2
fi

# Install source-based package dependencies
travis_run rosdep install -y -q -n --from-paths . --ignore-src --rosdistro $ROS_DISTRO

# Change to base of workspace
travis_run cd $CATKIN_WS
travis_run_simple cd $CATKIN_WS
travis_fold end catkin.ws

echo -e "\033[33;1mBuilding Workspace\033[0m"
echo -e "${ANSI_GREEN}Building Workspace${ANSI_RESET}"
# Configure catkin
travis_run catkin config --extend /opt/ros/$ROS_DISTRO --install --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS_RELEASE="-O3" $CMAKE_ARGS --
travis_run --title "catkin config $CMAKE_ARGS" catkin config --extend /opt/ros/$ROS_DISTRO --install --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS_RELEASE="-O3" $CMAKE_ARGS --

# Console output fix for: "WARNING: Could not encode unicode characters"
export PYTHONIOENCODING=UTF-8

# For a command that doesn’t produce output for more than 10 minutes, prefix it with travis_run_wait
travis_run_wait 60 catkin build --no-status --summarize || exit 1
travis_run_wait 60 --title "catkin build" catkin build --no-status --summarize

travis_run ccache -s
travis_run --title "ccache statistics" ccache -s

# Source the new built workspace
travis_run source install/setup.bash;
echo -e "${ANSI_GREEN}Testing Workspace${ANSI_RESET}"
travis_run_simple --title "Sourcing newly built install space" source install/setup.bash

# Choose which packages to run tests on
echo -e "\033[33;1mTesting Workspace\033[0m"
echo "Test blacklist: $TEST_BLACKLIST"
TEST_PKGS=$(catkin_topological_order $CATKIN_WS/src --only-names 2> /dev/null | grep -Fvxf <(echo "$TEST_BLACKLIST" | tr ' ;,' '\n') | tr '\n' ' ')
TEST_PKGS=$(filter-out "$TEST_BLACKLIST" $(catkin_topological_order $CATKIN_WS/src --only-names))

if [ -n "$TEST_PKGS" ]; then
# Fix formatting of list of packages to work correctly with Travis
IFS=' ' read -r -a TEST_PKGS <<< "$TEST_PKGS"
echo "Test packages: ${TEST_PKGS[@]}"
TEST_PKGS="--no-deps ${TEST_PKGS[@]}"

# Run catkin package tests
travis_run_wait catkin build --no-status --summarize --make-args tests -- $TEST_PKGS
echo "Test packages: $TEST_PKGS"
TEST_PKGS="--no-deps $TEST_PKGS"

# Run non-catkin package tests
travis_run_wait catkin build --catkin-make-args run_tests -- --no-status --summarize $TEST_PKGS
travis_run_wait --title "catkin build tests" catkin build --no-status --summarize --make-args tests -- $TEST_PKGS
travis_run_wait --title "catkin run_tests" catkin build --catkin-make-args run_tests -- --no-status --summarize $TEST_PKGS

# Show failed tests
travis_fold start test.results "catkin_test_results"
for file in $(catkin_test_results | grep "\.xml:" | cut -d ":" -f1); do
travis_run cat $file
travis_run --display "Test log of $file" cat $file
done
travis_fold end test.results

# Show test results summary and throw error if necessary
travis_run catkin_test_results
catkin_test_results || exit 2
else
echo "No packages to test."
fi
Expand Down
35 changes: 35 additions & 0 deletions travis_functions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# from https://github.com/travis-ci/travis-build/blob/master/lib/travis/build/bash/travis_cmd.bash

export ANSI_RED="\033[31;1m"
export ANSI_GREEN="\033[32;1m"
export ANSI_YELLOW="\033[33;1m"
export ANSI_RESET="\033[0m"
export ANSI_CLEAR="\033[0K"

travis_nanoseconds() {
local cmd='date'
local format='+%s%N'

if hash gdate >/dev/null 2>&1; then
cmd='gdate'
elif [[ "${TRAVIS_OS_NAME}" == osx ]]; then
format='+%s000000000'
fi

"${cmd}" -u "${format}"
}
travis_time_start() {
TRAVIS_TIMER_ID="$(printf %08x $((RANDOM * RANDOM)))"
TRAVIS_TIMER_START_TIME="$(travis_nanoseconds)"
export TRAVIS_TIMER_ID TRAVIS_TIMER_START_TIME
echo -en "travis_time:start:$TRAVIS_TIMER_ID\\r${ANSI_CLEAR}"
}
travis_time_finish() {
local result="${?}"
local travis_timer_end_time
travis_timer_end_time="$(travis_nanoseconds)"
local duration
duration="$((travis_timer_end_time - TRAVIS_TIMER_START_TIME))"
echo -en "travis_time:end:${TRAVIS_TIMER_ID}:start=${TRAVIS_TIMER_START_TIME},finish=${travis_timer_end_time},duration=${duration}\\r${ANSI_CLEAR}"
return "${result}"
}
Loading

0 comments on commit f3ac41d

Please sign in to comment.