lib.sh 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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. # XDG paths' standardized defaults:
  19. # (see https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html#variables )
  20. export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
  21. export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
  22. export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
  23. export XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}"
  24. export XDG_CONFIG_DIRS="${XDG_CONFIG_DIRS:-/etc/xdg}"
  25. export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
  26. export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/var/run}"
  27. # Check if a command is available
  28. require() {
  29. command -v "$1" >/dev/null 2>&1
  30. }
  31. configure-sentry-cli() {
  32. if [ -f "${venv_name}/bin/sentry-cli" ]; then
  33. return 0
  34. elif [ -f "${venv_name}/bin/pip" ]; then
  35. pip-install sentry-cli
  36. else
  37. cat <<EOF
  38. ${red}${bold}
  39. ERROR: sentry-cli could not be installed, please run "devenv sync".
  40. ${reset}
  41. EOF
  42. return 1
  43. fi
  44. }
  45. query-valid-python-version() {
  46. python_version=$(python3 -V 2>&1 | awk '{print $2}')
  47. if [[ -n "${SENTRY_PYTHON_VERSION:-}" ]]; then
  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. else
  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. else
  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 12 ] || [ "$patch" -lt 1 ]; then
  69. cat <<EOF
  70. ${red}${bold}
  71. ERROR: You're running a virtualenv with Python ${python_version}.
  72. We only support >= 3.12.1, < 3.13.
  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. fi
  79. }
  80. sudo-askpass() {
  81. if [ -z "${sudo-askpass-x}" ]; then
  82. sudo --askpass "$@"
  83. else
  84. sudo "$@"
  85. fi
  86. }
  87. pip-install() {
  88. pip install --constraint "${HERE}/../requirements-dev-frozen.txt" "$@"
  89. }
  90. upgrade-pip() {
  91. pip-install pip
  92. }
  93. install-py-dev() {
  94. upgrade-pip
  95. # It places us within top src dir to be at the same path as setup.py
  96. # This helps when getsentry calls into this script
  97. cd "${HERE}/.." || exit
  98. echo "--> Installing Sentry (for development)"
  99. # pip doesn't do well with swapping drop-ins
  100. pip uninstall -qqy djangorestframework-stubs django-stubs
  101. pip-install -r requirements-dev-frozen.txt
  102. python3 -m tools.fast_editable --path .
  103. }
  104. setup-git-config() {
  105. git config --local branch.autosetuprebase always
  106. git config --local core.ignorecase false
  107. git config --local blame.ignoreRevsFile .git-blame-ignore-revs
  108. }
  109. setup-git() {
  110. setup-git-config
  111. # if hooks are explicitly turned off do nothing
  112. if [[ "$(git config core.hooksPath)" == '/dev/null' ]]; then
  113. echo "--> core.hooksPath set to /dev/null. Skipping git hook setup"
  114. echo ""
  115. return
  116. fi
  117. echo "--> Installing git hooks"
  118. mkdir -p .git/hooks && cd .git/hooks && ln -sf ../../config/hooks/* ./ && cd - || exit
  119. .venv/bin/pre-commit install --install-hooks
  120. }
  121. node-version-check() {
  122. # Checks to see if node's version matches the one specified in package.json for Volta.
  123. node -pe "process.exit(Number(!(process.version == 'v' + require('./.volta.json').volta.node )))" ||
  124. (
  125. echo 'Unexpected node version. Recommended to use https://github.com/volta-cli/volta'
  126. echo 'Run `volta install node` and `volta install yarn` to update your toolchain.'
  127. echo 'If you do not have volta installed run `curl https://get.volta.sh | bash` or visit https://volta.sh'
  128. exit 1
  129. )
  130. }
  131. install-js-dev() {
  132. node-version-check
  133. echo "--> Installing Yarn packages (for development)"
  134. # Use NODE_ENV=development so that yarn installs both dependencies + devDependencies
  135. NODE_ENV=development yarn install --frozen-lockfile
  136. # A common problem is with node packages not existing in `node_modules` even though `yarn install`
  137. # says everything is up to date. Even though `yarn install` is run already, it doesn't take into
  138. # account the state of the current filesystem (it only checks .yarn-integrity).
  139. # Add an additional check against `node_modules`
  140. yarn check --verify-tree || yarn install --check-files
  141. }
  142. develop() {
  143. install-js-dev
  144. install-py-dev
  145. setup-git
  146. }
  147. init-config() {
  148. sentry init --dev --no-clobber
  149. }
  150. run-dependent-services() {
  151. sentry devservices up
  152. }
  153. create-db() {
  154. container_name=${POSTGRES_CONTAINER:-sentry_postgres}
  155. echo "--> Creating 'sentry' database"
  156. docker exec "${container_name}" createdb -h 127.0.0.1 -U postgres -E utf-8 sentry || true
  157. echo "--> Creating 'control', 'region' and 'secondary' database"
  158. docker exec "${container_name}" createdb -h 127.0.0.1 -U postgres -E utf-8 control || true
  159. docker exec "${container_name}" createdb -h 127.0.0.1 -U postgres -E utf-8 region || true
  160. docker exec "${container_name}" createdb -h 127.0.0.1 -U postgres -E utf-8 secondary || true
  161. }
  162. apply-migrations() {
  163. create-db
  164. echo "--> Applying migrations"
  165. sentry upgrade --noinput
  166. }
  167. create-superuser() {
  168. echo "--> Creating a superuser account"
  169. if [[ -n "${GITHUB_ACTIONS+x}" ]]; then
  170. sentry createuser --superuser --email foo@tbd.com --no-password --no-input
  171. else
  172. sentry createuser --superuser --email admin@sentry.io --password admin --no-input
  173. echo "Password is admin."
  174. fi
  175. }
  176. build-platform-assets() {
  177. echo "--> Building platform assets"
  178. python3 -m sentry.build._integration_docs
  179. # make sure this didn't silently do nothing
  180. test -f src/sentry/integration-docs/android.json
  181. }
  182. bootstrap() {
  183. develop
  184. init-config
  185. run-dependent-services
  186. apply-migrations
  187. create-superuser
  188. # Load mocks requires a superuser
  189. bin/load-mocks
  190. build-platform-assets
  191. echo "--> Finished bootstrapping. Have a nice day."
  192. }
  193. clean() {
  194. echo "--> Cleaning static cache"
  195. rm -rf dist/* src/sentry/static/sentry/dist/*
  196. echo "--> Cleaning integration docs cache"
  197. rm -rf src/sentry/integration-docs
  198. echo "--> Cleaning pyc files"
  199. find . -name "*.pyc" -delete
  200. echo "--> Cleaning python build artifacts"
  201. rm -rf build/ dist/ src/sentry/assets.json
  202. echo ""
  203. }
  204. drop-db() {
  205. container_name=${POSTGRES_CONTAINER:-sentry_postgres}
  206. echo "--> Dropping existing 'sentry' database"
  207. docker exec "${container_name}" dropdb --if-exists -h 127.0.0.1 -U postgres sentry
  208. echo "--> Dropping 'control' and 'region' database"
  209. docker exec "${container_name}" dropdb --if-exists -h 127.0.0.1 -U postgres control
  210. docker exec "${container_name}" dropdb --if-exists -h 127.0.0.1 -U postgres region
  211. docker exec "${container_name}" dropdb --if-exists -h 127.0.0.1 -U postgres secondary
  212. }
  213. reset-db() {
  214. drop-db
  215. apply-migrations
  216. create-superuser
  217. echo 'Finished resetting database. To load mock data, run `./bin/load-mocks`'
  218. }
  219. direnv-help() {
  220. cat >&2 <<EOF
  221. If you're a Sentry employee and you're stuck or have questions, ask in #discuss-dev-infra.
  222. If you're not, please file an issue under https://github.com/getsentry/sentry/issues/new/choose and mention @getsentry/owners-sentry-dev
  223. You can configure the behaviour of direnv by adding the following variables to a .env file:
  224. - SENTRY_DIRENV_DEBUG=1: This will allow printing debug messages
  225. - SENTRY_DEVENV_NO_REPORT=1: Do not report development environment errors to Sentry.io
  226. EOF
  227. }