|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# See docs at https://github.com/cppalliance/ci-automation/blob/master/scripts/docs/README.md |
| 4 | + |
| 5 | +set -e |
| 6 | + |
| 7 | +scriptname="lcov-jenkins-gcc-13.sh" |
| 8 | +echo "Starting $scriptname" |
| 9 | + |
| 10 | +# READ IN COMMAND-LINE OPTIONS |
| 11 | + |
| 12 | +TEMP=$(getopt -o h:: --long help::,skip-gcovr::,skip-genhtml::,skip-diff-report::,only-gcovr:: -- "$@") |
| 13 | +eval set -- "$TEMP" |
| 14 | + |
| 15 | +# extract options and their arguments into variables. |
| 16 | +while true ; do |
| 17 | + case "$1" in |
| 18 | + -h|--help) |
| 19 | + helpmessage=""" |
| 20 | +usage: $scriptname [-h] [--skip-gcovr] [--skip-genhtml] [--skip-diff-report] [--only-gcovr] |
| 21 | +
|
| 22 | +Builds library documentation. |
| 23 | +
|
| 24 | +optional arguments: |
| 25 | + -h, --help Show this help message and exit |
| 26 | + --skip-gcovr Don't run gcovr |
| 27 | + --skip-genhtml Don't run genhtml |
| 28 | + --skip-diff-report Don't run the diff-report |
| 29 | + --only-gcovr Only run the main gcovr report, which is the same as multiple |
| 30 | + skip options. |
| 31 | + If the goal is to run gcovr, this is the preferred method |
| 32 | + since this flag can be modified to skip other steps later. |
| 33 | +""" |
| 34 | + |
| 35 | + echo "" |
| 36 | + echo "$helpmessage" ; |
| 37 | + echo "" |
| 38 | + exit 0 |
| 39 | + ;; |
| 40 | + --skip-gcovr) |
| 41 | + skipgcovroption="yes" ; shift 2 ;; |
| 42 | + --skip-genhtml) |
| 43 | + skipgenhtmloption="yes" ; shift 2 ;; |
| 44 | + --skip-diff-report) |
| 45 | + skipdiffreportoption="yes" ; shift 2 ;; |
| 46 | + --only-gcovr) |
| 47 | + skipdiffreportoption="yes" ; skipgenhtmloption="yes" ; shift 2 ;; |
| 48 | + --) shift ; break ;; |
| 49 | + *) echo "Internal error!" ; exit 1 ;; |
| 50 | + esac |
| 51 | +done |
| 52 | + |
| 53 | +timestamp=$(date +"%Y-%m-%d-%H-%M-%S") |
| 54 | + |
| 55 | +env |
| 56 | + |
| 57 | +if [ -z "${REPONAME}" ]; then |
| 58 | + echo "Please set the env variable REPONAME" |
| 59 | + exit 1 |
| 60 | +fi |
| 61 | + |
| 62 | +if [ -z "${ORGANIZATION}" ]; then |
| 63 | + echo "Please set the env variable ORGANIZATION" |
| 64 | + exit 1 |
| 65 | +fi |
| 66 | + |
| 67 | +if [ "${BOOST_BRANCH_COVERAGE}" = "0" ]; then |
| 68 | + export LCOV_BRANCH_COVERAGE=0 |
| 69 | + export GCOVR_BRANCH_COVERAGE=0 |
| 70 | +elif [ "${BOOST_BRANCH_COVERAGE}" = "1" ]; then |
| 71 | + export LCOV_BRANCH_COVERAGE=1 |
| 72 | + export GCOVR_BRANCH_COVERAGE=1 |
| 73 | +fi |
| 74 | + |
| 75 | +# Default of GCOVR_BRANCH_COVERAGE is 0 -> no branch coverage report |
| 76 | +# That may be overwritten by BOOST_BRANCH_COVERAGE, above. |
| 77 | +: "${GCOVR_BRANCH_COVERAGE:=0}" |
| 78 | + |
| 79 | +GCOVR_EXTRA_OPTIONS=() |
| 80 | +if [ "${GCOVR_BRANCH_COVERAGE}" = "0" ]; then |
| 81 | + GCOVR_EXTRA_OPTIONS=(--exclude-branches-by-pattern='.*') |
| 82 | +fi |
| 83 | + |
| 84 | +# export USER=$(whoami) |
| 85 | +# echo "USER is ${USER}" |
| 86 | + |
| 87 | +# these packages are already installed on containers. |
| 88 | +sudo apt-get update |
| 89 | +sudo apt-get install -y python3-pip sudo git curl jq |
| 90 | + |
| 91 | +# codecov.sh installs perl packages also |
| 92 | +# sudo apt-get install -y libcapture-tiny-perl libdatetime-perl libdatetime-format-dateparse-perl |
| 93 | +sudo apt-get install -y libdatetime-format-dateparse-perl |
| 94 | + |
| 95 | +# expecting a venv to already exist in /opt/venv. |
| 96 | +export pythonvirtenvpath=/opt/venv |
| 97 | +if [ -f ${pythonvirtenvpath}/bin/activate ]; then |
| 98 | + # shellcheck source=/dev/null |
| 99 | + source ${pythonvirtenvpath}/bin/activate |
| 100 | +fi |
| 101 | + |
| 102 | +# pip install --upgrade gcovr==8.6 || true |
| 103 | +# pip install --upgrade git+https://github.com/Spacetown/gcovr.git@05cbbc6f769da3671a3f659ad99198bac4d62dee || true |
| 104 | +pip install --upgrade git+https://github.com/gcovr/gcovr.git@8dc1762283bbc30044f12e998b78e7f762e0f849 || true |
| 105 | + |
| 106 | +gcovr --version |
| 107 | + |
| 108 | +export B2_TOOLSET="gcc-13" |
| 109 | +export LCOV_VERSION="v2.3" |
| 110 | +export LCOV_OPTIONS="--ignore-errors mismatch" |
| 111 | + |
| 112 | +export REPO_NAME=${ORGANIZATION}/${REPONAME} |
| 113 | +export PATH=~/.local/bin:/usr/local/bin:$PATH |
| 114 | +export BOOST_CI_CODECOV_IO_UPLOAD="skip" |
| 115 | + |
| 116 | +# lcov will be present later |
| 117 | +export PATH=/tmp/lcov/bin:$PATH |
| 118 | +# command -v lcov |
| 119 | +# lcov --version |
| 120 | + |
| 121 | +collect_coverage () { |
| 122 | + |
| 123 | + git clone https://github.com/boostorg/boost-ci.git boost-ci-cloned --depth 1 |
| 124 | + cp -prf boost-ci-cloned/ci . |
| 125 | + rm -rf boost-ci-cloned |
| 126 | + |
| 127 | + SELF=$(basename "$REPO_NAME") |
| 128 | + export SELF |
| 129 | + BOOST_CI_SRC_FOLDER=$(pwd) |
| 130 | + export BOOST_CI_SRC_FOLDER |
| 131 | + |
| 132 | + echo "In collect_coverage. Running common_install.sh" |
| 133 | + # shellcheck source=/dev/null |
| 134 | + . ./ci/common_install.sh |
| 135 | + |
| 136 | + # Formatted such as "cppalliance/buffers cppalliance/http-proto" |
| 137 | + for EXTRA_LIB in ${EXTRA_BOOST_LIBRARIES}; do |
| 138 | + EXTRA_LIB_REPO=$(basename "$EXTRA_LIB") |
| 139 | + if [ ! -d "$BOOST_ROOT/libs/${EXTRA_LIB_REPO}" ]; then |
| 140 | + pushd "$BOOST_ROOT/libs" |
| 141 | + git clone "https://github.com/${EXTRA_LIB}" -b "$BOOST_BRANCH" --depth 1 |
| 142 | + popd |
| 143 | + fi |
| 144 | + done |
| 145 | + |
| 146 | + echo "In collect_coverage. Running codecov.sh" |
| 147 | + cd "$BOOST_ROOT/libs/$SELF" |
| 148 | + ci/travis/codecov.sh |
| 149 | + |
| 150 | + cd "$BOOST_CI_SRC_FOLDER" |
| 151 | + |
| 152 | + # lcov --ignore-errors unused --remove coverage.info -o coverage_filtered.info '*/test/*' '*/extra/*' '*/example/*' |
| 153 | + lcov --ignore-errors unused --extract coverage.info "*/boost/$SELF/*" "*/$SELF/src/*" -o coverage_filtered.info |
| 154 | + sed "s|${BOOST_ROOT}/boost/$SELF|${BOOST_ROOT}/libs/$SELF/include/boost/$SELF|g" coverage_filtered.info > coverage_remapped.info |
| 155 | + |
| 156 | +} |
| 157 | + |
| 158 | +collect_coverage |
| 159 | + |
| 160 | +# Now the tracefile is coverage_filtered.info |
| 161 | +if [ ! "$skipgenhtmloption" = "yes" ]; then |
| 162 | + genhtml --show-navigation -o genhtml coverage_remapped.info |
| 163 | +fi |
| 164 | + |
| 165 | +######################### |
| 166 | +# |
| 167 | +# gcovr |
| 168 | +# |
| 169 | +######################### |
| 170 | + |
| 171 | +if [ ! "$skipgcovroption" = "yes" ]; then |
| 172 | + |
| 173 | + GCOVRFILTER1=".*/boost/$SELF/.*" |
| 174 | + GCOVRFILTER2=".*/$SELF/src/.*" |
| 175 | + if [ -d "gcovr" ]; then |
| 176 | + rm -r gcovr |
| 177 | + fi |
| 178 | + mkdir gcovr |
| 179 | + cd ../boost-root |
| 180 | + if [ ! -d ci-automation ]; then |
| 181 | + git clone -b master https://github.com/cppalliance/ci-automation |
| 182 | + cd ci-automation |
| 183 | + git branch -vv || true |
| 184 | + cd .. |
| 185 | + else |
| 186 | + cd ci-automation |
| 187 | + git pull || true |
| 188 | + git branch -vv || true |
| 189 | + cd .. |
| 190 | + fi |
| 191 | + |
| 192 | + outputlocation="$BOOST_CI_SRC_FOLDER/gcovr" |
| 193 | + |
| 194 | + # First pass, output json |
| 195 | + gcovr "${GCOVR_EXTRA_OPTIONS[@]}" --merge-mode-functions separate --sort uncovered-percent --html-title "$REPONAME" --merge-lines --exclude-unreachable-branches --exclude-throw-branches --exclude '.*/test/.*' --exclude '.*/extra/.*' --exclude '.*/example/.*' --exclude '.*/examples/.*' --filter "$GCOVRFILTER1" --filter "$GCOVRFILTER2" --html --output "${outputlocation}/index.html" --json-summary-pretty --json-summary "${outputlocation}/summary.json" --json "${outputlocation}/coverage-raw.json" |
| 196 | + |
| 197 | + # Fix paths |
| 198 | + python3 "ci-automation/scripts/fix_paths.py" \ |
| 199 | + "$outputlocation/coverage-raw.json" \ |
| 200 | + "$outputlocation/coverage-fixed.json" \ |
| 201 | + --repo "$REPONAME" |
| 202 | + |
| 203 | + # Create symlinks so gcovr can find source files at repo-relative paths |
| 204 | + ln -sfn "$BOOST_CI_SRC_FOLDER/include" "$(pwd)/include" 2>/dev/null || true |
| 205 | + ln -sfn "$BOOST_CI_SRC_FOLDER/src" "$(pwd)/src" 2>/dev/null || true |
| 206 | + |
| 207 | + # Second pass, generate html |
| 208 | + gcovr "${GCOVR_EXTRA_OPTIONS[@]}" -a "$outputlocation/coverage-fixed.json" \ |
| 209 | + --merge-mode-functions separate \ |
| 210 | + --merge-lines \ |
| 211 | + --html-nested \ |
| 212 | + --no-html-self-contained \ |
| 213 | + --html-template-dir=ci-automation/gcovr-templates/html \ |
| 214 | + --html-title "$REPONAME" \ |
| 215 | + --html \ |
| 216 | + --output "$outputlocation/index.html" \ |
| 217 | + --json-summary-pretty \ |
| 218 | + --json-summary "$outputlocation/summary.json" |
| 219 | + |
| 220 | + # Second pass, generate html |
| 221 | + # Let's remove many options/flags from the second pass. See above. |
| 222 | + # gcovr "${GCOVR_EXTRA_OPTIONS[@]}" -a "$outputlocation/coverage-fixed.json" --merge-mode-functions separate --sort uncovered-percent --html-nested --html-template-dir=ci-automation/gcovr-templates/html --html-title "$REPONAME" --merge-lines --exclude-unreachable-branches --exclude-throw-branches --exclude '.*/test/.*' --exclude '.*/extra/.*' --exclude '.*/example/.*' --exclude '.*/examples/.*' --html --output "${outputlocation}/index.html" --json-summary-pretty --json-summary "$outputlocation/summary.json" |
| 223 | + |
| 224 | + ls -al "${outputlocation}" |
| 225 | + |
| 226 | + # Copy font files to output directory |
| 227 | + cp ci-automation/gcovr-templates/html/*.woff2 "$outputlocation/" |
| 228 | + |
| 229 | + # Generate tree.json for sidebar navigation |
| 230 | + python3 "ci-automation/scripts/gcovr_build_tree.py" "${outputlocation}" |
| 231 | + |
| 232 | + # Generate coverage badges |
| 233 | + python3 "ci-automation/scripts/generate_badges.py" "$outputlocation" --json "$outputlocation/summary.json" |
| 234 | + |
| 235 | +fi |
| 236 | + |
| 237 | +######################################################################### |
| 238 | +# |
| 239 | +# The following section is to generate a diff-report |
| 240 | +# |
| 241 | +######################################################################### |
| 242 | + |
| 243 | +if [ ! "$skipdiffreportoption" = "yes" ]; then |
| 244 | + |
| 245 | + ######################### |
| 246 | + # |
| 247 | + # Collect coverage again the same way on the target branch, usually develop |
| 248 | + # |
| 249 | + ######################### |
| 250 | + |
| 251 | + # preparation: |
| 252 | + |
| 253 | + # "$CHANGE_TARGET" is a variable from multibranch-pipeline. |
| 254 | + TARGET_BRANCH="${CHANGE_TARGET:-develop}" |
| 255 | + |
| 256 | + cd "$BOOST_CI_SRC_FOLDER" |
| 257 | + BOOST_CI_SRC_FOLDER_ORIG=$BOOST_CI_SRC_FOLDER |
| 258 | + rm -rf ../boost-root |
| 259 | + cd .. |
| 260 | + # It was possible to have the new folder be named $SELF. |
| 261 | + # But just to be extra careful, choose another name such as |
| 262 | + ADIRNAME=${SELF}-target-branch-iteration |
| 263 | + if [ -d "$ADIRNAME" ]; then |
| 264 | + mv "$ADIRNAME" "$ADIRNAME.bck.$timestamp" |
| 265 | + fi |
| 266 | + git clone -b "$TARGET_BRANCH" "https://github.com/$ORGANIZATION/$SELF" "$ADIRNAME" |
| 267 | + cd "$ADIRNAME" |
| 268 | + # The "new" BOOST_CI_SRC_FOLDER: |
| 269 | + BOOST_CI_SRC_FOLDER=$(pwd) |
| 270 | + export BOOST_CI_SRC_FOLDER |
| 271 | + BOOST_CI_SRC_FOLDER_TARGET=$(pwd) |
| 272 | + export BOOST_CI_SRC_FOLDER_TARGET |
| 273 | + |
| 274 | + # done with prep, now everything is the same as before |
| 275 | + |
| 276 | + collect_coverage |
| 277 | + |
| 278 | + # diff coverage report generation |
| 279 | + |
| 280 | + BOOST_CI_SRC_FOLDER=$BOOST_CI_SRC_FOLDER_ORIG |
| 281 | + cd "$BOOST_CI_SRC_FOLDER/.." |
| 282 | + |
| 283 | + if [ ! -d diff-coverage-report ]; then |
| 284 | + git clone https://github.com/grisumbras/diff-coverage-report |
| 285 | + else |
| 286 | + cd diff-coverage-report |
| 287 | + git pull || true |
| 288 | + cd .. |
| 289 | + fi |
| 290 | + |
| 291 | + diff -Nru0 --minimal -x '.git' -x '*.info' -x genhtml -x gcovr -x diff-report \ |
| 292 | + "$BOOST_CI_SRC_FOLDER_TARGET" "$BOOST_CI_SRC_FOLDER_ORIG" | tee difference |
| 293 | + |
| 294 | + diff-coverage-report/diff-coverage-report.py -D difference \ |
| 295 | + -O "$BOOST_CI_SRC_FOLDER/diff-report" \ |
| 296 | + -B "$BOOST_CI_SRC_FOLDER_TARGET/coverage_filtered.info" \ |
| 297 | + -T "$BOOST_CI_SRC_FOLDER_ORIG/coverage_filtered.info" \ |
| 298 | + -S "$BOOST_CI_SRC_FOLDER_ORIG" \ |
| 299 | + -P "$BOOST_CI_SRC_FOLDER_TARGET" "$BOOST_CI_SRC_FOLDER_ORIG" \ |
| 300 | + "$BOOST_ROOT/libs/$SELF" "$BOOST_CI_SRC_FOLDER_ORIG" \ |
| 301 | + "$BOOST_ROOT/boost" "$BOOST_CI_SRC_FOLDER_ORIG/include/boost" |
| 302 | + |
| 303 | + # In the event that diff-coverage-report.py doesn't run, ensure |
| 304 | + # an empty directory exists anyway to upload to S3. |
| 305 | + mkdir -p "$BOOST_CI_SRC_FOLDER/diff-report" |
| 306 | + touch "$BOOST_CI_SRC_FOLDER/diff-report/test.txt" |
| 307 | + |
| 308 | + # Done, return everything back. |
| 309 | + cd "$BOOST_CI_SRC_FOLDER" |
| 310 | + |
| 311 | +fi |
0 commit comments