lib.sh 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #!/bin/bash
  2. # NOTE: This file is sourced in CI across different repos (e.g. snuba),
  3. # thus, renaming this file or any functions can break CI!
  4. #
  5. # Module containing code shared across various shell scripts
  6. # Execute functions from this module via the script do.sh
  7. # shellcheck disable=SC2034 # Unused variables
  8. # shellcheck disable=SC2001 # https://github.com/koalaman/shellcheck/wiki/SC2001
  9. # This block is a safe-guard since in CI calling tput will fail and abort scripts
  10. if [ -z "${CI+x}" ]; then
  11. bold="$(tput bold)"
  12. red="$(tput setaf 1)"
  13. green="$(tput setaf 2)"
  14. yellow="$(tput setaf 3)"
  15. reset="$(tput sgr0)"
  16. fi
  17. venv_name=".venv"
  18. pip-install() {
  19. pip install $(grep ^-- requirements-base.txt) "$@"
  20. }
  21. # Check if a command is available
  22. require() {
  23. command -v "$1" >/dev/null 2>&1
  24. }
  25. configure-sentry-cli() {
  26. if [ -z "${SENTRY_DEVENV_NO_REPORT+x}" ]; then
  27. if ! require sentry-cli; then
  28. curl -sL https://sentry.io/get-cli/ | SENTRY_CLI_VERSION=2.0.4 bash
  29. fi
  30. fi
  31. }
  32. query-valid-python-version() {
  33. python_version=$(python3 -V 2>&1 | awk '{print $2}')
  34. if [[ -n "${SENTRY_PYTHON_VERSION:-}" ]]; then
  35. if [ "$python_version" != "$SENTRY_PYTHON_VERSION" ]; then
  36. cat <<EOF
  37. ${red}${bold}
  38. ERROR: You have explicitly set a non-recommended Python version (${SENTRY_PYTHON_VERSION}),
  39. but it doesn't match the value of python's version: ${python_version}
  40. You should create a new ${SENTRY_PYTHON_VERSION} virtualenv by running "rm -rf ${venv_name} && direnv allow".
  41. ${reset}
  42. EOF
  43. return 1
  44. else
  45. cat <<EOF
  46. ${yellow}${bold}
  47. You have explicitly set a non-recommended Python version (${SENTRY_PYTHON_VERSION}). You're on your own.
  48. ${reset}
  49. EOF
  50. return 0
  51. fi
  52. else
  53. minor=$(echo "${python_version}" | sed 's/[0-9]*\.\([0-9]*\)\.\([0-9]*\)/\1/')
  54. patch=$(echo "${python_version}" | sed 's/[0-9]*\.\([0-9]*\)\.\([0-9]*\)/\2/')
  55. if [ "$minor" -ne 8 ] || [ "$patch" -lt 10 ]; then
  56. cat <<EOF
  57. ${red}${bold}
  58. ERROR: You're running a virtualenv with Python ${python_version}.
  59. We only support >= 3.8.10, < 3.9.
  60. Either run "rm -rf ${venv_name} && direnv allow" to
  61. OR set SENTRY_PYTHON_VERSION=${python_version} to an .env file to bypass this check."
  62. EOF
  63. return 1
  64. fi
  65. fi
  66. }
  67. sudo-askpass() {
  68. if [ -z "${sudo-askpass-x}" ]; then
  69. sudo --askpass "$@"
  70. else
  71. sudo "$@"
  72. fi
  73. }
  74. upgrade-pip() {
  75. pip-install $(grep -E '^(pip|setuptools|wheel)==' requirements-dev-frozen.txt)
  76. }
  77. install-py-dev() {
  78. upgrade-pip
  79. # It places us within top src dir to be at the same path as setup.py
  80. # This helps when getsentry calls into this script
  81. cd "${HERE}/.." || exit
  82. echo "--> Installing Sentry (for development)"
  83. # pip doesn't do well with swapping drop-ins
  84. pip uninstall -qqy uwsgi
  85. # SENTRY_LIGHT_BUILD=1 disables webpacking during setup.py.
  86. # Webpacked assets are only necessary for devserver (which does it lazily anyways)
  87. # and acceptance tests, which webpack automatically if run.
  88. SENTRY_LIGHT_BUILD=1 pip-install -e '.[dev]'
  89. }
  90. setup-git-config() {
  91. git config --local branch.autosetuprebase always
  92. git config --local core.ignorecase false
  93. git config --local blame.ignoreRevsFile .git-blame-ignore-revs
  94. }
  95. setup-git() {
  96. setup-git-config
  97. # if hooks are explicitly turned off do nothing
  98. if [[ "$(git config core.hooksPath)" == '/dev/null' ]]; then
  99. echo "--> core.hooksPath set to /dev/null. Skipping git hook setup"
  100. echo ""
  101. return
  102. fi
  103. echo "--> Installing git hooks"
  104. mkdir -p .git/hooks && cd .git/hooks && ln -sf ../../config/hooks/* ./ && cd - || exit
  105. # shellcheck disable=SC2016
  106. python3 -c '' || (
  107. echo 'Please run `make setup-pyenv` to install the required Python 3 version.'
  108. exit 1
  109. )
  110. if ! require pre-commit; then
  111. pip-install -r requirements-dev-only-frozen.txt
  112. fi
  113. pre-commit install --install-hooks
  114. echo ""
  115. }
  116. node-version-check() {
  117. # Checks to see if node's version matches the one specified in package.json for Volta.
  118. node -pe "process.exit(Number(!(process.version == 'v' + require('./package.json').volta.node )))" ||
  119. (
  120. echo 'Unexpected node version. Recommended to use https://github.com/volta-cli/volta'
  121. echo 'Run `volta install node` and `volta install yarn` to update your toolchain.'
  122. echo 'If you do not have volta installed run `curl https://get.volta.sh | bash` or visit https://volta.sh'
  123. exit 1
  124. )
  125. }
  126. install-js-dev() {
  127. node-version-check
  128. echo "--> Installing Yarn packages (for development)"
  129. # Use NODE_ENV=development so that yarn installs both dependencies + devDependencies
  130. NODE_ENV=development yarn install --frozen-lockfile
  131. # A common problem is with node packages not existing in `node_modules` even though `yarn install`
  132. # says everything is up to date. Even though `yarn install` is run already, it doesn't take into
  133. # account the state of the current filesystem (it only checks .yarn-integrity).
  134. # Add an additional check against `node_modules`
  135. yarn check --verify-tree || yarn install --check-files
  136. }
  137. develop() {
  138. install-js-dev
  139. install-py-dev
  140. setup-git
  141. }
  142. init-config() {
  143. sentry init --dev
  144. }
  145. run-dependent-services() {
  146. sentry devservices up
  147. }
  148. create-db() {
  149. echo "--> Creating 'sentry' database"
  150. docker exec sentry_postgres createdb -h 127.0.0.1 -U postgres -E utf-8 sentry || true
  151. }
  152. apply-migrations() {
  153. echo "--> Applying migrations"
  154. sentry upgrade --noinput
  155. }
  156. create-user() {
  157. if [[ -n "${GITHUB_ACTIONS+x}" ]]; then
  158. sentry createuser --superuser --email foo@tbd.com --no-password --no-input
  159. else
  160. sentry createuser --superuser
  161. fi
  162. }
  163. build-platform-assets() {
  164. echo "--> Building platform assets"
  165. echo "from sentry.utils.integrationdocs import sync_docs; sync_docs(quiet=True)" | sentry exec
  166. # make sure this didn't silently do nothing
  167. test -f src/sentry/integration-docs/android.json
  168. }
  169. bootstrap() {
  170. develop
  171. init-config
  172. run-dependent-services
  173. create-db
  174. apply-migrations
  175. create-user
  176. # Load mocks requires a super user to exist, thus, we execute after create-user
  177. bin/load-mocks
  178. build-platform-assets
  179. }
  180. clean() {
  181. echo "--> Cleaning static cache"
  182. rm -rf dist/* src/sentry/static/sentry/dist/*
  183. echo "--> Cleaning integration docs cache"
  184. rm -rf src/sentry/integration-docs
  185. echo "--> Cleaning pyc files"
  186. find . -name "*.pyc" -delete
  187. echo "--> Cleaning python build artifacts"
  188. rm -rf build/ dist/ src/sentry/assets.json
  189. echo ""
  190. }
  191. drop-db() {
  192. echo "--> Dropping existing 'sentry' database"
  193. docker exec sentry_postgres dropdb -h 127.0.0.1 -U postgres sentry || true
  194. }
  195. reset-db() {
  196. drop-db
  197. create-db
  198. apply-migrations
  199. create-user
  200. echo "Finished resetting database. To load mock data, run `./bin/load-mocks`"
  201. }
  202. prerequisites() {
  203. if [ -z "${CI+x}" ]; then
  204. brew update -q && brew bundle -q
  205. else
  206. HOMEBREW_NO_AUTO_UPDATE=on brew install pyenv
  207. fi
  208. }
  209. direnv-help() {
  210. cat >&2 <<EOF
  211. If you're a Sentry employee and you're stuck or have questions, ask in #discuss-dev-infra.
  212. If you're not, please file an issue under https://github.com/getsentry/sentry/issues/new/choose and mention @getsentry/owners-sentry-dev
  213. You can configure the behaviour of direnv by adding the following variables to a .env file:
  214. - SENTRY_DIRENV_DEBUG=1: This will allow printing debug messages
  215. - SENTRY_DEVENV_NO_REPORT=1: Do not report development environment errors to Sentry.io
  216. EOF
  217. }