diff --git a/Jenkinsfile b/Jenkinsfile index 4f293248..14ee607a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -34,6 +34,10 @@ pipeline { defaultValue: true, description: 'Attempt a build with docs in this run? (Note: corresponding tools are required in the build environment)', name: 'DO_BUILD_DOCS') + booleanParam ( + defaultValue: false, + description: 'Publish as an archive a "dist" tarball from a build with docs in this run? (Note: corresponding tools are required in the build environment; enabling this enforces DO_BUILD_DOCS too)', + name: 'DO_DIST_DOCS') booleanParam ( defaultValue: true, description: 'Attempt "make check" in this run?', @@ -62,6 +66,10 @@ pipeline { defaultValue: true, description: 'Require that there are no files not discovered changed/untracked via .gitignore after builds and tests?', name: 'REQUIRE_GOOD_GITIGNORE') + string ( + defaultValue: "30", + description: 'When running tests, use this timeout (in minutes; be sure to leave enough for double-job of a distcheck too)', + name: 'USE_TEST_TIMEOUT') booleanParam ( defaultValue: true, description: 'When using temporary subdirs in build/test workspaces, wipe them after successful builds?', @@ -73,20 +81,11 @@ pipeline { // Note: your Jenkins setup may benefit from similar setup on side of agents: // PATH="/usr/lib64/ccache:/usr/lib/ccache:/usr/bin:/bin:${PATH}" stages { - stage ('cppcheck') { - when { expression { return ( params.DO_CPPCHECK ) } } - steps { - dir("tmp") { - deleteDir() - } - sh 'cppcheck --std=c++11 --enable=all --inconclusive --xml --xml-version=2 . 2>cppcheck.xml' - archiveArtifacts artifacts: '**/cppcheck.xml' - sh 'rm -f cppcheck.xml' - } - } stage ('prepare') { steps { dir("tmp") { + sh 'if [ -s Makefile ]; then make -k distclean || true ; fi' + sh 'chmod -R u+w .' deleteDir() } sh './autogen.sh' @@ -132,12 +131,19 @@ pipeline { } } stage ('build with DOCS') { - when { expression { return ( params.DO_BUILD_DOCS ) } } + when { expression { return ( params.DO_BUILD_DOCS || params.DO_DIST_DOCS ) } } steps { dir("tmp/build-DOCS") { deleteDir() unstash 'prepped' sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; ./configure --enable-drafts=yes --with-docs=yes' + script { + if ( params.DO_DIST_DOCS ) { + sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; make dist-gzip || exit ; DISTFILE="`ls -1tc *.tar.gz | head -1`" && [ -n "$DISTFILE" ] && [ -s "$DISTFILE" ] || exit ; mv -f "$DISTFILE" __dist.tar.gz' + archiveArtifacts artifacts: '__dist.tar.gz' + sh "rm -f __dist.tar.gz" + } + } sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; make -k -j4 || make' sh 'echo "Are GitIgnores good after make with docs? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi' stash (name: 'built-docs', includes: '**/*', excludes: '**/cppcheck.xml') @@ -153,14 +159,42 @@ pipeline { } stage ('check') { parallel { + stage ('cppcheck') { + when { expression { return ( params.DO_CPPCHECK ) } } + steps { + dir("tmp/test-cppcheck") { + deleteDir() + unstash 'prepped' + sh 'cppcheck --std=c++11 --enable=all --inconclusive --xml --xml-version=2 . 2>cppcheck.xml' + archiveArtifacts artifacts: '**/cppcheck.xml' + sh 'rm -f cppcheck.xml' + script { + if ( params.DO_CLEANUP_AFTER_BUILD ) { + deleteDir() + } + } + } + } + } stage ('check with DRAFT') { when { expression { return ( params.DO_BUILD_WITH_DRAFT_API && params.DO_TEST_CHECK ) } } steps { dir("tmp/test-check-withDRAFT") { deleteDir() unstash 'built-draft' - timeout (time: 20, unit: 'MINUTES') { + retry(3) { + timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') { + script { + try { sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" check' + } + catch (Exception e) { + sh 'D="`pwd`"; B="`basename "$D"`" ; tar czf test-suite_"$B".tgz `find . -name '*.trs'` `find . -name '*.log'`' + archiveArtifacts artifacts: "**/test-suite*.tgz", allowEmpty: true + throw e + } + } + } } sh 'echo "Are GitIgnores good after make check with drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi' script { @@ -177,8 +211,19 @@ pipeline { dir("tmp/test-check-withoutDRAFT") { deleteDir() unstash 'built-nondraft' - timeout (time: 20, unit: 'MINUTES') { + retry(3) { + timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') { + script { + try { sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" check' + } + catch (Exception e) { + sh 'D="`pwd`"; B="`basename "$D"`" ; tar czf test-suite_"$B".tgz `find . -name '*.trs'` `find . -name '*.log'`' + archiveArtifacts artifacts: "**/test-suite*.tgz", allowEmpty: true + throw e + } + } + } } sh 'echo "Are GitIgnores good after make check without drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi' script { @@ -195,8 +240,19 @@ pipeline { dir("tmp/test-memcheck-withDRAFT") { deleteDir() unstash 'built-draft' - timeout (time: 20, unit: 'MINUTES') { + retry(3) { + timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') { + script { + try { sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" memcheck && exit 0 ; echo "Re-running failed ($?) memcheck with greater verbosity" >&2 ; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" VERBOSE=1 memcheck-verbose' + } + catch (Exception e) { + sh 'D="`pwd`"; B="`basename "$D"`" ; tar czf test-suite_"$B".tgz `find . -name '*.trs'` `find . -name '*.log'`' + archiveArtifacts artifacts: "**/test-suite*.tgz", allowEmpty: true + throw e + } + } + } } sh 'echo "Are GitIgnores good after make memcheck with drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi' script { @@ -213,8 +269,19 @@ pipeline { dir("tmp/test-memcheck-withoutDRAFT") { deleteDir() unstash 'built-nondraft' - timeout (time: 20, unit: 'MINUTES') { + retry(3) { + timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') { + script { + try { sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" memcheck && exit 0 ; echo "Re-running failed ($?) memcheck with greater verbosity" >&2 ; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" VERBOSE=1 memcheck-verbose' + } + catch (Exception e) { + sh 'D="`pwd`"; B="`basename "$D"`" ; tar czf test-suite_"$B".tgz `find . -name '*.trs'` `find . -name '*.log'`' + archiveArtifacts artifacts: "**/test-suite*.tgz", allowEmpty: true + throw e + } + } + } } sh 'echo "Are GitIgnores good after make memcheck without drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi' script { @@ -231,8 +298,19 @@ pipeline { dir("tmp/test-distcheck-withDRAFT") { deleteDir() unstash 'built-draft' - timeout (time: 30, unit: 'MINUTES') { + retry(3) { + timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') { + script { + try { sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; DISTCHECK_CONFIGURE_FLAGS="--enable-drafts=yes --with-docs=no" ; export DISTCHECK_CONFIGURE_FLAGS; make DISTCHECK_CONFIGURE_FLAGS="$DISTCHECK_CONFIGURE_FLAGS" LD_LIBRARY_PATH="$LD_LIBRARY_PATH" distcheck' + } + catch (Exception e) { + sh 'D="`pwd`"; B="`basename "$D"`" ; tar czf test-suite_"$B".tgz `find . -name '*.trs'` `find . -name '*.log'`' + archiveArtifacts artifacts: "**/test-suite*.tgz", allowEmpty: true + throw e + } + } + } } sh 'echo "Are GitIgnores good after make distcheck with drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi' script { @@ -249,8 +327,19 @@ pipeline { dir("tmp/test-distcheck-withoutDRAFT") { deleteDir() unstash 'built-nondraft' - timeout (time: 30, unit: 'MINUTES') { + retry(3) { + timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') { + script { + try { sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; DISTCHECK_CONFIGURE_FLAGS="--enable-drafts=no --with-docs=no" ; export DISTCHECK_CONFIGURE_FLAGS; make DISTCHECK_CONFIGURE_FLAGS="$DISTCHECK_CONFIGURE_FLAGS" LD_LIBRARY_PATH="$LD_LIBRARY_PATH" distcheck' + } + catch (Exception e) { + sh 'D="`pwd`"; B="`basename "$D"`" ; tar czf test-suite_"$B".tgz `find . -name '*.trs'` `find . -name '*.log'`' + archiveArtifacts artifacts: "**/test-suite*.tgz", allowEmpty: true + throw e + } + } + } } sh 'echo "Are GitIgnores good after make distcheck without drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi' script { @@ -267,9 +356,11 @@ pipeline { dir("tmp/test-install-withDRAFT") { deleteDir() unstash 'built-draft' - timeout (time: 20, unit: 'MINUTES') { + retry(3) { + timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') { sh """CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:\${LD_LIBRARY_PATH}"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="\${LD_LIBRARY_PATH}" DESTDIR="${params.USE_TEST_INSTALL_DESTDIR}/withDRAFT" install""" } + } sh """cd "${params.USE_TEST_INSTALL_DESTDIR}/withDRAFT" && find . -ls""" sh 'echo "Are GitIgnores good after make install with drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi' script { @@ -286,9 +377,11 @@ pipeline { dir("tmp/test-install-withoutDRAFT") { deleteDir() unstash 'built-nondraft' - timeout (time: 20, unit: 'MINUTES') { + retry(3) { + timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') { sh """CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:\${LD_LIBRARY_PATH}"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="\${LD_LIBRARY_PATH}" DESTDIR="${params.USE_TEST_INSTALL_DESTDIR}/withoutDRAFT" install""" } + } sh """cd "${params.USE_TEST_INSTALL_DESTDIR}/withoutDRAFT" && find . -ls""" sh 'echo "Are GitIgnores good after make install without drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi' script { @@ -305,9 +398,11 @@ pipeline { dir("tmp/test-install-withDOCS") { deleteDir() unstash 'built-docs' - timeout (time: 20, unit: 'MINUTES') { + retry(3) { + timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') { sh """CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:\${LD_LIBRARY_PATH}"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="\${LD_LIBRARY_PATH}" DESTDIR="${params.USE_TEST_INSTALL_DESTDIR}/withDOCS" install""" } + } sh """cd "${params.USE_TEST_INSTALL_DESTDIR}/withDOCS" && find . -ls""" sh 'echo "Are GitIgnores good after make install with Docs? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi' script { @@ -332,10 +427,13 @@ pipeline { if ( env.BRANCH_NAME =~ myDEPLOY_BRANCH_PATTERN ) { def GIT_URL = sh(returnStdout: true, script: """git remote -v | egrep '^origin' | awk '{print \$2}' | head -1""").trim() def GIT_COMMIT = sh(returnStdout: true, script: 'git rev-parse --verify HEAD').trim() + def DIST_ARCHIVE = "" + if ( params.DO_DIST_DOCS ) { DIST_ARCHIVE = env.BUILD_URL + "artifact/__dist.tar.gz" } build job: "${myDEPLOY_JOB_NAME}", parameters: [ string(name: 'DEPLOY_GIT_URL', value: "${GIT_URL}"), string(name: 'DEPLOY_GIT_BRANCH', value: env.BRANCH_NAME), - string(name: 'DEPLOY_GIT_COMMIT', value: "${GIT_COMMIT}") + string(name: 'DEPLOY_GIT_COMMIT', value: "${GIT_COMMIT}"), + string(name: 'DEPLOY_DIST_ARCHIVE', value: "${DIST_ARCHIVE}") ], quietPeriod: 0, wait: myDEPLOY_REPORT_RESULT, propagate: myDEPLOY_REPORT_RESULT } else { echo "Not deploying because branch '${env.BRANCH_NAME}' did not match filter '${myDEPLOY_BRANCH_PATTERN}'"