From 40252075f3ef8f11b225f8fb9a4c7ce1b392e8f5 Mon Sep 17 00:00:00 2001 From: Daniel Agar <daniel@agar.ca> Date: Tue, 5 Feb 2019 15:42:34 -0500 Subject: [PATCH] Jenkins add SITL tests coverage pipeline --- .ci/Jenkinsfile-SITL_tests | 173 +++-------------------- .ci/Jenkinsfile-SITL_tests_coverage | 208 ++++++++++++++++++++++++++++ Jenkinsfile | 22 +++ 3 files changed, 252 insertions(+), 151 deletions(-) create mode 100644 .ci/Jenkinsfile-SITL_tests_coverage diff --git a/.ci/Jenkinsfile-SITL_tests b/.ci/Jenkinsfile-SITL_tests index ed52225c57..352e1b4c9d 100644 --- a/.ci/Jenkinsfile-SITL_tests +++ b/.ci/Jenkinsfile-SITL_tests @@ -3,81 +3,32 @@ pipeline { agent none - parameters { - choice( - name: 'PX4_CMAKE_BUILD_TYPE', - choices: ['RelWithDebInfo', 'Coverage', 'AddressSanitizer', 'UndefinedBehaviorSanitizer'], - description: "CMake build type" - ) - } - stages { stage('Build') { - agent { docker { image 'px4io/px4-dev-ros-kinetic:2018-09-11' args '-e CCACHE_BASEDIR=$WORKSPACE -v ${CCACHE_DIR}:${CCACHE_DIR}:rw -e HOME=$WORKSPACE --cap-add SYS_PTRACE --entrypoint=""' } } - - stages { - - stage('build px4') { - steps { - sh('export') - sh('make distclean') - sh "ccache -z" - sh "git fetch --tags" - sh('make px4_sitl_default') - sh "ccache -s" - } - } - - stage('stash build for coverage') { - steps { - stash includes: 'build/**/*', name: 'build_sitl_coverage', useDefaultExcludes: false - } - when { - environment name: 'PX4_CMAKE_BUILD_TYPE', value: 'Coverage' - } - } - - stage('unit tests') { - steps { - sh 'export' - sh 'make px4_sitl_test test_results_junit' - junit 'build/px4_sitl_test/JUnitTestResults.xml' - } - } - - stage('build sitl_gazebo') { - steps { - sh 'export' - sh "ccache -z" - sh('make px4_sitl_default sitl_gazebo') - sh "ccache -s" - } - } - - stage('package') { - steps { - sh 'export' - sh('make px4_sitl_default package') - stash(name: "px4_sitl_package", includes: "build/px4_sitl_default/*.bz2") - archiveArtifacts(artifacts: "build/px4_sitl_default/*.bz2", fingerprint: true, onlyIfSuccessful: true) - } - } - + steps { + sh 'export' + sh 'make distclean' + sh 'ccache -z' + sh 'git fetch --tags' + sh 'make px4_sitl_default' + sh 'make px4_sitl_default sitl_gazebo' + sh 'make px4_sitl_default package' + sh 'ccache -s' + stash(name: "px4_sitl_package", includes: "build/px4_sitl_default/*.bz2") + archiveArtifacts(artifacts: "build/px4_sitl_default/*.bz2", fingerprint: true, onlyIfSuccessful: true) } - post { always { sh 'make distclean' } } - } // stage Build stage('ROS Tests') { @@ -141,64 +92,11 @@ pipeline { } // steps } // stage ROS Tests - stage('Coverage') { - parallel { - - stage('code coverage (python)') { - agent { - docker { - image 'px4io/px4-dev-base:2019-01-26' - args '-e CCACHE_BASEDIR=$WORKSPACE -v ${CCACHE_DIR}:${CCACHE_DIR}:rw --cap-add SYS_PTRACE' - } - } - steps { - sh 'export' - sh 'make distclean' - sh 'make python_coverage' - withCredentials([string(credentialsId: 'FIRMWARE_CODECOV_TOKEN', variable: 'CODECOV_TOKEN')]) { - sh 'curl -s https://codecov.io/bash | bash -s - -F python' - } - - sh 'make distclean' - } - - when { - environment name: 'PX4_CMAKE_BUILD_TYPE', value: 'Coverage' - } - } - - stage('unit tests') { - agent { - docker { - image 'px4io/px4-dev-base:2019-01-26' - args '-e CCACHE_BASEDIR=$WORKSPACE -v ${CCACHE_DIR}:${CCACHE_DIR}:rw --cap-add SYS_PTRACE' - } - } - steps { - sh 'export' - sh 'make distclean' - sh 'make px4_sitl_test test_results_junit' - withCredentials([string(credentialsId: 'FIRMWARE_CODECOV_TOKEN', variable: 'CODECOV_TOKEN')]) { - sh 'curl -s https://codecov.io/bash | bash -s - -F unittest' - } - sh 'make distclean' - } - when { - environment name: 'PX4_CMAKE_BUILD_TYPE', value: 'Coverage' - } - } - - } // parallel - } // stage Coverage - } //stages environment { - ASAN_OPTIONS = 'detect_stack_use_after_return=1:check_initialization_order=1' - UBSAN_OPTIONS = 'print_stacktrace=1' CCACHE_DIR = '/tmp/ccache' CI = true - CTEST_OUTPUT_ON_FAILURE = 1 } options { @@ -216,11 +114,6 @@ def createTestNode(Map test_def) { def test_ok = true sh('export') - if (env.PX4_CMAKE_BUILD_TYPE == 'Coverage') { - checkout(scm) - unstash 'build_sitl_coverage' - } - unstash('px4_sitl_package') sh('tar -xjpvf build/px4_sitl_default/px4-px4_sitl_default*.bz2') @@ -235,41 +128,19 @@ def createTestNode(Map test_def) { } // log analysis - if (env.PX4_CMAKE_BUILD_TYPE == 'Coverage') { - withCredentials([string(credentialsId: 'FIRMWARE_CODECOV_TOKEN', variable: 'CODECOV_TOKEN')]) { - sh 'curl -s https://codecov.io/bash | bash -s - -F sitl_mission_${STAGE_NAME}' - - // process log data (with python code coverage) - try { - sh('coverage run -p px4-px4_sitl_default*/px4/Tools/ecl_ekf/process_logdata_ekf.py .ros/log/*/*.ulg') - } catch (exc) { - // save log analysis artifacts for debugging - archiveArtifacts(allowEmptyArchive: false, artifacts: '.ros/**/*.pdf, .ros/**/*.csv') - // FIXME: don't let the script to fail the build - // test_ok = false - } - - // upload log to flight review (https://logs.px4.io/) with python code coverage - sh('coverage run -p px4-px4_sitl_default*/px4/Tools/upload_log.py -q --description "${JOB_NAME}: ${STAGE_NAME}" --feedback "${JOB_NAME} ${CHANGE_TITLE} ${CHANGE_URL}" --source CI .ros/log/*/*.ulg') - - // upload python code coverage to codecov.io - sh 'curl -s https://codecov.io/bash | bash -s - -X gcov -F sitl_python_${STAGE_NAME}' - } - } else { // non code coverage - // process ekf log data - try { - sh('px4-px4_sitl_default*/px4/Tools/ecl_ekf/process_logdata_ekf.py .ros/log/*/*.ulg') - } catch (exc) { - // save log analysis artifacts for debugging - archiveArtifacts(allowEmptyArchive: false, artifacts: '.ros/**/*.pdf, .ros/**/*.csv') - // FIXME: don't let the script to fail the build - // test_ok = false - } - - // upload log to flight review (https://logs.px4.io/) - sh('px4-px4_sitl_default*/px4/Tools/upload_log.py -q --description "${JOB_NAME}: ${STAGE_NAME}" --feedback "${JOB_NAME} ${CHANGE_TITLE} ${CHANGE_URL}" --source CI .ros/log/*/*.ulg') + // process ekf log data + try { + sh('px4-px4_sitl_default*/px4/Tools/ecl_ekf/process_logdata_ekf.py .ros/log/*/*.ulg') + } catch (exc) { + // save log analysis artifacts for debugging + archiveArtifacts(allowEmptyArchive: false, artifacts: '.ros/**/*.pdf, .ros/**/*.csv') + // FIXME: don't let the script to fail the build + // test_ok = false } + // upload log to flight review (https://logs.px4.io/) + sh('px4-px4_sitl_default*/px4/Tools/upload_log.py -q --description "${JOB_NAME}: ${STAGE_NAME}" --feedback "${JOB_NAME} ${CHANGE_TITLE} ${CHANGE_URL}" --source CI .ros/log/*/*.ulg') + if (!test_ok) { error('ROS Test failed') } diff --git a/.ci/Jenkinsfile-SITL_tests_coverage b/.ci/Jenkinsfile-SITL_tests_coverage new file mode 100644 index 0000000000..3eb7fe09a7 --- /dev/null +++ b/.ci/Jenkinsfile-SITL_tests_coverage @@ -0,0 +1,208 @@ +#!/usr/bin/env groovy + +pipeline { + agent none + + stages { + + stage('Build') { + agent { + docker { + image 'px4io/px4-dev-ros-kinetic:2018-09-11' + args '-e CCACHE_BASEDIR=$WORKSPACE -v ${CCACHE_DIR}:${CCACHE_DIR}:rw -e HOME=$WORKSPACE --cap-add SYS_PTRACE --entrypoint=""' + } + } + steps { + sh 'export' + sh 'make distclean' + sh 'ccache -z' + sh 'git fetch --tags' + sh 'make px4_sitl_default' + stash includes: 'build/**/*', name: 'build_sitl_coverage', useDefaultExcludes: false + sh 'make px4_sitl_default sitl_gazebo' + sh 'make px4_sitl_default package' + sh 'ccache -s' + stash(name: "px4_sitl_package", includes: "build/px4_sitl_default/*.bz2") + archiveArtifacts(artifacts: "build/px4_sitl_default/*.bz2", fingerprint: true, onlyIfSuccessful: true) + } + post { + always { + sh 'make distclean' + } + } + } // stage Build + + stage('ROS Tests') { + steps { + script { + def missions = [ + [ + name: "FW", + test: "mavros_posix_test_mission.test", + mission: "FW_mission_1", + vehicle: "plane" + ], + + [ + name: "MC_box", + test: "mavros_posix_test_mission.test", + mission: "MC_mission_box", + vehicle: "iris" + ], + [ + name: "MC_offboard_att", + test: "mavros_posix_tests_offboard_attctl.test", + mission: "", + vehicle: "iris" + ], + [ + name: "MC_offboard_pos", + test: "mavros_posix_tests_offboard_posctl.test", + mission: "", + vehicle: "iris" + ], + + [ + name: "VTOL_standard", + test: "mavros_posix_test_mission.test", + mission: "VTOL_mission_1", + vehicle: "standard_vtol" + ], + [ + name: "VTOL_tailsitter", + test: "mavros_posix_test_mission.test", + mission: "VTOL_mission_1", + vehicle: "tailsitter" + ], + [ + name: "VTOL_tiltrotor", + test: "mavros_posix_test_mission.test", + mission: "VTOL_mission_1", + vehicle: "tiltrotor" + ], + + ] + + def test_nodes = [:] + for (def i = 0; i < missions.size(); i++) { + test_nodes.put(missions[i].name, createTestNode(missions[i])) + } + + parallel test_nodes + } // script + } // steps + } // stage ROS Tests + + stage('Coverage') { + parallel { + + stage('code coverage (python)') { + agent { + docker { + image 'px4io/px4-dev-base:2019-01-26' + args '-e CCACHE_BASEDIR=$WORKSPACE -v ${CCACHE_DIR}:${CCACHE_DIR}:rw --cap-add SYS_PTRACE' + } + } + steps { + sh 'export' + sh 'make distclean' + sh 'make python_coverage' + withCredentials([string(credentialsId: 'FIRMWARE_CODECOV_TOKEN', variable: 'CODECOV_TOKEN')]) { + sh 'curl -s https://codecov.io/bash | bash -s - -F python' + } + + sh 'make distclean' + } + } + + stage('unit tests') { + agent { + docker { + image 'px4io/px4-dev-base:2019-01-26' + args '-e CCACHE_BASEDIR=$WORKSPACE -v ${CCACHE_DIR}:${CCACHE_DIR}:rw --cap-add SYS_PTRACE' + } + } + steps { + sh 'export' + sh 'make distclean' + sh 'make px4_sitl_test test_results_junit' + withCredentials([string(credentialsId: 'FIRMWARE_CODECOV_TOKEN', variable: 'CODECOV_TOKEN')]) { + sh 'curl -s https://codecov.io/bash | bash -s - -F unittest' + } + sh 'make distclean' + } + } + + } // parallel + } // stage Coverage + + } //stages + + environment { + CCACHE_DIR = '/tmp/ccache' + CI = true + CTEST_OUTPUT_ON_FAILURE = 1 + PX4_CMAKE_BUILD_TYPE = 'Coverage' + } + + options { + buildDiscarder(logRotator(numToKeepStr: '2', artifactDaysToKeepStr: '14')) + timeout(time: 60, unit: 'MINUTES') + } +} // pipeline + +def createTestNode(Map test_def) { + return { + node { + cleanWs() + docker.image("px4io/px4-dev-ros-kinetic:2018-09-11").inside('-e HOME=${WORKSPACE} --cap-add SYS_PTRACE --entrypoint=""') { + stage(test_def.name) { + def test_ok = true + sh('export') + + checkout(scm) + unstash 'build_sitl_coverage' + + unstash('px4_sitl_package') + sh('tar -xjpvf build/px4_sitl_default/px4-px4_sitl_default*.bz2') + + // run test + try { + sh('px4-px4_sitl_default*/px4/test/rostest_px4_run.sh ' + test_def.test + ' mission:=' + test_def.mission + ' vehicle:=' + test_def.vehicle) + + } catch (exc) { + // save all test artifacts for debugging + archiveArtifacts(allowEmptyArchive: false, artifacts: '.ros/**/*.ulg, .ros/**/rosunit-*.xml, .ros/**/rostest-*.log') + test_ok = false + } + + // log analysis + withCredentials([string(credentialsId: 'FIRMWARE_CODECOV_TOKEN', variable: 'CODECOV_TOKEN')]) { + sh 'curl -s https://codecov.io/bash | bash -s - -F sitl_mission_${STAGE_NAME}' + + // process log data (with python code coverage) + try { + sh('coverage run -p px4-px4_sitl_default*/px4/Tools/ecl_ekf/process_logdata_ekf.py .ros/log/*/*.ulg') + } catch (exc) { + // save log analysis artifacts for debugging + archiveArtifacts(allowEmptyArchive: false, artifacts: '.ros/**/*.pdf, .ros/**/*.csv') + // FIXME: don't let the script to fail the build + // test_ok = false + } + + // upload log to flight review (https://logs.px4.io/) with python code coverage + sh('coverage run -p px4-px4_sitl_default*/px4/Tools/upload_log.py -q --description "${JOB_NAME}: ${STAGE_NAME}" --feedback "${JOB_NAME} ${CHANGE_TITLE} ${CHANGE_URL}" --source CI .ros/log/*/*.ulg') + + // upload python code coverage to codecov.io + sh 'curl -s https://codecov.io/bash | bash -s - -X gcov -F sitl_python_${STAGE_NAME}' + } + + if (!test_ok) { + error('ROS Test failed') + } + } // stage + cleanWs() + } // docker.image + } // node + } // return +} // createTestNode diff --git a/Jenkinsfile b/Jenkinsfile index 1f39bd5254..bf255aaeb8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -141,6 +141,28 @@ pipeline { } } + stage('SITL unit tests') { + agent { + docker { + image 'px4io/px4-dev-base:2019-02-03' + args '-e CCACHE_BASEDIR=$WORKSPACE -v ${CCACHE_DIR}:${CCACHE_DIR}:rw' + } + } + steps { + sh 'export' + sh 'make distclean' + sh 'ccache -z' + sh 'git fetch --tags' + sh 'make tests' + sh 'ccache -s' + } + post { + always { + sh 'make distclean' + } + } + } + stage('Clang analyzer') { agent { docker { -- GitLab