ci-driver.sh 13 KB

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