backend.yml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. name: backend
  2. on:
  3. push:
  4. branches:
  5. - master
  6. pull_request:
  7. # Cancel in progress workflows on pull_requests.
  8. # https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value
  9. concurrency:
  10. group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
  11. cancel-in-progress: true
  12. # hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359
  13. env:
  14. SEGMENT_DOWNLOAD_TIMEOUT_MINS: 3
  15. jobs:
  16. files-changed:
  17. name: detect what files changed
  18. runs-on: ubuntu-20.04
  19. timeout-minutes: 3
  20. # Map a step output to a job output
  21. outputs:
  22. api_docs: ${{ steps.changes.outputs.api_docs }}
  23. backend: ${{ steps.changes.outputs.backend_all }}
  24. backend_dependencies: ${{ steps.changes.outputs.backend_dependencies }}
  25. backend_any_type: ${{ steps.changes.outputs.backend_any_type }}
  26. migration_lockfile: ${{ steps.changes.outputs.migration_lockfile }}
  27. steps:
  28. - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
  29. - name: Check for backend file changes
  30. uses: getsentry/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
  31. id: changes
  32. with:
  33. token: ${{ github.token }}
  34. filters: .github/file-filters.yml
  35. api-docs:
  36. if: needs.files-changed.outputs.api_docs == 'true'
  37. needs: files-changed
  38. name: api docs test
  39. runs-on: ubuntu-20.04
  40. steps:
  41. - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
  42. - uses: getsentry/action-setup-volta@c52be2ea13cfdc084edb806e81958c13e445941e # v1.2.0
  43. - name: Setup sentry python env
  44. uses: ./.github/actions/setup-sentry
  45. id: setup
  46. with:
  47. snuba: true
  48. - name: Run API docs tests
  49. # install ts-node for ts build scripts to execute properly without potentially installing
  50. # conflicting deps when running scripts locally
  51. # see: https://github.com/getsentry/sentry/pull/32328/files
  52. run: |
  53. yarn add ts-node && make test-api-docs
  54. backend-test:
  55. if: needs.files-changed.outputs.backend == 'true'
  56. needs: files-changed
  57. name: backend test
  58. runs-on: ubuntu-20.04
  59. timeout-minutes: 60
  60. strategy:
  61. # This helps not having to run multiple jobs because one fails, thus, reducing resource usage
  62. # and reducing the risk that one of many runs would turn red again (read: intermittent tests)
  63. fail-fast: false
  64. matrix:
  65. # XXX: When updating this, make sure you also update MATRIX_INSTANCE_TOTAL.
  66. instance: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  67. pg-version: ['14']
  68. env:
  69. # XXX: `MATRIX_INSTANCE_TOTAL` must be hardcoded to the length of `strategy.matrix.instance`.
  70. # If this increases, make sure to also increase `flags.backend.after_n_builds` in `codecov.yml`.
  71. MATRIX_INSTANCE_TOTAL: 11
  72. steps:
  73. - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
  74. with:
  75. # Avoid codecov error message related to SHA resolution:
  76. # https://github.com/codecov/codecov-bash/blob/7100762afbc822b91806a6574658129fe0d23a7d/codecov#L891
  77. fetch-depth: '2'
  78. - name: Setup sentry env
  79. uses: ./.github/actions/setup-sentry
  80. id: setup
  81. with:
  82. kafka: true
  83. snuba: true
  84. symbolicator: true
  85. # Right now, we run so few bigtable related tests that the
  86. # overhead of running bigtable in all backend tests
  87. # is way smaller than the time it would take to run in its own job.
  88. bigtable: true
  89. pg-version: ${{ matrix.pg-version }}
  90. - name: Run backend test (${{ steps.setup.outputs.matrix-instance-number }} of ${{ steps.setup.outputs.matrix-instance-total }})
  91. run: |
  92. make test-python-ci
  93. # Upload coverage data even if running the tests step fails since
  94. # it reduces large coverage fluctuations
  95. - name: Handle artifacts
  96. if: ${{ always() }}
  97. uses: ./.github/actions/artifacts
  98. with:
  99. token: ${{ secrets.CODECOV_TOKEN }}
  100. backend-migration-tests:
  101. if: needs.files-changed.outputs.backend == 'true'
  102. needs: files-changed
  103. name: backend migration tests
  104. runs-on: ubuntu-20.04
  105. timeout-minutes: 30
  106. strategy:
  107. matrix:
  108. pg-version: ['14']
  109. steps:
  110. - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
  111. with:
  112. # Avoid codecov error message related to SHA resolution:
  113. # https://github.com/codecov/codecov-bash/blob/7100762afbc822b91806a6574658129fe0d23a7d/codecov#L891
  114. fetch-depth: '2'
  115. - name: Setup sentry env
  116. uses: ./.github/actions/setup-sentry
  117. id: setup
  118. with:
  119. snuba: true
  120. pg-version: ${{ matrix.pg-version }}
  121. - name: run tests
  122. run: |
  123. PYTEST_ADDOPTS="$PYTEST_ADDOPTS -m migrations --migrations" make test-python-ci
  124. # Upload coverage data even if running the tests step fails since
  125. # it reduces large coverage fluctuations
  126. - name: Handle artifacts
  127. if: ${{ always() }}
  128. uses: ./.github/actions/artifacts
  129. with:
  130. token: ${{ secrets.CODECOV_TOKEN }}
  131. cli:
  132. if: needs.files-changed.outputs.backend == 'true'
  133. needs: files-changed
  134. name: cli test
  135. runs-on: ubuntu-20.04
  136. timeout-minutes: 10
  137. strategy:
  138. matrix:
  139. pg-version: ['14']
  140. steps:
  141. - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
  142. - name: Setup sentry env
  143. uses: ./.github/actions/setup-sentry
  144. id: setup
  145. with:
  146. pg-version: ${{ matrix.pg-version }}
  147. - name: Run test
  148. run: |
  149. make test-cli
  150. # Upload coverage data even if running the tests step fails since
  151. # it reduces large coverage fluctuations
  152. - name: Handle artifacts
  153. if: ${{ always() }}
  154. uses: ./.github/actions/artifacts
  155. with:
  156. token: ${{ secrets.CODECOV_TOKEN }}
  157. requirements:
  158. if: needs.files-changed.outputs.backend_dependencies == 'true'
  159. needs: files-changed
  160. name: requirements check
  161. runs-on: ubuntu-20.04
  162. timeout-minutes: 3
  163. steps:
  164. - uses: getsentry/action-github-app-token@97c9e23528286821f97fba885c1b1123284b29cc # v2.0.0
  165. id: token
  166. continue-on-error: true
  167. with:
  168. app_id: ${{ vars.SENTRY_INTERNAL_APP_ID }}
  169. private_key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }}
  170. - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
  171. - uses: getsentry/action-setup-venv@9e3bbae3836b1b6f129955bf55a19e1d99a61c67 # v1.0.5
  172. with:
  173. python-version: 3.8.18
  174. cache-dependency-path: requirements-dev-frozen.txt
  175. install-cmd: python3 -m tools.hack_pip && pip install -q --constraint requirements-dev-frozen.txt pip-tools
  176. - name: check requirements
  177. run: |
  178. python -S -m tools.freeze_requirements
  179. if ! git diff --exit-code; then
  180. echo $'\n\nrun `make freeze-requirements` locally to update requirements'
  181. exit 1
  182. fi
  183. - name: apply any requirements changes
  184. if: steps.token.outcome == 'success' && github.ref != 'refs/heads/master' && always()
  185. uses: getsentry/action-github-commit@748c31dd78cffe76f51bef49a0be856b6effeda7 # v1.1.0
  186. with:
  187. github-token: ${{ steps.token.outputs.token }}
  188. message: ':snowflake: re-freeze requirements'
  189. migration:
  190. if: needs.files-changed.outputs.migration_lockfile == 'true'
  191. needs: files-changed
  192. name: check migration
  193. runs-on: ubuntu-20.04
  194. strategy:
  195. matrix:
  196. pg-version: ['14']
  197. steps:
  198. - name: Checkout sentry
  199. uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
  200. - name: Setup sentry env
  201. uses: ./.github/actions/setup-sentry
  202. id: setup
  203. with:
  204. pg-version: ${{ matrix.pg-version }}
  205. - name: Migration & lockfile checks
  206. env:
  207. SENTRY_LOG_LEVEL: ERROR
  208. PGPASSWORD: postgres
  209. run: |
  210. ./.github/workflows/scripts/migration-check.sh
  211. monolith-dbs:
  212. if: needs.files-changed.outputs.backend == 'true'
  213. needs: files-changed
  214. name: monolith-dbs test
  215. runs-on: ubuntu-20.04
  216. timeout-minutes: 20
  217. steps:
  218. - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
  219. with:
  220. # Avoid codecov error message related to SHA resolution:
  221. # https://github.com/codecov/codecov-bash/blob/7100762afbc822b91806a6574658129fe0d23a7d/codecov#L891
  222. fetch-depth: '2'
  223. - name: Setup sentry env
  224. uses: ./.github/actions/setup-sentry
  225. id: setup
  226. - name: Run test
  227. run: |
  228. make test-monolith-dbs
  229. # Upload coverage data even if running the tests step fails since
  230. # it reduces large coverage fluctuations
  231. - name: Handle artifacts
  232. if: ${{ always() }}
  233. uses: ./.github/actions/artifacts
  234. with:
  235. token: ${{ secrets.CODECOV_TOKEN }}
  236. typing:
  237. if: needs.files-changed.outputs.backend == 'true'
  238. needs: files-changed
  239. name: backend typing
  240. runs-on: ubuntu-20.04
  241. timeout-minutes: 20
  242. steps:
  243. - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
  244. - uses: getsentry/action-setup-venv@9e3bbae3836b1b6f129955bf55a19e1d99a61c67 # v1.0.5
  245. with:
  246. python-version: 3.8.18
  247. cache-dependency-path: requirements-dev-frozen.txt
  248. install-cmd: python3 -m tools.hack_pip && pip install -r requirements-dev-frozen.txt
  249. - name: setup sentry (lite)
  250. run: |
  251. python3 -m tools.fast_editable --path .
  252. sentry init
  253. - run: mypy
  254. id: run
  255. - uses: getsentry/action-github-app-token@97c9e23528286821f97fba885c1b1123284b29cc # v2.0.0
  256. id: token
  257. continue-on-error: true
  258. with:
  259. app_id: ${{ vars.SENTRY_INTERNAL_APP_ID }}
  260. private_key: ${{ secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY }}
  261. # only if `mypy` succeeds should we try and trim the blocklist
  262. - run: python3 -m tools.mypy_helpers.make_module_ignores
  263. id: regen-blocklist
  264. - run: git diff --exit-code
  265. - run: |
  266. # mypy does not have granular codes so don't allow specific messages to regress
  267. ! grep "'Settings' object has no attribute" .artifacts/mypy-all
  268. ! grep 'Cannot override class variable' .artifacts/mypy-all
  269. ! grep 'Exception type must be derived from BaseException' .artifacts/mypy-all
  270. ! grep 'Incompatible return value type (got "HttpResponseBase"' .artifacts/mypy-all
  271. ! grep 'Incompatible types in "yield"' .artifacts/mypy-all
  272. ! grep 'does not explicitly export attribute' .artifacts/mypy-all
  273. - name: apply blocklist changes
  274. if: |
  275. steps.token.outcome == 'success' &&
  276. steps.run.outcome == 'success' &&
  277. steps.regen-blocklist.outcome == 'success' &&
  278. github.ref != 'refs/heads/master' &&
  279. always()
  280. uses: getsentry/action-github-commit@748c31dd78cffe76f51bef49a0be856b6effeda7 # v1.1.0
  281. with:
  282. github-token: ${{ steps.token.outputs.token }}
  283. message: ':knife: regenerate mypy module blocklist'
  284. # This check runs once all dependent jobs have passed
  285. # It symbolizes that all required Backend checks have succesfully passed (Or skipped)
  286. # This step is the only required backend check
  287. backend-required-check:
  288. needs:
  289. [
  290. api-docs,
  291. backend-test,
  292. backend-migration-tests,
  293. cli,
  294. files-changed,
  295. requirements,
  296. migration,
  297. monolith-dbs,
  298. typing,
  299. ]
  300. name: Backend
  301. # This is necessary since a failed/skipped dependent job would cause this job to be skipped
  302. if: always()
  303. runs-on: ubuntu-20.04
  304. steps:
  305. # If any jobs we depend on fail, we will fail since this is a required check
  306. # NOTE: A timeout is considered a failure
  307. - name: Check for failures
  308. if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
  309. run: |
  310. echo "One of the dependent jobs have failed. You may need to re-run it." && exit 1