lib.sh 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. #!/bin/bash
  2. # Module containing code shared across various shell scripts
  3. # Execute functions from this module via the script do.sh
  4. # shellcheck disable=SC2034 # Unused variables
  5. # shellcheck disable=SC2001 # https://github.com/koalaman/shellcheck/wiki/SC2001
  6. # This block is a safe-guard since in CI calling tput will fail and abort scripts
  7. if [ -z "${CI+x}" ]; then
  8. bold="$(tput bold)"
  9. red="$(tput setaf 1)"
  10. green="$(tput setaf 2)"
  11. yellow="$(tput setaf 3)"
  12. reset="$(tput sgr0)"
  13. fi
  14. venv_name=".venv"
  15. # NOTE: This file is sourced in CI across different repos (e.g. snuba),
  16. # so renaming this file or any functions can break CI!
  17. # Check if a command is available
  18. require() {
  19. command -v "$1" >/dev/null 2>&1
  20. }
  21. configure-sentry-cli() {
  22. # XXX: For version 1.70.1 there's a bug hitting SENTRY_CLI_NO_EXIT_TRAP: unbound variable
  23. # We can remove this after it's fixed
  24. # https://github.com/getsentry/sentry-cli/pull/1059
  25. export SENTRY_CLI_NO_EXIT_TRAP=${SENTRY_CLI_NO_EXIT_TRAP-0}
  26. if [ -n "${SENTRY_DSN+x}" ] && [ -z "${SENTRY_DEVENV_NO_REPORT+x}" ]; then
  27. if ! require sentry-cli; then
  28. curl -sL https://sentry.io/get-cli/ | bash
  29. fi
  30. eval "$(sentry-cli bash-hook)"
  31. fi
  32. }
  33. query-mac() {
  34. [[ $(uname -s) = 'Darwin' ]]
  35. }
  36. query-big-sur() {
  37. if require sw_vers && sw_vers -productVersion | grep -E "11\." >/dev/null; then
  38. return 0
  39. fi
  40. return 1
  41. }
  42. query-apple-m1() {
  43. query-mac && [[ $(uname -m) = 'arm64' ]]
  44. }
  45. query-valid-python-version() {
  46. if [[ -n "${SENTRY_PYTHON_VERSION:-}" ]]; then
  47. python_version=$(python3 -V 2>&1 | awk '{print $2}')
  48. if [ "$python_version" != "$SENTRY_PYTHON_VERSION" ]; then
  49. cat <<EOF
  50. ${red}${bold}
  51. ERROR: You have explicitly set a non-recommended Python version (${SENTRY_PYTHON_VERSION}),
  52. but it doesn't match the value of python's version: ${python_version}
  53. You should create a new ${SENTRY_PYTHON_VERSION} virtualenv by running "rm -rf ${venv_name} && direnv allow".
  54. ${reset}
  55. EOF
  56. return 1
  57. fi
  58. cat <<EOF
  59. ${yellow}${bold}
  60. You have explicitly set a non-recommended Python version (${SENTRY_PYTHON_VERSION}). You're on your own.
  61. ${reset}
  62. EOF
  63. return 0
  64. fi
  65. python_version=$(python3 -V 2>&1 | awk '{print $2}')
  66. minor=$(echo "${python_version}" | sed 's/[0-9]*\.\([0-9]*\)\.\([0-9]*\)/\1/')
  67. patch=$(echo "${python_version}" | sed 's/[0-9]*\.\([0-9]*\)\.\([0-9]*\)/\2/')
  68. if [ "$minor" -ne 8 ] || [ "$patch" -lt 10 ]; then
  69. cat <<EOF
  70. ${red}${bold}
  71. ERROR: You're running a virtualenv with Python ${python_version}.
  72. We only support >= 3.8.10, < 3.9.
  73. Either run "rm -rf ${venv_name} && direnv allow" to
  74. OR set SENTRY_PYTHON_VERSION=${python_version} to an .env file to bypass this check."
  75. EOF
  76. return 1
  77. fi
  78. }
  79. sudo-askpass() {
  80. if [ -z "${sudo-askpass-x}" ]; then
  81. sudo --askpass "$@"
  82. else
  83. sudo "$@"
  84. fi
  85. }
  86. upgrade-pip() {
  87. pip install --upgrade "pip==21.1.2" "wheel==0.36.2"
  88. }
  89. install-py-dev() {
  90. upgrade-pip
  91. # It places us within top src dir to be at the same path as setup.py
  92. # This helps when getsentry calls into this script
  93. cd "${HERE}/.." || exit
  94. echo "--> Installing Sentry (for development)"
  95. if query-apple-m1; then
  96. # This installs pyscopg-binary2 since there's no arm64 wheel
  97. # This saves having to install postgresql on the Developer's machine + using flags
  98. # https://github.com/psycopg/psycopg2/issues/1286
  99. pip install https://storage.googleapis.com/python-arm64-wheels/psycopg2_binary-2.8.6-cp38-cp38-macosx_11_0_arm64.whl
  100. fi
  101. # SENTRY_LIGHT_BUILD=1 disables webpacking during setup.py.
  102. # Webpacked assets are only necessary for devserver (which does it lazily anyways)
  103. # and acceptance tests, which webpack automatically if run.
  104. SENTRY_LIGHT_BUILD=1 pip install -e '.[dev]'
  105. patch-selenium
  106. }
  107. patch-selenium() {
  108. # XXX: getsentry repo calls this!
  109. # This hack is until we can upgrade to a newer version of Selenium
  110. fx_profile=.venv/lib/python3.8/site-packages/selenium/webdriver/firefox/firefox_profile.py
  111. # Remove this block when upgrading the selenium package
  112. if grep -q "or setting is" "${fx_profile}"; then
  113. echo "We are patching ${fx_profile}. You will see this message only once."
  114. patch -p0 <scripts/patches/firefox_profile.diff
  115. fi
  116. }
  117. setup-apple-m1() {
  118. ! query-apple-m1 && return
  119. zshrc_path="${HOME}/.zshrc"
  120. header="# Apple M1 environment variables"
  121. # The CPATH is needed for confluent-kakfa --> https://github.com/confluentinc/confluent-kafka-python/issues/1190
  122. # The LDFLAGS is needed for uWSGI --> https://github.com/unbit/uwsgi/issues/2361
  123. body="
  124. $header
  125. export CPATH=/opt/homebrew/Cellar/librdkafka/1.8.2/include
  126. export LDFLAGS=-L/opt/homebrew/Cellar/gettext/0.21/lib"
  127. if [ "$SHELL" == "/bin/zsh" ]; then
  128. if ! grep -qF "${header}" "${zshrc_path}"; then
  129. echo "Added the following to ${zshrc_path}"
  130. cp "${zshrc_path}" "${zshrc_path}.bak"
  131. echo -e "$body" >> "${zshrc_path}"
  132. echo -e "$body"
  133. fi
  134. else
  135. echo "You are not using a supported shell. Please add these variables where appropiate."
  136. echo -e "$body"
  137. fi
  138. }
  139. setup-git-config() {
  140. git config --local branch.autosetuprebase always
  141. git config --local core.ignorecase false
  142. git config --local blame.ignoreRevsFile .git-blame-ignore-revs
  143. }
  144. setup-git() {
  145. setup-git-config
  146. echo "--> Installing git hooks"
  147. mkdir -p .git/hooks && cd .git/hooks && ln -sf ../../config/hooks/* ./ && cd - || exit
  148. # shellcheck disable=SC2016
  149. python3 -c '' || (
  150. echo 'Please run `make setup-pyenv` to install the required Python 3 version.'
  151. exit 1
  152. )
  153. pip install -r requirements-pre-commit.txt
  154. pre-commit install --install-hooks
  155. echo ""
  156. }
  157. node-version-check() {
  158. # Checks to see if node's version matches the one specified in package.json for Volta.
  159. node -pe "process.exit(Number(!(process.version == 'v' + require('./package.json').volta.node )))" ||
  160. (
  161. echo 'Unexpected node version. Recommended to use https://github.com/volta-cli/volta'
  162. exit 1
  163. )
  164. }
  165. install-js-dev() {
  166. node-version-check
  167. echo "--> Installing Yarn packages (for development)"
  168. # Use NODE_ENV=development so that yarn installs both dependencies + devDependencies
  169. NODE_ENV=development yarn install --frozen-lockfile
  170. # A common problem is with node packages not existing in `node_modules` even though `yarn install`
  171. # says everything is up to date. Even though `yarn install` is run already, it doesn't take into
  172. # account the state of the current filesystem (it only checks .yarn-integrity).
  173. # Add an additional check against `node_modules`
  174. yarn check --verify-tree || yarn install --check-files
  175. }
  176. develop() {
  177. setup-git
  178. install-js-dev
  179. install-py-dev
  180. }
  181. init-config() {
  182. sentry init --dev
  183. }
  184. run-dependent-services() {
  185. sentry devservices up
  186. }
  187. create-db() {
  188. echo "--> Creating 'sentry' database"
  189. docker exec sentry_postgres createdb -h 127.0.0.1 -U postgres -E utf-8 sentry || true
  190. }
  191. apply-migrations() {
  192. echo "--> Applying migrations"
  193. sentry upgrade --noinput
  194. }
  195. create-user() {
  196. if [[ -n "${GITHUB_ACTIONS+x}" ]]; then
  197. sentry createuser --superuser --email foo@tbd.com --no-password
  198. else
  199. sentry createuser --superuser
  200. fi
  201. }
  202. build-platform-assets() {
  203. echo "--> Building platform assets"
  204. echo "from sentry.utils.integrationdocs import sync_docs; sync_docs(quiet=True)" | sentry exec
  205. }
  206. bootstrap() {
  207. setup-apple-m1
  208. develop
  209. init-config
  210. run-dependent-services
  211. create-db
  212. apply-migrations
  213. create-user
  214. build-platform-assets
  215. }
  216. clean() {
  217. echo "--> Cleaning static cache"
  218. rm -rf dist/* src/sentry/static/sentry/dist/*
  219. echo "--> Cleaning integration docs cache"
  220. rm -rf src/sentry/integration-docs
  221. echo "--> Cleaning pyc files"
  222. find . -name "*.pyc" -delete
  223. echo "--> Cleaning python build artifacts"
  224. rm -rf build/ dist/ src/sentry/assets.json
  225. echo ""
  226. }
  227. drop-db() {
  228. echo "--> Dropping existing 'sentry' database"
  229. docker exec sentry_postgres dropdb -h 127.0.0.1 -U postgres sentry || true
  230. }
  231. reset-db() {
  232. drop-db
  233. create-db
  234. apply-migrations
  235. }
  236. prerequisites() {
  237. if [ -z "${CI+x}" ]; then
  238. brew update -q && brew bundle -q
  239. else
  240. HOMEBREW_NO_AUTO_UPDATE=on brew install libxmlsec1 pyenv
  241. fi
  242. }
  243. direnv-help() {
  244. cat >&2 <<EOF
  245. If you're a Sentry employee and you're stuck or have questions, ask in #discuss-dev-tooling.
  246. If you're not, please file an issue under https://github.com/getsentry/sentry/issues/new/choose and mention @getsentry/owners-sentry-dev
  247. You can configure the behaviour of direnv by adding the following variables to a .env file:
  248. - SENTRY_DIRENV_DEBUG=1: This will allow printing debug messages
  249. - SENTRY_DEVENV_NO_REPORT=1: Do not report development environment errors to Sentry.io
  250. EOF
  251. }