coverity-scan.sh 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #!/usr/bin/env bash
  2. # SPDX-License-Identifier: GPL-3.0-or-later
  3. # shellcheck disable=SC1091,SC2230,SC2086
  4. #
  5. # Coverity scan script
  6. #
  7. # To run manually, save configuration to .coverity-scan.conf like this:
  8. #
  9. # the repository to report to coverity - devs can set here their own fork
  10. # REPOSITORY="netdata/netdata"
  11. #
  12. # the email of the developer, as given to coverity
  13. # COVERITY_SCAN_SUBMIT_MAIL="you@example.com"
  14. #
  15. # the token given by coverity to the developer
  16. # COVERITY_SCAN_TOKEN="TOKEN taken from Coverity site"
  17. #
  18. # the absolute path of the cov-build - optional
  19. # COVERITY_BUILD_PATH="/opt/cov-analysis-linux64-2021.12/bin/cov-build"
  20. #
  21. # when set, the script will print on screen the curl command that submits the build to coverity
  22. # this includes the token, so the default is not to print it.
  23. # COVERITY_SUBMIT_DEBUG=1
  24. #
  25. # All these variables can also be exported before running this script.
  26. #
  27. # If the first parameter of this script is "install",
  28. # coverity build tools will be downloaded and installed in /opt/coverity
  29. set -e
  30. if [ "$(uname -s)" != "Linux" ] || [ "$(uname -m)" != "x86_64" ]; then
  31. echo "This script can only be used on a 64-bit x86 Linux system."
  32. exit 1
  33. fi
  34. INSTALL_DIR="/opt"
  35. SCRIPT_SOURCE="$(
  36. self=${0}
  37. while [ -L "${self}" ]
  38. do
  39. cd "${self%/*}" || exit 1
  40. self=$(readlink "${self}")
  41. done
  42. cd "${self%/*}" || exit 1
  43. echo "$(pwd -P)/${self##*/}"
  44. )"
  45. REPO_ROOT="$(dirname "${SCRIPT_SOURCE}")/../.."
  46. . "${REPO_ROOT}/packaging/installer/functions.sh"
  47. JOBS=$(find_processors)
  48. [ -z "${JOBS}" ] && JOBS=1
  49. if command -v ninja 2>&1; then
  50. ninja="$(command -v ninja)"
  51. fi
  52. CMAKE_OPTS="${ninja:+-G Ninja}"
  53. BUILD_OPTS="VERBOSE=1"
  54. [ -n "${ninja}" ] && BUILD_OPTS="-v"
  55. NETDATA_BUILD_DIR="${NETDATA_BUILD_DIR:-./build/}"
  56. if [ -f ".coverity-scan.conf" ]; then
  57. source ".coverity-scan.conf"
  58. fi
  59. repo="${REPOSITORY}"
  60. if [ -z "${repo}" ]; then
  61. fatal "export variable REPOSITORY or set it in .coverity-scan.conf"
  62. fi
  63. repo="${repo//\//%2F}"
  64. email="${COVERITY_SCAN_SUBMIT_MAIL}"
  65. if [ -z "${email}" ]; then
  66. fatal "export variable COVERITY_SCAN_SUBMIT_MAIL or set it in .coverity-scan.conf"
  67. fi
  68. token="${COVERITY_SCAN_TOKEN}"
  69. if [ -z "${token}" ]; then
  70. fatal "export variable COVERITY_SCAN_TOKEN or set it in .coverity-scan.conf"
  71. fi
  72. if ! command -v curl > /dev/null 2>&1; then
  73. fatal "CURL is required for coverity scan to work"
  74. fi
  75. # only print the output of a command
  76. # when debugging is enabled
  77. # used to hide the token when debugging is not enabled
  78. debugrun() {
  79. if [ "${COVERITY_SUBMIT_DEBUG}" = "1" ]; then
  80. run "${@}"
  81. return $?
  82. else
  83. "${@}"
  84. return $?
  85. fi
  86. }
  87. scanit() {
  88. progress "Scanning using coverity"
  89. COVERITY_PATH=$(find "${INSTALL_DIR}" -maxdepth 1 -name 'cov*linux*')
  90. export PATH=${PATH}:${COVERITY_PATH}/bin/
  91. covbuild="${COVERITY_BUILD_PATH}"
  92. [ -z "${covbuild}" ] && covbuild="$(which cov-build 2> /dev/null || command -v cov-build 2> /dev/null)"
  93. if [ -z "${covbuild}" ]; then
  94. fatal "Cannot find 'cov-build' binary in \$PATH. Export variable COVERITY_BUILD_PATH or set it in .coverity-scan.conf"
  95. elif [ ! -x "${covbuild}" ]; then
  96. fatal "The command '${covbuild}' is not executable. Export variable COVERITY_BUILD_PATH or set it in .coverity-scan.conf"
  97. fi
  98. cd "${REPO_ROOT}" || exit 1
  99. version="$(grep "^#define PACKAGE_VERSION" config.h | cut -d '"' -f 2)"
  100. progress "Working on netdata version: ${version}"
  101. progress "Cleaning up old builds..."
  102. rm -rf "${NETDATA_BUILD_DIR}"
  103. [ -d "cov-int" ] && rm -rf "cov-int"
  104. [ -f netdata-coverity-analysis.tgz ] && run rm netdata-coverity-analysis.tgz
  105. progress "Configuring netdata source..."
  106. USE_SYSTEM_PROTOBUF=1
  107. ENABLE_GO=0
  108. prepare_cmake_options
  109. run cmake ${NETDATA_CMAKE_OPTIONS}
  110. progress "Analyzing netdata..."
  111. run "${covbuild}" --dir cov-int cmake --build "${NETDATA_BUILD_DIR}" --parallel ${JOBS} -- ${BUILD_OPTS}
  112. echo >&2 "Compressing analysis..."
  113. run tar czvf netdata-coverity-analysis.tgz cov-int
  114. echo >&2 "Sending analysis to coverity for netdata version ${version} ..."
  115. COVERITY_SUBMIT_RESULT=$(debugrun curl --progress-bar \
  116. --form token="${token}" \
  117. --form email="${email}" \
  118. --form file=@netdata-coverity-analysis.tgz \
  119. --form version="${version}" \
  120. --form description="netdata, monitor everything, in real-time." \
  121. https://scan.coverity.com/builds?project="${repo}")
  122. echo "${COVERITY_SUBMIT_RESULT}" | grep -q -e 'Build successfully submitted' || echo >&2 "scan results were not pushed to coverity. Message was: ${COVERITY_SUBMIT_RESULT}"
  123. progress "Coverity scan completed"
  124. }
  125. installit() {
  126. TMP_DIR="$(mktemp -d /tmp/netdata-coverity-scan-XXXXX)"
  127. progress "Downloading coverity in ${TMP_DIR}..."
  128. (cd "${TMP_DIR}" && debugrun curl --remote-name --remote-header-name --show-error --location --data "token=${token}&project=${repo}" https://scan.coverity.com/download/linux64)
  129. COVERITY_ARCHIVE="$(find "${TMP_DIR}" -maxdepth 1 -mindepth 1 -name 'cov-analysis-linux64-*.tar.gz')"
  130. if [ -n "${COVERITY_ARCHIVE}" ] && [ -f "${COVERITY_ARCHIVE}" ]; then
  131. progress "Installing coverity..."
  132. run sudo tar -z -x -f "${COVERITY_ARCHIVE}" -C "${INSTALL_DIR}"
  133. rm -f "${COVERITY_ARCHIVE}"
  134. COVERITY_PATH=$(find "${INSTALL_DIR}" -maxdepth 1 -name 'cov*linux*')
  135. export PATH="${PATH}:${COVERITY_PATH}/bin/"
  136. elif find "${TMP_DIR}" -name "*.tar.gz" > /dev/null 2>&1; then
  137. ls "${TMP_DIR}"/*.tar.gz
  138. fatal "Downloaded coverity tool tarball does not appear to be the file-name we were expecting, exiting."
  139. else
  140. fatal "Failed to download coverity tool tarball!"
  141. fi
  142. # Validate the installation
  143. covbuild="$(which cov-build 2> /dev/null || command -v cov-build 2> /dev/null)"
  144. if [ -z "$covbuild" ]; then
  145. fatal "Failed to install coverity."
  146. fi
  147. progress "Coverity scan tools are installed."
  148. # Clean temp directory
  149. [ -n "${TMP_DIR}" ] && rm -rf "${TMP_DIR}"
  150. return 0
  151. }
  152. FOUND_OPTS="NO"
  153. while [ -n "${1}" ]; do
  154. if [ "${1}" = "--with-install" ]; then
  155. progress "Running coverity install"
  156. installit
  157. shift 1
  158. elif [ -n "${1}" ]; then
  159. # Clear the default arguments, once you bump into the first argument
  160. if [ "${FOUND_OPTS}" = "NO" ]; then
  161. OTHER_OPTIONS="${1}"
  162. FOUND_OPTS="YES"
  163. else
  164. OTHER_OPTIONS+=" ${1}"
  165. fi
  166. shift 1
  167. else
  168. break
  169. fi
  170. done
  171. echo "Running coverity scan with extra options ${OTHER_OPTIONS}"
  172. scanit "${OTHER_OPTIONS}"