ci-driver.sh (13819B)
1 #!/bin/bash 2 3 #### 4 # DO NOT EDIT THIS FILE IN MASTER. ONLY EDIT IT IN THE OLDEST SUPPORTED 5 # BRANCH, THEN MERGE FORWARD. 6 #### 7 8 # This script is used to build Tor for continuous integration. It should 9 # be kept the same for all supported Tor versions. 10 # 11 # It's subject to the regular Tor license; see LICENSE for copying 12 # information. 13 14 set -o errexit 15 set -o nounset 16 17 # Options for this script. 18 DEBUG_CI="${DEBUG_CI:-no}" 19 COLOR_CI="${COLOR_CI:-yes}" 20 21 # Options for which CI system this is. 22 ON_GITLAB="${ON_GITLAB:-yes}" 23 24 # Options for things we usually won't want to skip. 25 RUN_STAGE_CONFIGURE="${RUN_STAGE_CONFIGURE:-yes}" 26 RUN_STAGE_BUILD="${RUN_STAGE_BUILD:-yes}" 27 RUN_STAGE_TEST="${RUN_STAGE_TEST:-yes}" 28 29 # Options for how to build Tor. All should be yes/no. 30 FATAL_WARNINGS="${FATAL_WARNINGS:-yes}" 31 HARDENING="${HARDENING:-no}" 32 COVERAGE="${COVERAGE:-no}" 33 DOXYGEN="${DOXYGEN:-no}" 34 ASCIIDOC="${ASCIIDOC:-no}" 35 TRACING="${TRACING:-no}" 36 ALL_BUGS_ARE_FATAL="${ALL_BUGS_ARE_FATAL:-no}" 37 DISABLE_DIRAUTH="${DISABLE_DIRAUTH:-no}" 38 DISABLE_RELAY="${DISABLE_RELAY:-no}" 39 NSS="${NSS:-no}" 40 GPL="${GPL:-no}" 41 42 # Options for which tests to run. All should be yes/no. 43 CHECK="${CHECK:-yes}" 44 STEM="${STEM:-no}" 45 CHUTNEY="${CHUTNEY:-no}" 46 DISTCHECK="${DISTCHECK:-no}" 47 48 # Options for where the Tor source is. 49 CI_SRCDIR="${CI_SRCDIR:-.}" 50 51 # Options for where to build. 52 CI_BUILDDIR="${CI_BUILDDIR:-./build}" 53 54 # How parallel should we run make? 55 MAKE_J_OPT="${MAKE_J_OPT:--j4}" 56 # Should we stop after make finds an error? 57 MAKE_K_OPT="${MAKE_K_OPT:--k}" 58 59 # What make target should we use for chutney? 60 CHUTNEY_MAKE_TARGET="${CHUTNEY_MAKE_TARGET:-test-network}" 61 62 # Where do we find our additional testing tools? 63 CHUTNEY_PATH="${CHUTNEY_PATH:-}" 64 STEM_PATH="${STEM_PATH:-}" 65 66 ############################################################################# 67 # Preliminary functions. 68 69 # Terminal coloring/emphasis stuff. 70 if [[ "${COLOR_CI}" == "yes" ]]; then 71 T_RED=$(tput setaf 1 || true) 72 T_GREEN=$(tput setaf 2 || true) 73 T_YELLOW=$(tput setaf 3 || true) 74 T_DIM=$(tput dim || true) 75 T_BOLD=$(tput bold || true) 76 T_RESET=$(tput sgr0 || true) 77 else 78 T_RED= 79 T_GREEN= 80 T_YELLOW= 81 T_DIM= 82 T_BOLD= 83 T_RESET= 84 fi 85 86 function error() 87 { 88 echo "${T_BOLD}${T_RED}ERROR:${T_RESET} $*" 1>&2 89 } 90 91 function die() 92 { 93 echo "${T_BOLD}${T_RED}FATAL ERROR:${T_RESET} $*" 1>&2 94 exit 1 95 } 96 97 function skipping() 98 { 99 echo "${T_BOLD}${T_YELLOW}Skipping $*${T_RESET}" 100 } 101 102 function hooray() 103 { 104 echo "${T_BOLD}${T_GREEN}$*${T_RESET}" 105 } 106 107 if [[ "${DEBUG_CI}" == "yes" ]]; then 108 function debug() 109 { 110 echo "${T_DIM}(debug): $*${T_RESET}" 111 } 112 else 113 function debug() 114 { 115 : 116 } 117 fi 118 119 function yes_or_no() 120 { 121 local varname="$1" 122 local value="${!varname}" 123 debug "${varname} is ${value}" 124 if [[ "${value}" != 'yes' && "${value}" != 'no' ]]; then 125 die "${varname} must be 'yes' or 'no'. Got unexpected value ${value}". 126 fi 127 } 128 129 function incompatible() 130 { 131 local varname1="$1" 132 local varname2="$2" 133 local val1="${!varname1}" 134 local val2="${!varname2}" 135 if [[ "${val1}" = 'yes' && "${val2}" = 'yes' ]]; then 136 die "Cannot set both ${varname1} and ${varname2}: they are incompatible." 137 fi 138 } 139 140 function runcmd() 141 { 142 echo "${T_BOLD}\$ $*${T_RESET}" 143 if ! "$@" ; then 144 error "command '$*' has failed." 145 return 1 146 fi 147 } 148 149 function show_git_version() 150 { 151 local tool="$1" 152 local dir="$2" 153 local version="?????" 154 if [[ -e "$dir/.git" ]] ; then 155 version=$(cd "$dir"; git rev-parse HEAD) 156 fi 157 echo "${T_BOLD}$tool:${T_RESET} $version" 158 } 159 160 if [[ "${ON_GITLAB}" == "yes" ]]; then 161 function start_section() 162 { 163 local label="$1" 164 local stamp 165 stamp=$(date +%s) 166 printf "section_start:%s:%s\r\e[0K" "$stamp" "$label" 167 echo "${T_BOLD}${T_GREEN}========= $label${T_RESET}" 168 } 169 function end_section() 170 { 171 local label="$1" 172 local stamp 173 stamp=$(date +%s) 174 printf "section_end:%s:%s\r\e[0K" "$stamp" "$label" 175 } 176 else 177 function start_section() 178 { 179 true 180 } 181 function end_section() 182 { 183 true 184 } 185 fi 186 187 ############################################################################# 188 # Validate inputs. 189 190 debug Validating inputs 191 yes_or_no DEBUG_CI 192 yes_or_no COLOR_CI 193 yes_or_no ON_GITLAB 194 yes_or_no FATAL_WARNINGS 195 yes_or_no HARDENING 196 yes_or_no COVERAGE 197 yes_or_no DOXYGEN 198 yes_or_no ASCIIDOC 199 yes_or_no TRACING 200 yes_or_no ALL_BUGS_ARE_FATAL 201 yes_or_no DISABLE_DIRAUTH 202 yes_or_no DISABLE_RELAY 203 yes_or_no NSS 204 yes_or_no GPL 205 206 yes_or_no RUN_STAGE_CONFIGURE 207 yes_or_no RUN_STAGE_BUILD 208 yes_or_no RUN_STAGE_TEST 209 210 yes_or_no CHECK 211 yes_or_no STEM 212 yes_or_no DISTCHECK 213 214 incompatible DISTCHECK CHECK 215 incompatible DISTCHECK CHUTNEY 216 incompatible DISTCHECK STEM 217 incompatible DISTCHECK COVERAGE 218 incompatible DISTCHECK DOXYGEN 219 220 if [[ "${CHUTNEY}" = yes && "${CHUTNEY_PATH}" = '' ]] ; then 221 die "CHUTNEY is set to 'yes', but CHUTNEY_PATH was not specified." 222 fi 223 224 if [[ "${STEM}" = yes && "${STEM_PATH}" = '' ]] ; then 225 die "STEM is set to 'yes', but STEM_PATH was not specified." 226 fi 227 228 ############################################################################# 229 # Set up options for make and configure. 230 231 make_options=() 232 if [[ "$MAKE_J_OPT" != "" ]]; then 233 make_options+=("$MAKE_J_OPT") 234 fi 235 if [[ "$MAKE_K_OPT" != "" ]]; then 236 make_options+=("$MAKE_K_OPT") 237 fi 238 239 configure_options=() 240 if [[ "$FATAL_WARNINGS" == "yes" ]]; then 241 configure_options+=("--enable-fatal-warnings") 242 fi 243 if [[ "$HARDENING" == "yes" ]]; then 244 configure_options+=("--enable-fragile-hardening") 245 fi 246 if [[ "$COVERAGE" == "yes" ]]; then 247 configure_options+=("--enable-coverage") 248 fi 249 if [[ "$ASCIIDOC" != "yes" ]]; then 250 configure_options+=("--disable-asciidoc") 251 fi 252 if [[ "$TRACING" == "yes" ]]; then 253 configure_options+=("--enable-tracing-instrumentation-lttng") 254 fi 255 if [[ "$ALL_BUGS_ARE_FATAL" == "yes" ]]; then 256 configure_options+=("--enable-all-bugs-are-fatal") 257 fi 258 if [[ "$DISABLE_DIRAUTH" == "yes" ]]; then 259 configure_options+=("--disable-module-dirauth") 260 fi 261 if [[ "$DISABLE_RELAY" == "yes" ]]; then 262 configure_options+=("--disable-module-relay") 263 fi 264 if [[ "$NSS" == "yes" ]]; then 265 configure_options+=("--enable-nss") 266 fi 267 if [[ "$GPL" == "yes" ]]; then 268 configure_options+=("--enable-gpl") 269 fi 270 271 ############################################################################# 272 # Tell the user about our versions of different tools and packages. 273 274 uname -a 275 printf "python: " 276 python -V || echo "no 'python' binary." 277 printf "python3: " 278 python3 -V || echo "no 'python3' binary." 279 280 show_git_version Tor "${CI_SRCDIR}" 281 if [[ "${STEM}" = "yes" ]]; then 282 show_git_version Stem "${STEM_PATH}" 283 fi 284 if [[ "${CHUTNEY}" = "yes" ]]; then 285 show_git_version Chutney "${CHUTNEY_PATH}" 286 fi 287 288 ############################################################################# 289 # Determine the version of Tor. 290 291 TOR_VERSION=$(grep -m 1 AC_INIT "${CI_SRCDIR}"/configure.ac | sed -e 's/.*\[//; s/\].*//;') 292 293 # Use variables like these when we need to behave differently depending on 294 # Tor version. Only create the variables we need. 295 TOR_VER_AT_LEAST_043=no 296 TOR_VER_AT_LEAST_044=no 297 298 # These are the currently supported Tor versions; no need to work with anything 299 # ancient in this script. 300 case "$TOR_VERSION" in 301 0.4.8.*) 302 TOR_VER_AT_LEAST_043=yes 303 TOR_VER_AT_LEAST_044=yes 304 ;; 305 0.4.9.*) 306 TOR_VER_AT_LEAST_043=yes 307 TOR_VER_AT_LEAST_044=yes 308 ;; 309 0.5.0.*) 310 TOR_VER_AT_LEAST_043=yes 311 TOR_VER_AT_LEAST_044=yes 312 ;; 313 esac 314 315 ############################################################################# 316 # Make sure the directories are all there. 317 318 # Make sure CI_SRCDIR exists and has a file we expect. 319 if [[ ! -d "$CI_SRCDIR" ]] ; then 320 die "CI_SRCDIR=${CI_SRCDIR} is not a directory" 321 fi 322 if [[ ! -f "$CI_SRCDIR/src/core/or/or.h" ]] ; then 323 die "CI_SRCDIR=${CI_SRCDIR} does not look like a Tor directory." 324 fi 325 326 # Make CI_SRCDIR absolute. 327 CI_SRCDIR=$(cd "$CI_SRCDIR" && pwd) 328 329 # Create an "artifacts" directory to copy artifacts into. 330 mkdir -p ./artifacts 331 332 if [[ "$RUN_STAGE_CONFIGURE" = "yes" ]]; then 333 334 start_section "Autogen" 335 runcmd cd "${CI_SRCDIR}" 336 runcmd ./autogen.sh 337 runcmd mkdir -p "${CI_BUILDDIR}" 338 runcmd cd "${CI_BUILDDIR}" 339 end_section "Autogen" 340 341 # make the builddir absolute too. 342 CI_BUILDDIR=$(pwd) 343 344 start_section "Configure" 345 if ! runcmd "${CI_SRCDIR}"/configure "${configure_options[@]}" ; then 346 error "Here is the end of config.log:" 347 runcmd tail config.log 348 die "Unable to continue" 349 fi 350 end_section "Configure" 351 else 352 debug "Skipping configure stage. Making sure that ${CI_BUILDDIR}/config.log exists." 353 if [[ ! -d "${CI_BUILDDIR}" ]]; then 354 die "Build directory ${CI_BUILDDIR} did not exist!" 355 fi 356 if [[ ! -f "${CI_BUILDDIR}/config.log" ]]; then 357 die "Tor was not configured in ${CI_BUILDDIR}!" 358 fi 359 360 cp config.log "${CI_SRCDIR}"/artifacts 361 362 runcmd cd "${CI_BUILDDIR}" 363 CI_BUILDDIR=$(pwd) 364 fi 365 366 ############################### 367 # Build Tor. 368 369 if [[ "$RUN_STAGE_BUILD" = "yes" ]] ; then 370 if [[ "$DISTCHECK" = "no" ]]; then 371 start_section "Build" 372 runcmd make "${make_options[@]}" all 373 cp src/app/tor "${CI_SRCDIR}"/artifacts 374 end_section "Build" 375 else 376 export DISTCHECK_CONFIGURE_FLAGS="${configure_options[*]}" 377 # XXXX Set make options? 378 start_section Distcheck 379 if runcmd make "${make_options[@]}" distcheck ; then 380 hooray "Distcheck was successful. Nothing further will be done." 381 # We have to exit early here, since we can't do any other tests. 382 cp tor-*.tar.gz "${CI_SRCDIR}"/artifacts 383 else 384 error "Diagnostics:" 385 runcmd make show-distdir-testlog || true 386 runcmd make show-distdir-core || true 387 die "Unable to continue." 388 fi 389 end_section Distcheck 390 exit 0 391 fi 392 fi 393 394 ############################## 395 # Run tests. 396 397 if [[ "$RUN_STAGE_TEST" == "no" ]]; then 398 echo "Skipping tests. Exiting now." 399 exit 0 400 fi 401 402 FAILED_TESTS="" 403 404 if [[ "${DOXYGEN}" = 'yes' ]]; then 405 start_section Doxygen 406 if [[ "${TOR_VER_AT_LEAST_043}" = 'yes' ]]; then 407 if runcmd make doxygen; then 408 hooray "make doxygen has succeeded." 409 else 410 FAILED_TESTS="${FAILED_TESTS} doxygen" 411 fi 412 else 413 skipping "make doxygen: doxygen is broken for Tor < 0.4.3" 414 fi 415 end_section Doxygen 416 fi 417 418 if [[ "${ASCIIDOC}" = 'yes' ]]; then 419 start_section Asciidoc 420 if runcmd make manpages; then 421 hooray "make manpages has succeeded." 422 else 423 FAILED_TESTS="${FAILED_TESTS} asciidoc" 424 fi 425 end_section Asciidoc 426 fi 427 428 if [[ "${CHECK}" = "yes" ]]; then 429 start_section "Check" 430 if runcmd make "${make_options[@]}" check; then 431 hooray "make check has succeeded." 432 else 433 error "Here are the contents of the test suite output:" 434 runcmd cat test-suite.log || true 435 FAILED_TESTS="${FAILED_TESTS} check" 436 fi 437 end_section "Check" 438 fi 439 440 if [[ "${CHUTNEY}" = "yes" ]]; then 441 start_section "Chutney" 442 export CHUTNEY_TOR_SANDBOX=0 443 export CHUTNEY_ALLOW_FAILURES=2 444 # Send 5MB for every verify check. 445 export CHUTNEY_DATA_BYTES=5000000 446 if runcmd make "${CHUTNEY_MAKE_TARGET}"; then 447 hooray "Chutney tests have succeeded" 448 else 449 error "Chutney says:" 450 export CHUTNEY_DATA_DIR="${CHUTNEY_PATH}/net" 451 runcmd "${CHUTNEY_PATH}"/tools/diagnostics.sh || true 452 # XXXX These next two should be part of a make target. 453 runcmd ls test_network_log || true 454 runcmd head -n -0 test_network_log/* || true 455 FAILED_TESTS="${FAILED_TESTS} chutney" 456 fi 457 end_section "Chutney" 458 fi 459 460 if [[ "${STEM}" = "yes" ]]; then 461 start_section "Stem" 462 # 0.3.5 and onward have now disabled onion service v2 so we need to exclude 463 # these Stem tests from now on. 464 EXCLUDE_TESTS="--exclude-test control.controller.test_ephemeral_hidden_services_v2 --exclude-test control.controller.test_hidden_services_conf --exclude-test control.controller.test_with_ephemeral_hidden_services_basic_auth --exclude-test control.controller.test_without_ephemeral_hidden_services --exclude-test control.controller.test_with_ephemeral_hidden_services_basic_auth_no_credentials --exclude-test control.controller.test_with_detached_ephemeral_hidden_services --exclude-test control.controller.test_with_invalid_ephemeral_hidden_service_port --exclude-test control.controller.test_ephemeral_hidden_services_v3" 465 if [[ "${TOR_VER_AT_LEAST_044}" = 'yes' ]]; then 466 # XXXX This should probably be part of some test-stem make target. 467 468 # Disable the check around EXCLUDE_TESTS that requires double quote. We 469 # need it to be expanded. 470 # shellcheck disable=SC2086 471 if runcmd timelimit -p -t 520 -s USR1 -T 30 -S ABRT \ 472 python3 "${STEM_PATH}/run_tests.py" \ 473 --tor src/app/tor \ 474 --integ --test control.controller \ 475 $EXCLUDE_TESTS \ 476 --test control.base_controller \ 477 --test process \ 478 --log TRACE \ 479 --log-file stem.log ; then 480 hooray "Stem tests have succeeded" 481 else 482 error "Stem output:" 483 runcmd tail -1000 "${STEM_PATH}"/test/data/tor_log 484 runcmd grep -v "SocketClosed" stem.log | tail -1000 485 FAILED_TESTS="${FAILED_TESTS} stem" 486 fi 487 else 488 skipping "Stem: broken with <= 0.4.3. See bug tor#40077" 489 fi 490 end_section "Stem" 491 fi 492 493 # TODO: Coverage 494 495 if [[ "${FAILED_TESTS}" != "" ]]; then 496 die "Failed tests: ${FAILED_TESTS}" 497 fi 498 499 hooray "Everything seems fine."