From 0ad26262ac155e7d1031a4340e3c54cfb710083d Mon Sep 17 00:00:00 2001 From: Dennis Klein Date: Fri, 5 Mar 2021 02:59:46 +0100 Subject: [PATCH] CI: Migrate to new alfa-ci infrastructure --- CMakeLists.txt | 8 +++ Dart.sh | 133 ---------------------------------------- FairLoggerTest.cmake | 93 +++++++++++++--------------- Jenkinsfile | 76 ++++++++++------------- Jenkinsfile.nightly | 77 ----------------------- test/ci/CMakeLists.txt | 46 ++++++++++++++ test/ci/linux.def.in | 8 +++ test/ci/setup-fedora.sh | 8 +++ test/ci/slurm-submit.sh | 41 +++++++++++++ 9 files changed, 188 insertions(+), 302 deletions(-) delete mode 100755 Dart.sh delete mode 100644 Jenkinsfile.nightly create mode 100644 test/ci/CMakeLists.txt create mode 100644 test/ci/linux.def.in create mode 100755 test/ci/setup-fedora.sh create mode 100755 test/ci/slurm-submit.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index e27a8b9..497dad5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,6 +156,14 @@ if(BUILD_TESTING) endif() ################################################################################ +# Utils ######################################################################## +find_program(BASH bash HINTS "/bin") +find_program(SINGULARITY singularity) +if(BASH AND SINGULARITY) + add_subdirectory(test/ci) +endif() +################################################################################ + # Summary ###################################################################### message(STATUS " ") message(STATUS " ${Cyan}CXX STANDARD${CR} ${BGreen}C++${CMAKE_CXX_STANDARD}${CR} (>= C++${PROJECT_MIN_CXX_STANDARD}, change with ${BMagenta}-DCMAKE_CXX_STANDARD=17${CR})") diff --git a/Dart.sh b/Dart.sh deleted file mode 100755 index 250a599..0000000 --- a/Dart.sh +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/bash - - -function print_example(){ -echo "##################################################################" -echo "# To set the required parameters as source and the build #" -echo "# directory for ctest, the linux flavour and the SIMPATH #" -echo "# put the export commands below to a separate file which is read #" -echo "# during execution and which is defined on the command line. #" -echo "# Set all parameters according to your needs. #" -echo "# LINUX_FLAVOUR should be set to the distribution you are using #" -echo "# eg Debian, SuSe etc. #" -echo "# An additional varibale NCPU can overwrite the default number #" -echo "# of parallel processes used to compile the project. #" -echo "# This can be usefull if one can use a distributed build system #" -echo "# like icecream. #" -echo "# For example #" -echo "#!/bin/bash #" -echo "export LINUX_FLAVOUR= #" -echo "export FAIRSOFT_VERSION= #" -echo "export SIMPATH= #" -echo "export GIT_BRANCH=< master or dev> #" -echo "export BUILDDIR= #" -echo "export SOURCEDIR= #" -echo "#export NCPU=100 #" -echo "##################################################################" -} - -if [ "$#" -lt "2" ]; then - echo "" - echo "-- Error -- Please start script with two parameters" - echo "-- Error -- The first parameter is the ctest model." - echo "-- Error -- Possible arguments are Nightly, Experimental, " - echo "-- Error -- Continuous or Profile." - echo "-- Error -- The second parameter is the file containg the" - echo "-- Error -- Information about the setup at the client" - echo "-- Error -- installation (see example below)." - echo "" - print_example - exit 1 -fi - -# test if a valid ctest model is defined -if [ "$1" == "Experimental" -o "$1" == "Nightly" -o "$1" == "Continuous" -o "$1" == "Profile" -o "$1" == "alfa_ci" ]; then - echo "" -else - echo "-- Error -- This ctest model is not supported." - echo "-- Error -- Possible arguments are Nightly, Experimental, Continuous or Profile." - exit 1 -fi - -# test if the input file exists and execute it -if [ -e "$2" ];then - source $2 -else - echo "-- Error -- Input file does not exist." - echo "-- Error -- Please choose existing input file." - exit 1 -fi - -# set the ctest model to command line parameter -if [ "$1" == "alfa_ci" ]; then - export ctest_model=Experimental -else - export ctest_model=$1 -fi - - -# test for architecture -arch=$(uname -s | tr '[A-Z]' '[a-z]') -chip=$(uname -m | tr '[A-Z]' '[a-z]') - -# extract information about the system and the machine and set -# environment variables used by ctest -SYSTEM=$arch-$chip -if test -z $CXX ; then - if [ "$arch" == "darwin" ]; then - COMPILER=$(clang --version | head -n 1 | cut -d' ' -f1,2,4 | tr -d ' ') - else - COMPILER=gcc$(gcc -dumpversion) - fi -else - COMPILER=$CXX$($CXX -dumpversion) -fi - -if [ "$1" == "alfa_ci" ]; then - export LABEL1=alfa_ci-$COMPILER-FairLogger_$GIT_BRANCH - export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g') -else - export LABEL1=${LINUX_FLAVOUR}-$chip-$COMPILER-FairLogger_$GIT_BRANCH - export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g') -fi - -# get the number of processors -# and information about the host -if [ "$arch" = "linux" ]; -then - if [ "$NCPU" != "" ]; - then - export number_of_processors=$NCPU - else - export number_of_processors=$(cat /proc/cpuinfo | grep processor | wc -l) - fi - if [ -z "$SITE" ]; then - export SITE=$(hostname -f) - if [ -z "$SITE" ]; then - export SITE=$(uname -n) - fi - fi -elif [ "$arch" = "darwin" ]; -then - if [ "$NCPU" != "" ]; - then - export number_of_processors=$NCPU - else - export number_of_processors=$(sysctl -n hw.ncpu) - fi - if [ -z "$SITE" ]; then - export SITE=$(hostname -s) - fi -fi - -echo "************************" -date -echo "LABEL: " $LABEL -echo "SITE: " $SITE -echo "Model: " ${ctest_model} -echo "Nr. of processes: " $number_of_processors -echo "************************" - -cd $SOURCEDIR - -ctest -S FairLoggerTest.cmake -V --VV diff --git a/FairLoggerTest.cmake b/FairLoggerTest.cmake index 297784b..1267f1a 100644 --- a/FairLoggerTest.cmake +++ b/FairLoggerTest.cmake @@ -1,69 +1,62 @@ ################################################################################ -# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH # +# Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH # # # # This software is distributed under the terms of the # # GNU Lesser General Public Licence (LGPL) version 3, # # copied verbatim in the file "LICENSE" # ################################################################################ -Set(CTEST_SOURCE_DIRECTORY $ENV{SOURCEDIR}) -Set(CTEST_BINARY_DIRECTORY $ENV{BUILDDIR}) -Set(CTEST_SITE $ENV{SITE}) -Set(CTEST_BUILD_NAME $ENV{LABEL}) -Set(CTEST_CMAKE_GENERATOR "Unix Makefiles") -Set(CTEST_PROJECT_NAME "FairLogger") -Find_Program(CTEST_GIT_COMMAND NAMES git) -Set(CTEST_UPDATE_COMMAND "${CTEST_GIT_COMMAND}") +cmake_host_system_information(RESULT fqdn QUERY FQDN) -Set(BUILD_COMMAND "make") -Set(CTEST_BUILD_COMMAND "${BUILD_COMMAND} -j$ENV{number_of_processors}") +set(CTEST_SOURCE_DIRECTORY .) +set(CTEST_BINARY_DIRECTORY build) +set(CTEST_CMAKE_GENERATOR "Ninja") +set(CTEST_USE_LAUNCHERS ON) +set(CTEST_CONFIGURATION_TYPE "RelWithDebInfo") -String(TOUPPER $ENV{ctest_model} _Model) -Set(configure_options "-DCMAKE_BUILD_TYPE=${_Model}") +if(NOT NCPUS) + if(ENV{SLURM_CPUS_PER_TASK}) + set(NCPUS $ENV{SLURM_CPUS_PER_TASK}) + else() + include(ProcessorCount) + ProcessorCount(NCPUS) + if(NCPUS EQUAL 0) + set(NCPUS 1) + endif() + endif() +endif() -Set(CTEST_USE_LAUNCHERS 1) -Set(configure_options "${configure_options};-DCTEST_USE_LAUNCHERS=${CTEST_USE_LAUNCHERS}") +if ("$ENV{CTEST_SITE}" STREQUAL "") + set(CTEST_SITE "${fqdn}") +else() + set(CTEST_SITE $ENV{CTEST_SITE}) +endif() -Set(configure_options "${configure_options};-DDISABLE_COLOR=ON") +if ("$ENV{LABEL}" STREQUAL "") + set(CTEST_BUILD_NAME "build") +else() + set(CTEST_BUILD_NAME $ENV{LABEL}) +endif() -Set(EXTRA_FLAGS $ENV{EXTRA_FLAGS}) -If(EXTRA_FLAGS) - Set(configure_options "${configure_options};${EXTRA_FLAGS}") -EndIf() +ctest_start(Continuous) -If($ENV{ctest_model} MATCHES Nightly OR $ENV{ctest_model} MATCHES Profile) +list(APPEND options + "-DDISABLE_COLOR=ON" + "-DUSE_EXTERNAL_FMT=ON" + "-DUSE_BOOST_PRETTY_FUNCTION=ON" + ) +list(JOIN options ";" optionsstr) +ctest_configure(OPTIONS "${optionsstr}") - Find_Program(GCOV_COMMAND gcov) - If(GCOV_COMMAND) - Message("Found GCOV: ${GCOV_COMMAND}") - Set(CTEST_COVERAGE_COMMAND ${GCOV_COMMAND}) - EndIf(GCOV_COMMAND) +ctest_build(FLAGS "-j${NCPUS}") - Set(ENV{ctest_model} Nightly) +ctest_test(BUILD "${CTEST_BINARY_DIRECTORY}" + PARALLEL_LEVEL 1 + SCHEDULE_RANDOM ON + RETURN_VALUE _ctest_test_ret_val) - CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY}) +ctest_submit() -EndIf() - -Ctest_Start($ENV{ctest_model}) - -Ctest_Configure(BUILD "${CTEST_BINARY_DIRECTORY}" - OPTIONS "${configure_options}" - ) - -Ctest_Build(BUILD "${CTEST_BINARY_DIRECTORY}") - -Ctest_Test(BUILD "${CTEST_BINARY_DIRECTORY}" - PARALLEL_LEVEL $ENV{number_of_processors} - RETURN_VALUE _ctest_test_ret_val - ) - -If(GCOV_COMMAND) - Ctest_Coverage(BUILD "${CTEST_BINARY_DIRECTORY}") -EndIf() - -Ctest_Submit() - -if (_ctest_test_ret_val) +if(_ctest_test_ret_val) Message(FATAL_ERROR "Some tests failed.") endif() diff --git a/Jenkinsfile b/Jenkinsfile index dfd0b25..01de8ad 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,51 +1,44 @@ #!groovy -def specToLabel(Map spec) { - return "${spec.os}-${spec.arch}-${spec.compiler}-FairSoft_${spec.fairsoft}" -} - -def jobMatrix(String prefix, List specs, Closure callback) { +def jobMatrix(String prefix, String type, List specs) { def nodes = [:] for (spec in specs) { - def label = specToLabel(spec) - def fairsoft = spec.fairsoft + job = "${spec.os}-${spec.ver}-${spec.arch}-${spec.compiler}" + def label = "${type}/${job}" + def selector = "${spec.os}-${spec.ver}-${spec.arch}" def os = spec.os - def compiler = spec.compiler - nodes["${prefix}/${label}"] = { - node(label) { + def ver = spec.ver + def check = spec.check + + nodes[label] = { + node(selector) { githubNotify(context: "${prefix}/${label}", description: 'Building ...', status: 'PENDING') try { deleteDir() checkout scm - sh """\ - echo "export SIMPATH=\${SIMPATH_PREFIX}${fairsoft}" >> Dart.cfg - echo "export FAIRSOFT_VERSION=${fairsoft}" >> Dart.cfg - """ - if (os =~ /Debian/ && compiler =~ /gcc9/) { - sh '''\ - echo "source /etc/profile.d/modules.sh" >> Dart.cfg - echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg - echo "module load compiler/gcc/9.1.0" >> Dart.cfg - ''' - } - if (os =~ /MacOS/) { - sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=clang++'\" >> Dart.cfg" + def jobscript = 'job.sh' + def ctestcmd = "ctest -S FairLoggerTest.cmake -V --output-on-failure" + sh "echo \"set -e\" >> ${jobscript}" + sh "echo \"export LABEL=\\\"\${JOB_BASE_NAME} ${label}\\\"\" >> ${jobscript}" + if (selector =~ /^macos/) { + sh "echo \"${ctestcmd}\" >> ${jobscript}" + sh "cat ${jobscript}" + sh "bash ${jobscript}" } else { - sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=g++'\" >> Dart.cfg" + def containercmd = "singularity exec -B/shared ${env.SINGULARITY_CONTAINER_ROOT}/fairlogger/${os}.${ver}.sif bash -l -c \\\"${ctestcmd}\\\"" + sh """\ + echo \"echo \\\"*** Job started at .......: \\\$(date -R)\\\"\" >> ${jobscript} + echo \"echo \\\"*** Job ID ...............: \\\${SLURM_JOB_ID}\\\"\" >> ${jobscript} + echo \"echo \\\"*** Compute node .........: \\\$(hostname -f)\\\"\" >> ${jobscript} + echo \"unset http_proxy\" >> ${jobscript} + echo \"unset HTTP_PROXY\" >> ${jobscript} + echo \"${containercmd}\" >> ${jobscript} + """ + sh "cat ${jobscript}" + sh "test/ci/slurm-submit.sh \"FairLogger \${JOB_BASE_NAME} ${label}\" ${jobscript}" } - sh '''\ - echo "export BUILDDIR=$PWD/build" >> Dart.cfg - echo "export SOURCEDIR=$PWD" >> Dart.cfg - echo "export PATH=\\\$SIMPATH/bin:\\\$PATH" >> Dart.cfg - echo "export GIT_BRANCH=$JOB_BASE_NAME" >> Dart.cfg - echo "echo \\\$PATH" >> Dart.cfg - ''' - sh 'cat Dart.cfg' - - callback.call(spec, label) - deleteDir() githubNotify(context: "${prefix}/${label}", description: 'Success', status: 'SUCCESS') } catch (e) { @@ -65,13 +58,12 @@ pipeline{ stage("Run CI Matrix") { steps{ script { - parallel(jobMatrix('alfa-ci/build', [ - [os: 'Debian8', arch: 'x86_64', compiler: 'gcc9.1.0', fairsoft: 'fairmq_dev'], - [os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'], - [os: 'MacOS10.14', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'], - ]) { spec, label -> - sh './Dart.sh alfa_ci Dart.cfg' - }) + def builds = jobMatrix('alfa-ci', 'build', [ + [os: 'fedora', ver: '33', arch: 'x86_64', compiler: 'gcc-10'], + [os: 'macos', ver: '11', arch: 'x86_64', compiler: 'apple-clang-12'], + ]) + + parallel(builds) } } } diff --git a/Jenkinsfile.nightly b/Jenkinsfile.nightly deleted file mode 100644 index 54e316d..0000000 --- a/Jenkinsfile.nightly +++ /dev/null @@ -1,77 +0,0 @@ -#!groovy - -def specToLabel(Map spec) { - return "${spec.os}-${spec.arch}-${spec.compiler}-FairSoft_${spec.fairsoft}" -} - -def buildMatrix(List specs, Closure callback) { - def nodes = [:] - for (spec in specs) { - def label = specToLabel(spec) - def fairsoft = spec.fairsoft - def os = spec.os - def compiler = spec.compiler - nodes[label] = { - node(label) { - try { - deleteDir() - checkout scm - - sh """\ - echo "export SIMPATH=\${SIMPATH_PREFIX}${fairsoft}" >> Dart.cfg - echo "export FAIRSOFT_VERSION=${fairsoft}" >> Dart.cfg - """ - if (os =~ /Debian/ && compiler =~ /gcc9/) { - sh '''\ - echo "source /etc/profile.d/modules.sh" >> Dart.cfg - echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg - echo "module load compiler/gcc/9.1.0" >> Dart.cfg - ''' - } - if (os =~ /MacOS/) { - sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=clang++'\" >> Dart.cfg" - } else { - sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=g++'\" >> Dart.cfg" - } - sh '''\ - echo "export BUILDDIR=$PWD/build" >> Dart.cfg - echo "export SOURCEDIR=$PWD" >> Dart.cfg - echo "export PATH=\\\$SIMPATH/bin:\\\$PATH" >> Dart.cfg - echo "export GIT_BRANCH=dev" >> Dart.cfg - echo "echo \\\$PATH" >> Dart.cfg - ''' - sh 'cat Dart.cfg' - - callback.call(spec, label) - - deleteDir() - } catch (e) { - deleteDir() - throw e - } - } - } - } - return nodes -} - -pipeline{ - agent none - triggers { cron('H 2 * * *') } - stages { - stage("Run Nightly Build/Test Matrix") { - steps{ - script { - parallel(buildMatrix([ - [os: 'Debian8', arch: 'x86_64', compiler: 'gcc9.1.0', fairsoft: 'fairmq_dev'], - [os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'], - [os: 'MacOS10.14', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'], - ]) { spec, label -> - sh './Dart.sh Nightly Dart.cfg' - sh './Dart.sh Profile Dart.cfg' - }) - } - } - } - } -} diff --git a/test/ci/CMakeLists.txt b/test/ci/CMakeLists.txt new file mode 100644 index 0000000..280ddfc --- /dev/null +++ b/test/ci/CMakeLists.txt @@ -0,0 +1,46 @@ +################################################################################ +# Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH # +# # +# This software is distributed under the terms of the # +# GNU Lesser General Public Licence (LGPL) version 3, # +# copied verbatim in the file "LICENSE" # +################################################################################ + +function(container) + cmake_parse_arguments(ARGS "" "OS;VERSION;DOCKER_TAG;PACKAGE_SETUP_SCRIPT" "" ${ARGN}) + + if(ARGS_DOCKER_TAG) + set(DOCKER_TAG ${ARGS_DOCKER_TAG}) + else() + set(DOCKER_TAG "${ARGS_OS}:${ARGS_VERSION}") + endif() + + if(ARGS_PACKAGE_SETUP_SCRIPT) + set(PACKAGE_SETUP_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/${ARGS_PACKAGE_SETUP_SCRIPT}") + else() + set(PACKAGE_SETUP_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/setup-${ARGS_OS}.sh") + endif() + + set(container "${ARGS_OS}.${ARGS_VERSION}") + set(def "${container}.def") + set(log "${container}.log") + set(target "${container}.fairlogger.sif") + + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/linux.def.in" ${def} @ONLY) + + add_custom_command(OUTPUT ${target} + COMMAND ${CMAKE_COMMAND} -E env ${BASH} -c + "${SINGULARITY} build -f -F ${target} ${def} > ${log} 2>&1" + VERBATIM + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Building fairlogger test container ${target}, logging to ${CMAKE_CURRENT_BINARY_DIR}/${log}" + DEPENDS ${PACKAGE_SETUP_SCRIPT} ${bootstrap_cmake_script} + ) + + list(APPEND containers ${target}) + set(containers ${containers} PARENT_SCOPE) +endfunction() + +container(OS fedora VERSION 33) + +add_custom_target(all-containers DEPENDS ${containers}) diff --git a/test/ci/linux.def.in b/test/ci/linux.def.in new file mode 100644 index 0000000..501f89b --- /dev/null +++ b/test/ci/linux.def.in @@ -0,0 +1,8 @@ +Bootstrap: docker +From: @DOCKER_TAG@ + +%files + @PACKAGE_SETUP_SCRIPT@ /setup.sh + +%post + bash /setup.sh diff --git a/test/ci/setup-fedora.sh b/test/ci/setup-fedora.sh new file mode 100755 index 0000000..44f9ff0 --- /dev/null +++ b/test/ci/setup-fedora.sh @@ -0,0 +1,8 @@ +#! /bin/bash + +dnf -y update +dnf -y groupinstall "C Development Tools and Libraries" +dnf -y install binutils boost-devel cmake ca-certificates coreutils diffutils \ + findutils fmt-devel gcc-c++ git hostname ninja-build patch procps python \ + redhat-lsb-core sed tar wget which +dnf -y clean all diff --git a/test/ci/slurm-submit.sh b/test/ci/slurm-submit.sh new file mode 100755 index 0000000..87601b3 --- /dev/null +++ b/test/ci/slurm-submit.sh @@ -0,0 +1,41 @@ +#! /bin/bash + +label="$1" +jobsh="$2" + +if [ -z "$ALFACI_SLURM_CPUS" ] +then + ALFACI_SLURM_CPUS=32 +fi +if [ -z "$ALFACI_SLURM_EXTRA_OPTS" ] +then + ALFACI_SLURM_EXTRA_OPTS="--hint=compute_bound" +fi +if [ -z "$ALFACI_SLURM_TIMEOUT" ] +then + ALFACI_SLURM_TIMEOUT=30 +fi +if [ -z "$ALFACI_SLURM_QUEUE" ] +then + ALFACI_SLURM_QUEUE=main +fi + +echo "*** Slurm request options :" +echo "*** Working directory ..: $PWD" +echo "*** Queue ..............: $ALFACI_SLURM_QUEUE" +echo "*** CPUs ...............: $ALFACI_SLURM_CPUS" +echo "*** Wall Time ..........: $ALFACI_SLURM_TIMEOUT min" +echo "*** Job Name ...........: ${label}" +echo "*** Extra Options ......: ${ALFACI_SLURM_EXTRA_OPTS}" +echo "*** Submitting job at ....: $(date -R)" +( + set -x + srun -p $ALFACI_SLURM_QUEUE -c $ALFACI_SLURM_CPUS -n 1 \ + -t $ALFACI_SLURM_TIMEOUT \ + --job-name="${label}" \ + ${ALFACI_SLURM_EXTRA_OPTS} \ + bash "${jobsh}" +) +retval=$? +echo "*** Exit Code ............: $retval" +exit "$retval"