squad 1.88__tar.gz → 1.89__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (637) hide show
  1. {squad-1.88 → squad-1.89}/CHANGELOG.md +20 -0
  2. {squad-1.88 → squad-1.89}/PKG-INFO +1 -1
  3. {squad-1.88 → squad-1.89}/squad/api/rest.py +7 -1
  4. {squad-1.88 → squad-1.89}/squad/ci/backend/lava.py +3 -2
  5. {squad-1.88 → squad-1.89}/squad/ci/tasks.py +6 -2
  6. {squad-1.88 → squad-1.89}/squad/core/callback.py +10 -4
  7. {squad-1.88 → squad-1.89}/squad/core/history.py +4 -1
  8. {squad-1.88 → squad-1.89}/squad/core/models.py +15 -3
  9. {squad-1.88 → squad-1.89}/squad/core/utils.py +1 -1
  10. {squad-1.88 → squad-1.89}/squad/frontend/comparison.py +6 -1
  11. {squad-1.88 → squad-1.89}/squad/frontend/tests.py +2 -2
  12. squad-1.89/squad/plugins/linux_log_parser.py +183 -0
  13. squad-1.89/squad/version.py +1 -0
  14. {squad-1.88 → squad-1.89}/squad.egg-info/PKG-INFO +1 -1
  15. {squad-1.88 → squad-1.89}/test/ci/backend/test_lava.py +10 -0
  16. {squad-1.88 → squad-1.89}/test/ci/test_tasks.py +21 -4
  17. {squad-1.88 → squad-1.89}/test/core/test_callback.py +14 -0
  18. {squad-1.88 → squad-1.89}/test/core/test_history.py +7 -0
  19. {squad-1.88 → squad-1.89}/test/core/test_project_status.py +17 -0
  20. {squad-1.88 → squad-1.89}/test/core/test_update_project_statuses.py +4 -4
  21. {squad-1.88 → squad-1.89}/test/frontend/test_comparison.py +8 -0
  22. {squad-1.88 → squad-1.89}/test/plugins/test_linux_log_parser.py +62 -19
  23. squad-1.88/squad/plugins/linux_log_parser.py +0 -136
  24. squad-1.88/squad/version.py +0 -1
  25. {squad-1.88 → squad-1.89}/.ackrc +0 -0
  26. {squad-1.88 → squad-1.89}/.coveragerc +0 -0
  27. {squad-1.88 → squad-1.89}/.ctags +0 -0
  28. {squad-1.88 → squad-1.89}/.dockerignore +0 -0
  29. {squad-1.88 → squad-1.89}/.github/workflows/release.yml +0 -0
  30. {squad-1.88 → squad-1.89}/.github/workflows/test.yml +0 -0
  31. {squad-1.88 → squad-1.89}/.gitignore +0 -0
  32. {squad-1.88 → squad-1.89}/.mailmap +0 -0
  33. {squad-1.88 → squad-1.89}/.readthedocs.yml +0 -0
  34. {squad-1.88 → squad-1.89}/.reuse/dep5 +0 -0
  35. {squad-1.88 → squad-1.89}/COPYING +0 -0
  36. {squad-1.88 → squad-1.89}/COPYRIGHTS +0 -0
  37. {squad-1.88 → squad-1.89}/Dockerfile +0 -0
  38. {squad-1.88 → squad-1.89}/LICENSES/GPL-3.0-or-later.txt +0 -0
  39. {squad-1.88 → squad-1.89}/LICENSES/MIT.txt +0 -0
  40. {squad-1.88 → squad-1.89}/LICENSES/OFL-1.1.txt +0 -0
  41. {squad-1.88 → squad-1.89}/MANIFEST.in +0 -0
  42. {squad-1.88 → squad-1.89}/Procfile +0 -0
  43. {squad-1.88 → squad-1.89}/README.rst +0 -0
  44. {squad-1.88 → squad-1.89}/babel.cfg +0 -0
  45. {squad-1.88 → squad-1.89}/dev-docker +0 -0
  46. {squad-1.88 → squad-1.89}/doc/.gitignore +0 -0
  47. {squad-1.88 → squad-1.89}/doc/Makefile +0 -0
  48. {squad-1.88 → squad-1.89}/doc/api.rst +0 -0
  49. {squad-1.88 → squad-1.89}/doc/ci.rst +0 -0
  50. {squad-1.88 → squad-1.89}/doc/conf.py +0 -0
  51. {squad-1.88 → squad-1.89}/doc/hacking.rst +0 -0
  52. {squad-1.88 → squad-1.89}/doc/index.rst +0 -0
  53. {squad-1.88 → squad-1.89}/doc/install.rst +0 -0
  54. {squad-1.88 → squad-1.89}/doc/intro.rst +0 -0
  55. {squad-1.88 → squad-1.89}/doc/lava_usecase.rst +0 -0
  56. {squad-1.88 → squad-1.89}/doc/plugins.rst +0 -0
  57. {squad-1.88 → squad-1.89}/doc/quickstart.rst +0 -0
  58. {squad-1.88 → squad-1.89}/doc/translating.rst +0 -0
  59. {squad-1.88 → squad-1.89}/doc/tuxsuite_usecase.rst +0 -0
  60. {squad-1.88 → squad-1.89}/docker/db-dumped +0 -0
  61. {squad-1.88 → squad-1.89}/docker/db-to-be-restored +0 -0
  62. {squad-1.88 → squad-1.89}/docker/docker-compose.yml +0 -0
  63. {squad-1.88 → squad-1.89}/docker/extra_settings.py +0 -0
  64. {squad-1.88 → squad-1.89}/docker/init-db.sh +0 -0
  65. {squad-1.88 → squad-1.89}/docker/rabbitmq.config +0 -0
  66. {squad-1.88 → squad-1.89}/docker/squad-apache.conf +0 -0
  67. {squad-1.88 → squad-1.89}/docker-compose.yaml +0 -0
  68. {squad-1.88 → squad-1.89}/manage.py +0 -0
  69. {squad-1.88 → squad-1.89}/package-lock.json +0 -0
  70. {squad-1.88 → squad-1.89}/package.json +0 -0
  71. {squad-1.88 → squad-1.89}/pytest.ini +0 -0
  72. {squad-1.88 → squad-1.89}/requirements-dev.txt +0 -0
  73. {squad-1.88 → squad-1.89}/requirements.txt +0 -0
  74. {squad-1.88 → squad-1.89}/scripts/build +0 -0
  75. {squad-1.88 → squad-1.89}/scripts/check-ci +0 -0
  76. {squad-1.88 → squad-1.89}/scripts/check-ignore +0 -0
  77. {squad-1.88 → squad-1.89}/scripts/community_connector/main.js +0 -0
  78. {squad-1.88 → squad-1.89}/scripts/community_connector/manifest.json +0 -0
  79. {squad-1.88 → squad-1.89}/scripts/dogfood +0 -0
  80. {squad-1.88 → squad-1.89}/scripts/get-metrics +0 -0
  81. {squad-1.88 → squad-1.89}/scripts/get-tests +0 -0
  82. {squad-1.88 → squad-1.89}/scripts/git-build +0 -0
  83. {squad-1.88 → squad-1.89}/scripts/pytest +0 -0
  84. {squad-1.88 → squad-1.89}/scripts/rabbitmq-server +0 -0
  85. {squad-1.88 → squad-1.89}/scripts/release +0 -0
  86. {squad-1.88 → squad-1.89}/scripts/release-docker +0 -0
  87. {squad-1.88 → squad-1.89}/scripts/squad-config +0 -0
  88. {squad-1.88 → squad-1.89}/scripts/test-ci +0 -0
  89. {squad-1.88 → squad-1.89}/scripts/test-docker +0 -0
  90. {squad-1.88 → squad-1.89}/scripts/testdata/gen-ci-jobs +0 -0
  91. {squad-1.88 → squad-1.89}/scripts/testdata/gen-metrics +0 -0
  92. {squad-1.88 → squad-1.89}/scripts/testdata/gen-test-data +0 -0
  93. {squad-1.88 → squad-1.89}/scripts/testdata/gen-tests +0 -0
  94. {squad-1.88 → squad-1.89}/scripts/testdata/setup-dev +0 -0
  95. {squad-1.88 → squad-1.89}/scripts/testdata/submit-ci-jobs +0 -0
  96. {squad-1.88 → squad-1.89}/scripts/testdata/submit-test-data +0 -0
  97. {squad-1.88 → squad-1.89}/scripts/translate +0 -0
  98. {squad-1.88 → squad-1.89}/scripts/travis-lava +0 -0
  99. {squad-1.88 → squad-1.89}/scripts/update-translation-files +0 -0
  100. {squad-1.88 → squad-1.89}/scripts/upload +0 -0
  101. {squad-1.88 → squad-1.89}/setup.cfg +0 -0
  102. {squad-1.88 → squad-1.89}/setup.py +0 -0
  103. {squad-1.88 → squad-1.89}/squad/__init__.py +0 -0
  104. {squad-1.88 → squad-1.89}/squad/admin.py +0 -0
  105. {squad-1.88 → squad-1.89}/squad/api/__init__.py +0 -0
  106. {squad-1.88 → squad-1.89}/squad/api/apps.py +0 -0
  107. {squad-1.88 → squad-1.89}/squad/api/ci.py +0 -0
  108. {squad-1.88 → squad-1.89}/squad/api/data.py +0 -0
  109. {squad-1.88 → squad-1.89}/squad/api/filters.py +0 -0
  110. {squad-1.88 → squad-1.89}/squad/api/urls.py +0 -0
  111. {squad-1.88 → squad-1.89}/squad/api/utils.py +0 -0
  112. {squad-1.88 → squad-1.89}/squad/api/views.py +0 -0
  113. {squad-1.88 → squad-1.89}/squad/celery.py +0 -0
  114. {squad-1.88 → squad-1.89}/squad/ci/__init__.py +0 -0
  115. {squad-1.88 → squad-1.89}/squad/ci/admin.py +0 -0
  116. {squad-1.88 → squad-1.89}/squad/ci/apps.py +0 -0
  117. {squad-1.88 → squad-1.89}/squad/ci/backend/__init__.py +0 -0
  118. {squad-1.88 → squad-1.89}/squad/ci/backend/fake.py +0 -0
  119. {squad-1.88 → squad-1.89}/squad/ci/backend/null.py +0 -0
  120. {squad-1.88 → squad-1.89}/squad/ci/backend/tuxsuite.py +0 -0
  121. {squad-1.88 → squad-1.89}/squad/ci/exceptions.py +0 -0
  122. {squad-1.88 → squad-1.89}/squad/ci/management/__init__.py +0 -0
  123. {squad-1.88 → squad-1.89}/squad/ci/management/commands/__init__.py +0 -0
  124. {squad-1.88 → squad-1.89}/squad/ci/management/commands/create_tuxsuite_boot_tests.py +0 -0
  125. {squad-1.88 → squad-1.89}/squad/ci/management/commands/listen.py +0 -0
  126. {squad-1.88 → squad-1.89}/squad/ci/management/commands/testfetch.py +0 -0
  127. {squad-1.88 → squad-1.89}/squad/ci/migrations/0001_initial.py +0 -0
  128. {squad-1.88 → squad-1.89}/squad/ci/migrations/0002_auto_20170406_1252.py +0 -0
  129. {squad-1.88 → squad-1.89}/squad/ci/migrations/0003_backend_name.py +0 -0
  130. {squad-1.88 → squad-1.89}/squad/ci/migrations/0004_testjob_failure.py +0 -0
  131. {squad-1.88 → squad-1.89}/squad/ci/migrations/0005_remove_listener_data.py +0 -0
  132. {squad-1.88 → squad-1.89}/squad/ci/migrations/0006_simplify_backend_loading.py +0 -0
  133. {squad-1.88 → squad-1.89}/squad/ci/migrations/0007_auto_20170517_1736.py +0 -0
  134. {squad-1.88 → squad-1.89}/squad/ci/migrations/0008_testjob_testrun.py +0 -0
  135. {squad-1.88 → squad-1.89}/squad/ci/migrations/0009_slug_pattern.py +0 -0
  136. {squad-1.88 → squad-1.89}/squad/ci/migrations/0010_testjob_can_resubmit.py +0 -0
  137. {squad-1.88 → squad-1.89}/squad/ci/migrations/0011_testjob_resubmitted_count.py +0 -0
  138. {squad-1.88 → squad-1.89}/squad/ci/migrations/0012_testjob_build.py +0 -0
  139. {squad-1.88 → squad-1.89}/squad/ci/migrations/0013_testjob_name.py +0 -0
  140. {squad-1.88 → squad-1.89}/squad/ci/migrations/0014_testjob_target_build.py +0 -0
  141. {squad-1.88 → squad-1.89}/squad/ci/migrations/0015_testjob_populate_target_build.py +0 -0
  142. {squad-1.88 → squad-1.89}/squad/ci/migrations/0016_backend_max_fetch_attempts.py +0 -0
  143. {squad-1.88 → squad-1.89}/squad/ci/migrations/0017_testjob_fetch_attempts.py +0 -0
  144. {squad-1.88 → squad-1.89}/squad/ci/migrations/0018_testjob_dates.py +0 -0
  145. {squad-1.88 → squad-1.89}/squad/ci/migrations/0019_add_fake_backend.py +0 -0
  146. {squad-1.88 → squad-1.89}/squad/ci/migrations/0020_backend_settings_field.py +0 -0
  147. {squad-1.88 → squad-1.89}/squad/ci/migrations/0021_testjob_parent_job.py +0 -0
  148. {squad-1.88 → squad-1.89}/squad/ci/migrations/0022_backend_poll_enabled.py +0 -0
  149. {squad-1.88 → squad-1.89}/squad/ci/migrations/0023_remove_testjob_build.py +0 -0
  150. {squad-1.88 → squad-1.89}/squad/ci/migrations/0024_fix_testjob_environment_validation.py +0 -0
  151. {squad-1.88 → squad-1.89}/squad/ci/migrations/0025_backend_listen_enabled.py +0 -0
  152. {squad-1.88 → squad-1.89}/squad/ci/migrations/0026_job_start_end_time.py +0 -0
  153. {squad-1.88 → squad-1.89}/squad/ci/migrations/0027_add_tuxsuite_implementation_type.py +0 -0
  154. {squad-1.88 → squad-1.89}/squad/ci/migrations/0028_create_testjob_indexes.py +0 -0
  155. {squad-1.88 → squad-1.89}/squad/ci/migrations/0029_create_testjob_results_input.py +0 -0
  156. {squad-1.88 → squad-1.89}/squad/ci/migrations/0030_testjob_subtasks_count.py +0 -0
  157. {squad-1.88 → squad-1.89}/squad/ci/migrations/__init__.py +0 -0
  158. {squad-1.88 → squad-1.89}/squad/ci/models.py +0 -0
  159. {squad-1.88 → squad-1.89}/squad/ci/templates/squad/ci/testjob_resubmit.html.jinja2 +0 -0
  160. {squad-1.88 → squad-1.89}/squad/ci/templates/squad/ci/testjob_resubmit.txt.jinja2 +0 -0
  161. {squad-1.88 → squad-1.89}/squad/ci/templatetags/__init__.py +0 -0
  162. {squad-1.88 → squad-1.89}/squad/ci/templatetags/filter_jobs.py +0 -0
  163. {squad-1.88 → squad-1.89}/squad/ci/utils.py +0 -0
  164. {squad-1.88 → squad-1.89}/squad/compat.py +0 -0
  165. {squad-1.88 → squad-1.89}/squad/container_settings.py +0 -0
  166. {squad-1.88 → squad-1.89}/squad/core/__init__.py +0 -0
  167. {squad-1.88 → squad-1.89}/squad/core/admin.py +0 -0
  168. {squad-1.88 → squad-1.89}/squad/core/apps.py +0 -0
  169. {squad-1.88 → squad-1.89}/squad/core/comparison.py +0 -0
  170. {squad-1.88 → squad-1.89}/squad/core/data.py +0 -0
  171. {squad-1.88 → squad-1.89}/squad/core/failures.py +0 -0
  172. {squad-1.88 → squad-1.89}/squad/core/locale/django.pot +0 -0
  173. {squad-1.88 → squad-1.89}/squad/core/locale/es_MX/LC_MESSAGES/django.po +0 -0
  174. {squad-1.88 → squad-1.89}/squad/core/locale/pl/LC_MESSAGES/django.po +0 -0
  175. {squad-1.88 → squad-1.89}/squad/core/locale/pt/LC_MESSAGES/django.po +0 -0
  176. {squad-1.88 → squad-1.89}/squad/core/locale/pt_BR/LC_MESSAGES/django.po +0 -0
  177. {squad-1.88 → squad-1.89}/squad/core/management/__init__.py +0 -0
  178. {squad-1.88 → squad-1.89}/squad/core/management/commands/__init__.py +0 -0
  179. {squad-1.88 → squad-1.89}/squad/core/management/commands/compute_build_summaries.py +0 -0
  180. {squad-1.88 → squad-1.89}/squad/core/management/commands/compute_project_statuses.py +0 -0
  181. {squad-1.88 → squad-1.89}/squad/core/management/commands/fill_test_metadata.py +0 -0
  182. {squad-1.88 → squad-1.89}/squad/core/management/commands/fix_squadplugin_data.py +0 -0
  183. {squad-1.88 → squad-1.89}/squad/core/management/commands/import_data.py +0 -0
  184. {squad-1.88 → squad-1.89}/squad/core/management/commands/import_data.rst +0 -0
  185. {squad-1.88 → squad-1.89}/squad/core/management/commands/migrate_test_runs.py +0 -0
  186. {squad-1.88 → squad-1.89}/squad/core/management/commands/populate_metric_build_and_environment.py +0 -0
  187. {squad-1.88 → squad-1.89}/squad/core/management/commands/populate_test_build_and_environment.py +0 -0
  188. {squad-1.88 → squad-1.89}/squad/core/management/commands/prepdump.py +0 -0
  189. {squad-1.88 → squad-1.89}/squad/core/management/commands/send-email.py +0 -0
  190. {squad-1.88 → squad-1.89}/squad/core/management/commands/update_project_statuses.py +0 -0
  191. {squad-1.88 → squad-1.89}/squad/core/management/commands/users.py +0 -0
  192. {squad-1.88 → squad-1.89}/squad/core/migrations/0001_initial.py +0 -0
  193. {squad-1.88 → squad-1.89}/squad/core/migrations/0002_auto_20160525_1403.py +0 -0
  194. {squad-1.88 → squad-1.89}/squad/core/migrations/0003_testrun_log_file.py +0 -0
  195. {squad-1.88 → squad-1.89}/squad/core/migrations/0004_group_user_groups.py +0 -0
  196. {squad-1.88 → squad-1.89}/squad/core/migrations/0005_token.py +0 -0
  197. {squad-1.88 → squad-1.89}/squad/core/migrations/0006_auto_20160826_2242.py +0 -0
  198. {squad-1.88 → squad-1.89}/squad/core/migrations/0007_testrun_data_processed.py +0 -0
  199. {squad-1.88 → squad-1.89}/squad/core/migrations/0008_status.py +0 -0
  200. {squad-1.88 → squad-1.89}/squad/core/migrations/0009_testrun_status_recorded.py +0 -0
  201. {squad-1.88 → squad-1.89}/squad/core/migrations/0010_testrun_datetime.py +0 -0
  202. {squad-1.88 → squad-1.89}/squad/core/migrations/0011_testrun_metadata_fields.py +0 -0
  203. {squad-1.88 → squad-1.89}/squad/core/migrations/0012_build_datetime.py +0 -0
  204. {squad-1.88 → squad-1.89}/squad/core/migrations/0013_testrun_resubmit_url.py +0 -0
  205. {squad-1.88 → squad-1.89}/squad/core/migrations/0014_testrun_metadata_file.py +0 -0
  206. {squad-1.88 → squad-1.89}/squad/core/migrations/0015_attachment.py +0 -0
  207. {squad-1.88 → squad-1.89}/squad/core/migrations/0016_project_is_public.py +0 -0
  208. {squad-1.88 → squad-1.89}/squad/core/migrations/0017_slug_validator.py +0 -0
  209. {squad-1.88 → squad-1.89}/squad/core/migrations/0018_build_name.py +0 -0
  210. {squad-1.88 → squad-1.89}/squad/core/migrations/0019_build_version.py +0 -0
  211. {squad-1.88 → squad-1.89}/squad/core/migrations/0020_build_ordering.py +0 -0
  212. {squad-1.88 → squad-1.89}/squad/core/migrations/0021_global_tokens.py +0 -0
  213. {squad-1.88 → squad-1.89}/squad/core/migrations/0022_projectstatus.py +0 -0
  214. {squad-1.88 → squad-1.89}/squad/core/migrations/0023_subscription.py +0 -0
  215. {squad-1.88 → squad-1.89}/squad/core/migrations/0024_project_build_completion_threshold.py +0 -0
  216. {squad-1.88 → squad-1.89}/squad/core/migrations/0025_unique_testrun_job_id.py +0 -0
  217. {squad-1.88 → squad-1.89}/squad/core/migrations/0026_testrun_result_accept_null.py +0 -0
  218. {squad-1.88 → squad-1.89}/squad/core/migrations/0027_project_notification_strategy.py +0 -0
  219. {squad-1.88 → squad-1.89}/squad/core/migrations/0028_suite_and_test_name_length.py +0 -0
  220. {squad-1.88 → squad-1.89}/squad/core/migrations/0029_subscription_email_formats.py +0 -0
  221. {squad-1.88 → squad-1.89}/squad/core/migrations/0030_remove_project_build_completion_threshold.py +0 -0
  222. {squad-1.88 → squad-1.89}/squad/core/migrations/0031_environment_expected_test_runs.py +0 -0
  223. {squad-1.88 → squad-1.89}/squad/core/migrations/0032_testrun_completed.py +0 -0
  224. {squad-1.88 → squad-1.89}/squad/core/migrations/0033_drop_debversion.py +0 -0
  225. {squad-1.88 → squad-1.89}/squad/core/migrations/0034_prepare_to_remove_build_name.py +0 -0
  226. {squad-1.88 → squad-1.89}/squad/core/migrations/0035_remove_build_name.py +0 -0
  227. {squad-1.88 → squad-1.89}/squad/core/migrations/0036_status_tests_skip.py +0 -0
  228. {squad-1.88 → squad-1.89}/squad/core/migrations/0037_project_status_test_summary_fields.py +0 -0
  229. {squad-1.88 → squad-1.89}/squad/core/migrations/0038_populate_project_status_cache.py +0 -0
  230. {squad-1.88 → squad-1.89}/squad/core/migrations/0039_orderings.py +0 -0
  231. {squad-1.88 → squad-1.89}/squad/core/migrations/0040_remove_subscription_html.py +0 -0
  232. {squad-1.88 → squad-1.89}/squad/core/migrations/0041_projectstatus_notified.py +0 -0
  233. {squad-1.88 → squad-1.89}/squad/core/migrations/0042_set_projectstatus_notified.py +0 -0
  234. {squad-1.88 → squad-1.89}/squad/core/migrations/0043_project_status_build.py +0 -0
  235. {squad-1.88 → squad-1.89}/squad/core/migrations/0044_project_html_mail.py +0 -0
  236. {squad-1.88 → squad-1.89}/squad/core/migrations/0045_adminsubscription.py +0 -0
  237. {squad-1.88 → squad-1.89}/squad/core/migrations/0046_projectstatus_last_updated.py +0 -0
  238. {squad-1.88 → squad-1.89}/squad/core/migrations/0047_populate_projectstatus_last_updated.py +0 -0
  239. {squad-1.88 → squad-1.89}/squad/core/migrations/0048_moderate_notifications.py +0 -0
  240. {squad-1.88 → squad-1.89}/squad/core/migrations/0049_projectstatus_plural.py +0 -0
  241. {squad-1.88 → squad-1.89}/squad/core/migrations/0050_projectstatus_finished.py +0 -0
  242. {squad-1.88 → squad-1.89}/squad/core/migrations/0051_build_status.py +0 -0
  243. {squad-1.88 → squad-1.89}/squad/core/migrations/0052_recreate_projectstatus_data.py +0 -0
  244. {squad-1.88 → squad-1.89}/squad/core/migrations/0053_remove_projectstatus_previous.py +0 -0
  245. {squad-1.88 → squad-1.89}/squad/core/migrations/0054_custom_email_template.py +0 -0
  246. {squad-1.88 → squad-1.89}/squad/core/migrations/0055_emailtemplate_subject.py +0 -0
  247. {squad-1.88 → squad-1.89}/squad/core/migrations/0056_project_description.py +0 -0
  248. {squad-1.88 → squad-1.89}/squad/core/migrations/0057_projectstatus_has_metrics.py +0 -0
  249. {squad-1.88 → squad-1.89}/squad/core/migrations/0058_populate_projectstatus_has_metrics.py +0 -0
  250. {squad-1.88 → squad-1.89}/squad/core/migrations/0059_project_important_metadata_keys.py +0 -0
  251. {squad-1.88 → squad-1.89}/squad/core/migrations/0060_test_log.py +0 -0
  252. {squad-1.88 → squad-1.89}/squad/core/migrations/0061_project_enabled_plugins_list.py +0 -0
  253. {squad-1.88 → squad-1.89}/squad/core/migrations/0062_project_allow_empty_enabled_plugin_list.py +0 -0
  254. {squad-1.88 → squad-1.89}/squad/core/migrations/0063_project_wait_before_notification.py +0 -0
  255. {squad-1.88 → squad-1.89}/squad/core/migrations/0064_project_notification_timeout.py +0 -0
  256. {squad-1.88 → squad-1.89}/squad/core/migrations/0065_projectstatus_notified_on_timeout.py +0 -0
  257. {squad-1.88 → squad-1.89}/squad/core/migrations/0066_environment_description.py +0 -0
  258. {squad-1.88 → squad-1.89}/squad/core/migrations/0067_accept_blank_suite_name.py +0 -0
  259. {squad-1.88 → squad-1.89}/squad/core/migrations/0068_suite_version.py +0 -0
  260. {squad-1.88 → squad-1.89}/squad/core/migrations/0069_suite_metadata.py +0 -0
  261. {squad-1.88 → squad-1.89}/squad/core/migrations/0070_create_suite_test_and_metric_metadata.py +0 -0
  262. {squad-1.88 → squad-1.89}/squad/core/migrations/0071_migrate_old_tokens.py +0 -0
  263. {squad-1.88 → squad-1.89}/squad/core/migrations/0072_group_description.py +0 -0
  264. {squad-1.88 → squad-1.89}/squad/core/migrations/0073_auto_20180420_1643.py +0 -0
  265. {squad-1.88 → squad-1.89}/squad/core/migrations/0074_add_indexes.py +0 -0
  266. {squad-1.88 → squad-1.89}/squad/core/migrations/0075_update_project_enabled_plugin_list.py +0 -0
  267. {squad-1.88 → squad-1.89}/squad/core/migrations/0076_patch_builds.py +0 -0
  268. {squad-1.88 → squad-1.89}/squad/core/migrations/0077_knownissue.py +0 -0
  269. {squad-1.88 → squad-1.89}/squad/core/migrations/0078_cache_test_run_counts.py +0 -0
  270. {squad-1.88 → squad-1.89}/squad/core/migrations/0079_init_cache_test_run_counts.py +0 -0
  271. {squad-1.88 → squad-1.89}/squad/core/migrations/0080_auto_20180810_0047.py +0 -0
  272. {squad-1.88 → squad-1.89}/squad/core/migrations/0081_status_has_metrics.py +0 -0
  273. {squad-1.88 → squad-1.89}/squad/core/migrations/0082_populate_status_has_metrics.py +0 -0
  274. {squad-1.88 → squad-1.89}/squad/core/migrations/0083_rename_knownissue_environments.py +0 -0
  275. {squad-1.88 → squad-1.89}/squad/core/migrations/0084_projectstatus_regressions_fixes.py +0 -0
  276. {squad-1.88 → squad-1.89}/squad/core/migrations/0085_projectstatus_defaults.py +0 -0
  277. {squad-1.88 → squad-1.89}/squad/core/migrations/0086_xfail.py +0 -0
  278. {squad-1.88 → squad-1.89}/squad/core/migrations/0087_test_known_issues.py +0 -0
  279. {squad-1.88 → squad-1.89}/squad/core/migrations/0088_user_subscriptions.py +0 -0
  280. {squad-1.88 → squad-1.89}/squad/core/migrations/0089_test_has_known_issues.py +0 -0
  281. {squad-1.88 → squad-1.89}/squad/core/migrations/0090_populate_test_has_known_issues.py +0 -0
  282. {squad-1.88 → squad-1.89}/squad/core/migrations/0091_notification_delivery_remove_unique_status.py +0 -0
  283. {squad-1.88 → squad-1.89}/squad/core/migrations/0092_annotation.py +0 -0
  284. {squad-1.88 → squad-1.89}/squad/core/migrations/0093_historicalemailtemplate.py +0 -0
  285. {squad-1.88 → squad-1.89}/squad/core/migrations/0094_populatehistoricalemailtemplate.py +0 -0
  286. {squad-1.88 → squad-1.89}/squad/core/migrations/0095_project_data_retention_days.py +0 -0
  287. {squad-1.88 → squad-1.89}/squad/core/migrations/0096_build_keep_data.py +0 -0
  288. {squad-1.88 → squad-1.89}/squad/core/migrations/0097_build_placeholder.py +0 -0
  289. {squad-1.88 → squad-1.89}/squad/core/migrations/0098_blank_annotation.py +0 -0
  290. {squad-1.88 → squad-1.89}/squad/core/migrations/0099_metricthreshold.py +0 -0
  291. {squad-1.88 → squad-1.89}/squad/core/migrations/0100_metric_is_outlier.py +0 -0
  292. {squad-1.88 → squad-1.89}/squad/core/migrations/0101_project_project_settings.py +0 -0
  293. {squad-1.88 → squad-1.89}/squad/core/migrations/0102_projectstatus_null_metric_summary.py +0 -0
  294. {squad-1.88 → squad-1.89}/squad/core/migrations/0103_populate_project_status.py +0 -0
  295. {squad-1.88 → squad-1.89}/squad/core/migrations/0104_delayedreport.py +0 -0
  296. {squad-1.88 → squad-1.89}/squad/core/migrations/0105_delayed_report_error_message.py +0 -0
  297. {squad-1.88 → squad-1.89}/squad/core/migrations/0106_delayedreport_output_subject.py +0 -0
  298. {squad-1.88 → squad-1.89}/squad/core/migrations/0107_move_notification_strategy.py +0 -0
  299. {squad-1.88 → squad-1.89}/squad/core/migrations/0108_add_email_template_validator.py +0 -0
  300. {squad-1.88 → squad-1.89}/squad/core/migrations/0109_group_member.py +0 -0
  301. {squad-1.88 → squad-1.89}/squad/core/migrations/0110_move_users_from_django_groups_to_squad_groups.py +0 -0
  302. {squad-1.88 → squad-1.89}/squad/core/migrations/0111_remove_group_user_groups.py +0 -0
  303. {squad-1.88 → squad-1.89}/squad/core/migrations/0112_user_namespaces.py +0 -0
  304. {squad-1.88 → squad-1.89}/squad/core/migrations/0113_group_project_blank_name_and_description.py +0 -0
  305. {squad-1.88 → squad-1.89}/squad/core/migrations/0114_project_enabled_plugin_list_can_be_blank.py +0 -0
  306. {squad-1.88 → squad-1.89}/squad/core/migrations/0115_fix_slug_validation.py +0 -0
  307. {squad-1.88 → squad-1.89}/squad/core/migrations/0116_make_group_membership_unique.py +0 -0
  308. {squad-1.88 → squad-1.89}/squad/core/migrations/0117_drop_obsolete_token_model.py +0 -0
  309. {squad-1.88 → squad-1.89}/squad/core/migrations/0118_project_is_archived.py +0 -0
  310. {squad-1.88 → squad-1.89}/squad/core/migrations/0119_i18n.py +0 -0
  311. {squad-1.88 → squad-1.89}/squad/core/migrations/0120_buildsummary.py +0 -0
  312. {squad-1.88 → squad-1.89}/squad/core/migrations/0121_add_password_patchsource.py +0 -0
  313. {squad-1.88 → squad-1.89}/squad/core/migrations/0122_fix_patchsource_url_and_token.py +0 -0
  314. {squad-1.88 → squad-1.89}/squad/core/migrations/0123_django_upgrade_missing_migrations.py +0 -0
  315. {squad-1.88 → squad-1.89}/squad/core/migrations/0124_set_default_expected_test_runs_to_zero.py +0 -0
  316. {squad-1.88 → squad-1.89}/squad/core/migrations/0125_fix_missing_status_has_metrics_for_testruns.py +0 -0
  317. {squad-1.88 → squad-1.89}/squad/core/migrations/0126_metricthreshold_environment.py +0 -0
  318. {squad-1.88 → squad-1.89}/squad/core/migrations/0127_metric_thresholds_migrate_data.py +0 -0
  319. {squad-1.88 → squad-1.89}/squad/core/migrations/0128_metric_thresholds_remove_proj_col.py +0 -0
  320. {squad-1.88 → squad-1.89}/squad/core/migrations/0129_projectstatus_nullable_notified_on_timeout.py +0 -0
  321. {squad-1.88 → squad-1.89}/squad/core/migrations/0130_project_status_baseline_next.py +0 -0
  322. {squad-1.88 → squad-1.89}/squad/core/migrations/0131_create_squad_auth_group_and_add_users.py +0 -0
  323. {squad-1.88 → squad-1.89}/squad/core/migrations/0132_attachment_mimetype.py +0 -0
  324. {squad-1.88 → squad-1.89}/squad/core/migrations/0133_append_project_permissions_to_squad_auth_group.py +0 -0
  325. {squad-1.88 → squad-1.89}/squad/core/migrations/0134_longer_metric_name.py +0 -0
  326. {squad-1.88 → squad-1.89}/squad/core/migrations/0135_add_privileged_access_level.py +0 -0
  327. {squad-1.88 → squad-1.89}/squad/core/migrations/0136_migrate_submitters_to_privileged.py +0 -0
  328. {squad-1.88 → squad-1.89}/squad/core/migrations/0137_patchsource_token_null.py +0 -0
  329. {squad-1.88 → squad-1.89}/squad/core/migrations/0138_metric_unit.py +0 -0
  330. {squad-1.88 → squad-1.89}/squad/core/migrations/0139_nullable_test_name.py +0 -0
  331. {squad-1.88 → squad-1.89}/squad/core/migrations/0140_increase_gerrit_password_length.py +0 -0
  332. {squad-1.88 → squad-1.89}/squad/core/migrations/0141_remove_test_name.py +0 -0
  333. {squad-1.88 → squad-1.89}/squad/core/migrations/0142_add_testrun_file_storage.py +0 -0
  334. {squad-1.88 → squad-1.89}/squad/core/migrations/0143_attachment_storage.py +0 -0
  335. {squad-1.88 → squad-1.89}/squad/core/migrations/0144_attachment_data_null.py +0 -0
  336. {squad-1.88 → squad-1.89}/squad/core/migrations/0145_pluginscratch.py +0 -0
  337. {squad-1.88 → squad-1.89}/squad/core/migrations/0146_deprecate_testrun_and_attachment_data_fields.py +0 -0
  338. {squad-1.88 → squad-1.89}/squad/core/migrations/0147_add_build_and_environment_to_test.py +0 -0
  339. {squad-1.88 → squad-1.89}/squad/core/migrations/0148_remove_legacy_storage_fields.py +0 -0
  340. {squad-1.88 → squad-1.89}/squad/core/migrations/0149_build_patch_url.py +0 -0
  341. {squad-1.88 → squad-1.89}/squad/core/migrations/0150_add_new_notification_strategy.py +0 -0
  342. {squad-1.88 → squad-1.89}/squad/core/migrations/0151_callback.py +0 -0
  343. {squad-1.88 → squad-1.89}/squad/core/migrations/0152_add_build_patch_notified.py +0 -0
  344. {squad-1.88 → squad-1.89}/squad/core/migrations/0153_callback_make_response_content_blob.py +0 -0
  345. {squad-1.88 → squad-1.89}/squad/core/migrations/0154_project_add_force_finishing_builds_field.py +0 -0
  346. {squad-1.88 → squad-1.89}/squad/core/migrations/0155_add_build_and_environment_to_metric.py +0 -0
  347. {squad-1.88 → squad-1.89}/squad/core/migrations/0156_nullable_metric_name.py +0 -0
  348. {squad-1.88 → squad-1.89}/squad/core/migrations/0157_remove_metric_name.py +0 -0
  349. {squad-1.88 → squad-1.89}/squad/core/migrations/0158_add_metric_comparison_to_projectstatus.py +0 -0
  350. {squad-1.88 → squad-1.89}/squad/core/migrations/0159_nullable_metricthreshold_value.py +0 -0
  351. {squad-1.88 → squad-1.89}/squad/core/migrations/0160_add_project_to_metricthreshold.py +0 -0
  352. {squad-1.88 → squad-1.89}/squad/core/migrations/0161_add_metricthreshold_perm_to_squad_group.py +0 -0
  353. {squad-1.88 → squad-1.89}/squad/core/migrations/0162_project_add_build_confidence_settings.py +0 -0
  354. {squad-1.88 → squad-1.89}/squad/core/migrations/0163_hirtoricalemailtemplate_update.py +0 -0
  355. {squad-1.88 → squad-1.89}/squad/core/migrations/0164_django_update.py +0 -0
  356. {squad-1.88 → squad-1.89}/squad/core/migrations/0165_buildsummary_uniqueness.py +0 -0
  357. {squad-1.88 → squad-1.89}/squad/core/migrations/0166_build_is_release.py +0 -0
  358. {squad-1.88 → squad-1.89}/squad/core/migrations/0167_add_project_datetime.py +0 -0
  359. {squad-1.88 → squad-1.89}/squad/core/migrations/0168_add_group_settings.py +0 -0
  360. {squad-1.88 → squad-1.89}/squad/core/migrations/0169_userpreferences.py +0 -0
  361. {squad-1.88 → squad-1.89}/squad/core/migrations/__init__.py +0 -0
  362. {squad-1.88 → squad-1.89}/squad/core/notification.py +0 -0
  363. {squad-1.88 → squad-1.89}/squad/core/plugins.py +0 -0
  364. {squad-1.88 → squad-1.89}/squad/core/queries.py +0 -0
  365. {squad-1.88 → squad-1.89}/squad/core/statistics.py +0 -0
  366. {squad-1.88 → squad-1.89}/squad/core/tasks/__init__.py +0 -0
  367. {squad-1.88 → squad-1.89}/squad/core/tasks/exceptions.py +0 -0
  368. {squad-1.88 → squad-1.89}/squad/core/tasks/notification.py +0 -0
  369. {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/base.jinja2 +0 -0
  370. {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/diff.html.jinja2 +0 -0
  371. {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/diff.txt.jinja2 +0 -0
  372. {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/failed_test_jobs.html.jinja2 +0 -0
  373. {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/failed_test_jobs.txt.jinja2 +0 -0
  374. {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/moderation.html.jinja2 +0 -0
  375. {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/moderation.txt.jinja2 +0 -0
  376. {squad-1.88 → squad-1.89}/squad/core/templatetags/__init__.py +0 -0
  377. {squad-1.88 → squad-1.89}/squad/core/templatetags/squad_notification.py +0 -0
  378. {squad-1.88 → squad-1.89}/squad/frontend/__init__.py +0 -0
  379. {squad-1.88 → squad-1.89}/squad/frontend/__main__.py +0 -0
  380. {squad-1.88 → squad-1.89}/squad/frontend/admin.py +0 -0
  381. {squad-1.88 → squad-1.89}/squad/frontend/apps.py +0 -0
  382. {squad-1.88 → squad-1.89}/squad/frontend/badges.py +0 -0
  383. {squad-1.88 → squad-1.89}/squad/frontend/build_settings.py +0 -0
  384. {squad-1.88 → squad-1.89}/squad/frontend/ci.py +0 -0
  385. {squad-1.88 → squad-1.89}/squad/frontend/extract.py +0 -0
  386. {squad-1.88 → squad-1.89}/squad/frontend/forms.py +0 -0
  387. {squad-1.88 → squad-1.89}/squad/frontend/group_settings.py +0 -0
  388. {squad-1.88 → squad-1.89}/squad/frontend/locale/django.pot +0 -0
  389. {squad-1.88 → squad-1.89}/squad/frontend/locale/pl/LC_MESSAGES/django.po +0 -0
  390. {squad-1.88 → squad-1.89}/squad/frontend/locale/pt/LC_MESSAGES/django.po +0 -0
  391. {squad-1.88 → squad-1.89}/squad/frontend/locale/pt_BR/LC_MESSAGES/django.po +0 -0
  392. {squad-1.88 → squad-1.89}/squad/frontend/management/__init__.py +0 -0
  393. {squad-1.88 → squad-1.89}/squad/frontend/management/commands/__init__.py +0 -0
  394. {squad-1.88 → squad-1.89}/squad/frontend/management/commands/get_token.py +0 -0
  395. {squad-1.88 → squad-1.89}/squad/frontend/metrics.py +0 -0
  396. {squad-1.88 → squad-1.89}/squad/frontend/project_settings.py +0 -0
  397. {squad-1.88 → squad-1.89}/squad/frontend/queries.py +0 -0
  398. {squad-1.88 → squad-1.89}/squad/frontend/setup.py +0 -0
  399. {squad-1.88 → squad-1.89}/squad/frontend/static/compare.css +0 -0
  400. {squad-1.88 → squad-1.89}/squad/frontend/static/download +0 -0
  401. {squad-1.88 → squad-1.89}/squad/frontend/static/download.conf +0 -0
  402. {squad-1.88 → squad-1.89}/squad/frontend/static/favicon.ico +0 -0
  403. {squad-1.88 → squad-1.89}/squad/frontend/static/main.css +0 -0
  404. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/attach_select2.js +0 -0
  405. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/build.js +0 -0
  406. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/build_compare.js +0 -0
  407. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/build_list.js +0 -0
  408. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/charts.js +0 -0
  409. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/common.js +0 -0
  410. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/compare.js +0 -0
  411. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/config.js +0 -0
  412. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/annotation.js +0 -0
  413. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/build_compare.js +0 -0
  414. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/build_list_compare.js +0 -0
  415. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/build_release.js +0 -0
  416. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/cancel.js +0 -0
  417. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/charts.js +0 -0
  418. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/compare.js +0 -0
  419. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/fetch.js +0 -0
  420. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/filter.js +0 -0
  421. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/metricThreshold.js +0 -0
  422. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/project_compare.js +0 -0
  423. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/resubmit.js +0 -0
  424. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/testjobs_progress.js +0 -0
  425. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/metric.threshold.js +0 -0
  426. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/project_compare.js +0 -0
  427. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/showHide.js +0 -0
  428. {squad-1.88 → squad-1.89}/squad/frontend/static/squad/table.js +0 -0
  429. {squad-1.88 → squad-1.89}/squad/frontend/static/squad_sign.svg +0 -0
  430. {squad-1.88 → squad-1.89}/squad/frontend/templates/401.jinja2 +0 -0
  431. {squad-1.88 → squad-1.89}/squad/frontend/templates/404.jinja2 +0 -0
  432. {squad-1.88 → squad-1.89}/squad/frontend/templates/django/rest_framework/api.html +0 -0
  433. {squad-1.88 → squad-1.89}/squad/frontend/templates/django/squad/_user_menu.html +0 -0
  434. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_builds_table.jinja2 +0 -0
  435. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_env_suite_data.jinja2 +0 -0
  436. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_metadata.jinja2 +0 -0
  437. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_pagination.jinja2 +0 -0
  438. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_permissions.jinja2 +0 -0
  439. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_project_list.jinja2 +0 -0
  440. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_regressions_and_fixes.jinja2 +0 -0
  441. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_results_table.jinja2 +0 -0
  442. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_results_transitions_filter.jinja2 +0 -0
  443. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_subscribe.jinja2 +0 -0
  444. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_results_envbox.jinja2 +0 -0
  445. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_results_suitebox.jinja2 +0 -0
  446. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_results_summary.jinja2 +0 -0
  447. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_results_table.jinja2 +0 -0
  448. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_run_metric.jinja2 +0 -0
  449. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_run_test.jinja2 +0 -0
  450. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_unfinished_build.jinja2 +0 -0
  451. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_user_menu.jinja2 +0 -0
  452. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/base.jinja2 +0 -0
  453. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build-nav.jinja2 +0 -0
  454. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build.jinja2 +0 -0
  455. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build_callbacks.jinja2 +0 -0
  456. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build_metadata.jinja2 +0 -0
  457. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build_metrics.jinja2 +0 -0
  458. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build_settings.jinja2 +0 -0
  459. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/builds.jinja2 +0 -0
  460. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/compare.jinja2 +0 -0
  461. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/compare_builds.jinja2 +0 -0
  462. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/compare_projects.jinja2 +0 -0
  463. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group-nav.jinja2 +0 -0
  464. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group.jinja2 +0 -0
  465. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/advanced.jinja2 +0 -0
  466. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/base.jinja2 +0 -0
  467. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/delete.jinja2 +0 -0
  468. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/index.jinja2 +0 -0
  469. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/members.jinja2 +0 -0
  470. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/new_group.jinja2 +0 -0
  471. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/new_project.jinja2 +0 -0
  472. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/index.jinja2 +0 -0
  473. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/knownissues.jinja2 +0 -0
  474. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/login.jinja2 +0 -0
  475. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/metrics.jinja2 +0 -0
  476. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project-nav.jinja2 +0 -0
  477. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project.jinja2 +0 -0
  478. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/_threshold_table.jinja2 +0 -0
  479. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/advanced.jinja2 +0 -0
  480. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/base.jinja2 +0 -0
  481. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/build_confidence.jinja2 +0 -0
  482. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/delete.jinja2 +0 -0
  483. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/environments.jinja2 +0 -0
  484. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/index.jinja2 +0 -0
  485. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/thresholds.jinja2 +0 -0
  486. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/test_history.jinja2 +0 -0
  487. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/test_run.jinja2 +0 -0
  488. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/test_run_suite_metrics.jinja2 +0 -0
  489. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/test_run_suite_test_details.jinja2 +0 -0
  490. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/test_run_suite_tests.jinja2 +0 -0
  491. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/testjob.jinja2 +0 -0
  492. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/testjobs.jinja2 +0 -0
  493. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/testjobs_progress.jinja2 +0 -0
  494. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/tests-details-nav.jinja2 +0 -0
  495. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/tests.jinja2 +0 -0
  496. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/api_token.jinja2 +0 -0
  497. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/base.jinja2 +0 -0
  498. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/profile.jinja2 +0 -0
  499. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/projects.jinja2 +0 -0
  500. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/subscriptions.jinja2 +0 -0
  501. {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/user_preferences.jinja2 +0 -0
  502. {squad-1.88 → squad-1.89}/squad/frontend/templatetags/__init__.py +0 -0
  503. {squad-1.88 → squad-1.89}/squad/frontend/templatetags/squad.py +0 -0
  504. {squad-1.88 → squad-1.89}/squad/frontend/urls.py +0 -0
  505. {squad-1.88 → squad-1.89}/squad/frontend/user_settings.py +0 -0
  506. {squad-1.88 → squad-1.89}/squad/frontend/utils.py +0 -0
  507. {squad-1.88 → squad-1.89}/squad/frontend/views.py +0 -0
  508. {squad-1.88 → squad-1.89}/squad/http.py +0 -0
  509. {squad-1.88 → squad-1.89}/squad/jinja2.py +0 -0
  510. {squad-1.88 → squad-1.89}/squad/mail.py +0 -0
  511. {squad-1.88 → squad-1.89}/squad/manage.py +0 -0
  512. {squad-1.88 → squad-1.89}/squad/plugins/__init__.py +0 -0
  513. {squad-1.88 → squad-1.89}/squad/plugins/example.py +0 -0
  514. {squad-1.88 → squad-1.89}/squad/plugins/gerrit.py +0 -0
  515. {squad-1.88 → squad-1.89}/squad/plugins/github.py +0 -0
  516. {squad-1.88 → squad-1.89}/squad/run/__init__.py +0 -0
  517. {squad-1.88 → squad-1.89}/squad/run/__main__.py +0 -0
  518. {squad-1.88 → squad-1.89}/squad/run/listener.py +0 -0
  519. {squad-1.88 → squad-1.89}/squad/run/scheduler.py +0 -0
  520. {squad-1.88 → squad-1.89}/squad/run/worker.py +0 -0
  521. {squad-1.88 → squad-1.89}/squad/settings.py +0 -0
  522. {squad-1.88 → squad-1.89}/squad/socialaccount.py +0 -0
  523. {squad-1.88 → squad-1.89}/squad/urls.py +0 -0
  524. {squad-1.88 → squad-1.89}/squad/wsgi.py +0 -0
  525. {squad-1.88 → squad-1.89}/squad.egg-info/SOURCES.txt +0 -0
  526. {squad-1.88 → squad-1.89}/squad.egg-info/dependency_links.txt +0 -0
  527. {squad-1.88 → squad-1.89}/squad.egg-info/entry_points.txt +0 -0
  528. {squad-1.88 → squad-1.89}/squad.egg-info/requires.txt +0 -0
  529. {squad-1.88 → squad-1.89}/squad.egg-info/top_level.txt +0 -0
  530. {squad-1.88 → squad-1.89}/squad.svg +0 -0
  531. {squad-1.88 → squad-1.89}/test/__init__.py +0 -0
  532. {squad-1.88 → squad-1.89}/test/api/__init__.py +0 -0
  533. {squad-1.88 → squad-1.89}/test/api/benchmarks.csv +0 -0
  534. {squad-1.88 → squad-1.89}/test/api/benchmarks.json +0 -0
  535. {squad-1.88 → squad-1.89}/test/api/definition.yaml +0 -0
  536. {squad-1.88 → squad-1.89}/test/api/metadata.json +0 -0
  537. {squad-1.88 → squad-1.89}/test/api/test_ci.py +0 -0
  538. {squad-1.88 → squad-1.89}/test/api/test_data.py +0 -0
  539. {squad-1.88 → squad-1.89}/test/api/test_rest.py +0 -0
  540. {squad-1.88 → squad-1.89}/test/api/test_run.log +0 -0
  541. {squad-1.88 → squad-1.89}/test/api/tests.csv +0 -0
  542. {squad-1.88 → squad-1.89}/test/api/tests.json +0 -0
  543. {squad-1.88 → squad-1.89}/test/api/tests.py +0 -0
  544. {squad-1.88 → squad-1.89}/test/api/tests_log.json +0 -0
  545. {squad-1.88 → squad-1.89}/test/api/tests_two.json +0 -0
  546. {squad-1.88 → squad-1.89}/test/api/twoline_definition.yaml +0 -0
  547. {squad-1.88 → squad-1.89}/test/ci/__init__.py +0 -0
  548. {squad-1.88 → squad-1.89}/test/ci/backend/__init__.py +0 -0
  549. {squad-1.88 → squad-1.89}/test/ci/backend/example-broken-log.yaml +0 -0
  550. {squad-1.88 → squad-1.89}/test/ci/backend/example-lava-log.yaml +0 -0
  551. {squad-1.88 → squad-1.89}/test/ci/backend/lava.json +0 -0
  552. {squad-1.88 → squad-1.89}/test/ci/backend/test_fake.py +0 -0
  553. {squad-1.88 → squad-1.89}/test/ci/backend/test_real_lava.py +0 -0
  554. {squad-1.88 → squad-1.89}/test/ci/backend/test_tuxsuite.py +0 -0
  555. {squad-1.88 → squad-1.89}/test/ci/backend/tuxsuite_test_failed_result_sample.json +0 -0
  556. {squad-1.88 → squad-1.89}/test/ci/backend/tuxsuite_test_result_sample.json +0 -0
  557. {squad-1.88 → squad-1.89}/test/ci/test_listen.py +0 -0
  558. {squad-1.88 → squad-1.89}/test/ci/test_models.py +0 -0
  559. {squad-1.88 → squad-1.89}/test/core/__init__.py +0 -0
  560. {squad-1.88 → squad-1.89}/test/core/test_attachment.py +0 -0
  561. {squad-1.88 → squad-1.89}/test/core/test_build.py +0 -0
  562. {squad-1.88 → squad-1.89}/test/core/test_build_summary.py +0 -0
  563. {squad-1.88 → squad-1.89}/test/core/test_emailtemplate.py +0 -0
  564. {squad-1.88 → squad-1.89}/test/core/test_failures.py +0 -0
  565. {squad-1.88 → squad-1.89}/test/core/test_group.py +0 -0
  566. {squad-1.88 → squad-1.89}/test/core/test_historical_emailtemplate.py +0 -0
  567. {squad-1.88 → squad-1.89}/test/core/test_import_data.py +0 -0
  568. {squad-1.88 → squad-1.89}/test/core/test_import_data_input/1/default/1/metadata.json +0 -0
  569. {squad-1.88 → squad-1.89}/test/core/test_import_data_input/1/default/1/metrics.json +0 -0
  570. {squad-1.88 → squad-1.89}/test/core/test_import_data_input/2/default/2/metadata.json +0 -0
  571. {squad-1.88 → squad-1.89}/test/core/test_import_data_input/2/default/2/metrics.json +0 -0
  572. {squad-1.88 → squad-1.89}/test/core/test_import_data_input/2/default/2/screenshot.png +0 -0
  573. {squad-1.88 → squad-1.89}/test/core/test_import_data_input/2/default/2/tests.json +0 -0
  574. {squad-1.88 → squad-1.89}/test/core/test_import_data_missing_metadata/1/1/tests.json +0 -0
  575. {squad-1.88 → squad-1.89}/test/core/test_known_issues.py +0 -0
  576. {squad-1.88 → squad-1.89}/test/core/test_metric.py +0 -0
  577. {squad-1.88 → squad-1.89}/test/core/test_metric_comparison.py +0 -0
  578. {squad-1.88 → squad-1.89}/test/core/test_metric_threshold.py +0 -0
  579. {squad-1.88 → squad-1.89}/test/core/test_metrics_data.py +0 -0
  580. {squad-1.88 → squad-1.89}/test/core/test_metrics_summary.py +0 -0
  581. {squad-1.88 → squad-1.89}/test/core/test_notification.py +0 -0
  582. {squad-1.88 → squad-1.89}/test/core/test_notification_delivery.py +0 -0
  583. {squad-1.88 → squad-1.89}/test/core/test_patch_source.py +0 -0
  584. {squad-1.88 → squad-1.89}/test/core/test_project.py +0 -0
  585. {squad-1.88 → squad-1.89}/test/core/test_statistics.py +0 -0
  586. {squad-1.88 → squad-1.89}/test/core/test_tasks.py +0 -0
  587. {squad-1.88 → squad-1.89}/test/core/test_tasks_notification.py +0 -0
  588. {squad-1.88 → squad-1.89}/test/core/test_test.py +0 -0
  589. {squad-1.88 → squad-1.89}/test/core/test_test_comparison.py +0 -0
  590. {squad-1.88 → squad-1.89}/test/core/test_test_data.py +0 -0
  591. {squad-1.88 → squad-1.89}/test/core/test_test_run.py +0 -0
  592. {squad-1.88 → squad-1.89}/test/core/test_test_summary.py +0 -0
  593. {squad-1.88 → squad-1.89}/test/core/test_user_namespace.py +0 -0
  594. {squad-1.88 → squad-1.89}/test/core/test_utils.py +0 -0
  595. {squad-1.88 → squad-1.89}/test/frontend/__init__.py +0 -0
  596. {squad-1.88 → squad-1.89}/test/frontend/test_basics.py +0 -0
  597. {squad-1.88 → squad-1.89}/test/frontend/test_get_token_command.py +0 -0
  598. {squad-1.88 → squad-1.89}/test/frontend/test_group_settings.py +0 -0
  599. {squad-1.88 → squad-1.89}/test/frontend/test_history.py +0 -0
  600. {squad-1.88 → squad-1.89}/test/frontend/test_template_tags.py +0 -0
  601. {squad-1.88 → squad-1.89}/test/frontend/test_test_job.py +0 -0
  602. {squad-1.88 → squad-1.89}/test/frontend/test_tests.py +0 -0
  603. {squad-1.88 → squad-1.89}/test/frontend/test_utils.py +0 -0
  604. {squad-1.88 → squad-1.89}/test/integration/__init__.py +0 -0
  605. {squad-1.88 → squad-1.89}/test/integration/plugins/test_tradefed.py +0 -0
  606. {squad-1.88 → squad-1.89}/test/integration/plugins/tradefed-output-20220608105250.tar.xz +0 -0
  607. {squad-1.88 → squad-1.89}/test/integration/test_build_notification_from_ci.py +0 -0
  608. {squad-1.88 → squad-1.89}/test/javascript.py +0 -0
  609. {squad-1.88 → squad-1.89}/test/karma.conf.js +0 -0
  610. {squad-1.88 → squad-1.89}/test/mock.py +0 -0
  611. {squad-1.88 → squad-1.89}/test/performance.py +0 -0
  612. {squad-1.88 → squad-1.89}/test/plugins/__init__.py +0 -0
  613. {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kasan.log +0 -0
  614. {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kernel_bug_and_invalid_opcode.log +0 -0
  615. {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kernelexceptiontrace.log +0 -0
  616. {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kernelexceptiontrace_without_squarebraces.log +0 -0
  617. {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kernelpanic.log +0 -0
  618. {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kfence.log +0 -0
  619. {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/multiple_issues_dmesg.log +0 -0
  620. {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/oops.log +0 -0
  621. {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/rcu_warning.log +0 -0
  622. {squad-1.88 → squad-1.89}/test/plugins/test_gerrit.py +0 -0
  623. {squad-1.88 → squad-1.89}/test/plugins/test_github.py +0 -0
  624. {squad-1.88 → squad-1.89}/test/plugins/test_plugin.py +0 -0
  625. {squad-1.88 → squad-1.89}/test/settings.py +0 -0
  626. {squad-1.88 → squad-1.89}/test/test_architecture.py +0 -0
  627. {squad-1.88 → squad-1.89}/test/test_code_quality.py +0 -0
  628. {squad-1.88 → squad-1.89}/test/test_cors.py +0 -0
  629. {squad-1.88 → squad-1.89}/test/test_i18n.py +0 -0
  630. {squad-1.88 → squad-1.89}/test/test_mail.py +0 -0
  631. {squad-1.88 → squad-1.89}/test/test_pending_migrations.py +0 -0
  632. {squad-1.88 → squad-1.89}/test/unit/test_annotation.js +0 -0
  633. {squad-1.88 → squad-1.89}/test/unit/test_cancel.js +0 -0
  634. {squad-1.88 → squad-1.89}/test/unit/test_charts.js +0 -0
  635. {squad-1.88 → squad-1.89}/test/unit/test_compare.js +0 -0
  636. {squad-1.88 → squad-1.89}/test/unit/test_filter.js +0 -0
  637. {squad-1.88 → squad-1.89}/test/unit/test_resubmit.js +0 -0
@@ -1,3 +1,23 @@
1
+ # 1.89
2
+
3
+ This 1.89 release comes with quite several changes:
4
+
5
+ * api/rest.py: check if callback exception has messages attribute
6
+ * ci:
7
+ * backend/lava.py:
8
+ * add sanity check in job_name
9
+ * fix cases for empty job_name in definition
10
+ * ci/tasks.py:
11
+ * check if job exists before fetching
12
+ * do not fetch jobs without job_id
13
+ * core/models.py: prevend malformed yaml to be saved
14
+ * core/callback.py: handle requests exceptions
15
+ * core/history.py: check for empty projects
16
+ * frontend/comparison.py: sanity check project slug
17
+ * plugins/linux_log_parser:
18
+ * Add support for test name regex
19
+ * Move test name regex to higher level
20
+
1
21
  # 1.88
2
22
 
3
23
  This 1.88 release adds a neat feature that gives the user the exact log link
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: squad
3
- Version: 1.88
3
+ Version: 1.89
4
4
  Summary: Software Quality Dashboard
5
5
  Home-page: https://github.com/Linaro/squad
6
6
  Author: Antonio Terceiro
@@ -1190,7 +1190,13 @@ class BuildViewSet(NestedViewSetMixin, ModelViewSet):
1190
1190
  raise ValidationError('url is required.')
1191
1191
  return Response({'message': 'OK'}, status=status.HTTP_202_ACCEPTED)
1192
1192
  except (ValidationError, IntegrityError) as e:
1193
- return Response({'message': ', '.join(e.messages)}, status=status.HTTP_400_BAD_REQUEST)
1193
+ message = ""
1194
+ if hasattr(e, "messages"):
1195
+ message = ', '.join(e.messages)
1196
+ else:
1197
+ message = str(e)
1198
+
1199
+ return Response({'message': message}, status=status.HTTP_400_BAD_REQUEST)
1194
1200
 
1195
1201
  @action(detail=True, methods=['get'], suffix='compare')
1196
1202
  def compare(self, request, pk=None):
@@ -396,9 +396,10 @@ class Backend(BaseBackend):
396
396
 
397
397
  def __lava_job_name(self, definition):
398
398
  yaml_definition = yaml.safe_load(definition)
399
- if 'job_name' in yaml_definition.keys():
399
+ if type(yaml_definition) is dict and 'job_name' in yaml_definition.keys():
400
+ job_name = yaml_definition['job_name']
400
401
  # only return first 255 characters
401
- return yaml_definition['job_name'][:255]
402
+ return job_name[:255] if job_name else ''
402
403
  return None
403
404
 
404
405
  def __resubmit__(self, job_id):
@@ -27,8 +27,12 @@ def poll(backend_id=None):
27
27
  @celery.task
28
28
  def fetch(job_id):
29
29
  logger.info("fetching %s" % job_id)
30
- backend = TestJob.objects.get(pk=job_id).backend
31
- backend.fetch(job_id)
30
+ try:
31
+ testjob = TestJob.objects.get(pk=job_id)
32
+ if testjob.job_id:
33
+ testjob.backend.fetch(testjob.id)
34
+ except TestJob.DoesNotExist:
35
+ return
32
36
 
33
37
 
34
38
  @celery.task
@@ -56,12 +56,18 @@ def dispatch_callback(callback_object):
56
56
  else:
57
57
  args['data'] = json.loads(callback_object.payload)
58
58
 
59
- request = getattr(requests, callback_object.method)
60
- response = request(callback_object.url, **args)
59
+ try:
60
+ request = getattr(requests, callback_object.method)
61
+ response = request(callback_object.url, **args)
62
+ response_code = response.status_code
63
+ response_content = response.content
64
+ except requests.exceptions.RequestException as e:
65
+ response_code = None
66
+ response_content = str(e)
61
67
 
62
68
  if callback_object.record_response:
63
- callback_object.response_code = response.status_code
64
- callback_object.response_content = response.content
69
+ callback_object.response_code = response_code
70
+ callback_object.response_content = response_content
65
71
 
66
72
  callback_object.is_sent = True
67
73
  callback_object.save()
@@ -3,7 +3,7 @@ from django.core.paginator import Paginator
3
3
 
4
4
  from squad.core.queries import test_confidence
5
5
  from squad.core.utils import parse_name
6
- from squad.core.models import SuiteMetadata, KnownIssue, Environment
6
+ from squad.core.models import SuiteMetadata, KnownIssue, Environment, Build
7
7
 
8
8
 
9
9
  class TestResult(object):
@@ -49,6 +49,9 @@ class TestHistory(object):
49
49
  self.number = page
50
50
  builds = self.paginator.page(page)
51
51
 
52
+ if len(builds) == 0:
53
+ raise Build.DoesNotExist
54
+
52
55
  self.top = builds[0]
53
56
 
54
57
  issues_by_env = {}
@@ -16,7 +16,7 @@ from django.db.models.query import prefetch_related_objects
16
16
  from django.contrib.auth.models import User, AnonymousUser, Group as auth_group
17
17
  from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
18
18
  from django.contrib.contenttypes.models import ContentType
19
- from django.db.models.signals import post_save, pre_delete
19
+ from django.db.models.signals import post_save, pre_delete, pre_save
20
20
  from django.dispatch import receiver
21
21
 
22
22
  from django.conf import settings
@@ -1428,9 +1428,13 @@ class ProjectStatus(models.Model, TestSummaryBase):
1428
1428
  return None
1429
1429
 
1430
1430
  def __get_yaml_field__(self, field_value):
1431
- if field_value is not None:
1431
+ if field_value is None:
1432
+ return {}
1433
+
1434
+ try:
1432
1435
  return yaml.load(field_value, Loader=yaml.Loader)
1433
- return {}
1436
+ except yaml.YAMLError:
1437
+ return {}
1434
1438
 
1435
1439
  def get_regressions(self):
1436
1440
  return self.__get_yaml_field__(self.regressions)
@@ -1467,6 +1471,14 @@ class ProjectStatus(models.Model, TestSummaryBase):
1467
1471
  return thresholds_exceeded
1468
1472
 
1469
1473
 
1474
+ @receiver(pre_save, sender=ProjectStatus)
1475
+ def validate_project_status(sender, instance, *args, **kwargs):
1476
+ yaml_validator(instance.regressions)
1477
+ yaml_validator(instance.fixes)
1478
+ yaml_validator(instance.metric_regressions)
1479
+ yaml_validator(instance.metric_fixes)
1480
+
1481
+
1470
1482
  class NotificationDelivery(models.Model):
1471
1483
 
1472
1484
  status = models.ForeignKey('ProjectStatus', related_name='deliveries', on_delete=models.CASCADE)
@@ -67,7 +67,7 @@ def yaml_validator(value):
67
67
  if len(value) == 0:
68
68
  return
69
69
  try:
70
- if not isinstance(yaml.safe_load(value), dict):
70
+ if not isinstance(yaml.load(value, Loader=yaml.Loader), dict):
71
71
  raise ValidationError("Dictionary object expected")
72
72
  except yaml.YAMLError as e:
73
73
  raise ValidationError(e)
@@ -3,6 +3,7 @@ from functools import reduce
3
3
  from django.shortcuts import render, get_object_or_404
4
4
  from django.core.paginator import Paginator
5
5
  from django.db.models import Q, Prefetch
6
+ from django.http import HttpResponseNotFound
6
7
 
7
8
  from squad.core.models import Project, Group, Build
8
9
  from squad.core.comparison import TestComparison, MetricComparison
@@ -107,7 +108,11 @@ def compare_builds(request):
107
108
  comparison = None
108
109
  project = None
109
110
  if project_slug:
110
- group_slug, project_slug = project_slug.split('/')
111
+ group_and_project = project_slug.split('/')
112
+ if len(group_and_project) != 2:
113
+ return HttpResponseNotFound()
114
+
115
+ group_slug, project_slug = group_and_project
111
116
  project = get_object_or_404(Project, group__slug=group_slug, slug=project_slug)
112
117
 
113
118
  baseline_build = request.GET.get('baseline')
@@ -6,7 +6,7 @@ from django.shortcuts import render, get_object_or_404
6
6
  from django.http import Http404
7
7
 
8
8
  from squad.http import auth
9
- from squad.core.models import Test, Suite, SuiteMetadata, Environment
9
+ from squad.core.models import Build, Test, Suite, SuiteMetadata, Environment
10
10
  from squad.core.history import TestHistory
11
11
  from squad.core.queries import test_confidence
12
12
  from squad.frontend.views import get_build
@@ -234,5 +234,5 @@ def test_history(request, group_slug, project_slug, build_version=None, testrun_
234
234
  history = TestHistory(project, full_test_name, top=top, page=page)
235
235
  context.update({"history": history})
236
236
  return render(request, 'squad/test_history.jinja2', context)
237
- except (Suite.DoesNotExist, SuiteMetadata.DoesNotExist) as e:
237
+ except (Suite.DoesNotExist, SuiteMetadata.DoesNotExist, Build.DoesNotExist) as e:
238
238
  raise Http404(f"Test not found: {e}")
@@ -0,0 +1,183 @@
1
+ import hashlib
2
+ import logging
3
+ import re
4
+ from collections import defaultdict
5
+ from squad.plugins import Plugin as BasePlugin
6
+ from squad.core.models import SuiteMetadata
7
+ from django.template.defaultfilters import slugify
8
+
9
+
10
+ logger = logging.getLogger()
11
+
12
+ REGEX_NAME = 0
13
+ REGEX_BODY = 1
14
+ REGEX_EXTRACT_NAME = 2
15
+
16
+ MULTILINERS = [
17
+ ('check-kernel-exception', r'-+\[? cut here \]?-+.*?-+\[? end trace \w* \]?-+', r"\d][^\+\n]*"),
18
+ ('check-kernel-kasan', r'=+\n\[[\s\.\d]+\]\s+BUG: KASAN:.*?=+', r"BUG: KASAN:[^\+\n]*"),
19
+ ('check-kernel-kfence', r'=+\n\[[\s\.\d]+\]\s+BUG: KFENCE:.*?=+', r"BUG: KFENCE:[^\+\n]*"),
20
+ ]
21
+
22
+ ONELINERS = [
23
+ ('check-kernel-oops', r'^[^\n]+Oops(?: -|:).*?$', r"Oops[^\+\n]*"),
24
+ ('check-kernel-fault', r'^[^\n]+Unhandled fault.*?$', r"Unhandled [^\+\n]*"),
25
+ ('check-kernel-warning', r'^[^\n]+WARNING:.*?$', r"WARNING: [^\+\n]*"),
26
+ ('check-kernel-bug', r'^[^\n]+(?: kernel BUG at|BUG:).*?$', r"BUG[^\+\n]*"),
27
+ ('check-kernel-invalid-opcode', r'^[^\n]+invalid opcode:.*?$', r"invalid opcode: [^\+\n]*"),
28
+ ('check-kernel-panic', r'Kernel panic - not syncing.*?$', r"Kernel [^\+\n]*"),
29
+ ]
30
+
31
+ # Tip: broader regexes should come first
32
+ REGEXES = MULTILINERS + ONELINERS
33
+
34
+
35
+ class Plugin(BasePlugin):
36
+ def __compile_regexes(self, regexes):
37
+ combined = [r'(%s)' % r[REGEX_BODY] for r in regexes]
38
+ return re.compile(r'|'.join(combined), re.S | re.M)
39
+
40
+ def __cutoff_boot_log(self, log):
41
+ # Attempt to split the log in " login:"
42
+ logs = log.split(' login:', 1)
43
+
44
+ # 1 string means no split was done, consider all logs as test log
45
+ if len(logs) == 1:
46
+ return '', log
47
+
48
+ boot_log = logs[0]
49
+ test_log = logs[1]
50
+ return boot_log, test_log
51
+
52
+ def __kernel_msgs_only(self, log):
53
+ kernel_msgs = re.findall(r'(\[[ \d]+\.[ \d]+\] .*?)$', log, re.S | re.M)
54
+ return '\n'.join(kernel_msgs)
55
+
56
+ def __join_matches(self, matches, regexes):
57
+ """
58
+ group regex in python are returned as a list of tuples which each
59
+ group match in one of the positions in the tuple. Example:
60
+ regex = r'(a)|(b)|(c)'
61
+ matches = [
62
+ ('match a', '', ''),
63
+ ('', 'match b', ''),
64
+ ('match a', '', ''),
65
+ ('', '', 'match c')
66
+ ]
67
+ """
68
+ snippets = {regex_id: [] for regex_id in range(len(regexes))}
69
+ for match in matches:
70
+ for regex_id in range(len(regexes)):
71
+ if len(match[regex_id]) > 0:
72
+ snippets[regex_id].append(match[regex_id])
73
+ return snippets
74
+
75
+ def __create_tests(self, testrun, suite, test_name, lines, test_regex=None):
76
+ """
77
+ There will be at least one test per regex. If there were any match for a given
78
+ regex, then a new test will be generated using test_name + shasum. This helps
79
+ comparing kernel logs accross different builds
80
+ """
81
+ # Run the REGEX_EXTRACT_NAME regex over the log lines to sort them by
82
+ # extracted name. If no name is extracted or the log parser did not
83
+ # have any output for a particular regex, just use the default name
84
+ # (for example "check-kernel-oops").
85
+ tests_to_create = defaultdict(set)
86
+ shas = defaultdict(set)
87
+
88
+ # If there are no lines, use the default name and create a passing
89
+ # test. For example "check-kernel-oops"
90
+ if not lines:
91
+ tests_to_create[test_name] = []
92
+
93
+ # If there are lines, then create the tests for these.
94
+ for line in lines:
95
+ extracted_name = self.__create_name(line, test_regex)
96
+ if extracted_name:
97
+ extended_test_name = f"{test_name}-{extracted_name}"
98
+ else:
99
+ extended_test_name = test_name
100
+ tests_to_create[extended_test_name].add(line)
101
+
102
+ for name, lines in tests_to_create.items():
103
+ metadata, _ = SuiteMetadata.objects.get_or_create(suite=suite.slug, name=name, kind='test')
104
+ testrun.tests.create(
105
+ suite=suite,
106
+ result=(len(lines) == 0),
107
+ log='\n'.join(lines),
108
+ metadata=metadata,
109
+ build=testrun.build,
110
+ environment=testrun.environment,
111
+ )
112
+
113
+ # Some lines of the matched regex might be the same, and we don't want to create
114
+ # multiple tests like test1-sha1, test1-sha1, etc, so we'll create a set of sha1sums
115
+ # then create only new tests for unique sha's
116
+
117
+ for line in lines:
118
+ sha = self.__create_shasum(line)
119
+ name_with_sha = f"{name}-{sha}"
120
+ shas[name_with_sha].add(line)
121
+
122
+ for name_with_sha, lines in shas.items():
123
+ metadata, _ = SuiteMetadata.objects.get_or_create(suite=suite.slug, name=name_with_sha, kind='test')
124
+ testrun.tests.create(
125
+ suite=suite,
126
+ result=False,
127
+ log='\n---\n'.join(lines),
128
+ metadata=metadata,
129
+ build=testrun.build,
130
+ environment=testrun.environment,
131
+ )
132
+
133
+ def __remove_numbers_and_time(self, snippet):
134
+ without_numbers = re.sub(r"(0x[a-f0-9]+|[<\[][0-9a-f]+?[>\]]|\d+)", "", snippet)
135
+ without_time = re.sub(r"^\[[^\]]+\]", "", without_numbers)
136
+
137
+ return without_time
138
+
139
+ def __create_name(self, snippet, regex=None):
140
+ matches = None
141
+ if regex:
142
+ matches = regex.findall(snippet)
143
+ if not matches:
144
+ return None
145
+ snippet = matches[0]
146
+ without_numbers_and_time = self.__remove_numbers_and_time(snippet)
147
+
148
+ # Limit the name length to 191 characters, since the max name length
149
+ # for SuiteMetadata in SQUAD is 256 characters. The SHA and "-" take 65
150
+ # characters: 256-65=191
151
+ return slugify(without_numbers_and_time)[:191]
152
+
153
+ def __create_shasum(self, snippet):
154
+ sha = hashlib.sha256()
155
+ without_numbers_and_time = self.__remove_numbers_and_time(snippet)
156
+ sha.update(without_numbers_and_time.encode())
157
+ return sha.hexdigest()
158
+
159
+ def postprocess_testrun(self, testrun):
160
+ if testrun.log_file is None:
161
+ return
162
+
163
+ boot_log, test_log = self.__cutoff_boot_log(testrun.log_file)
164
+ logs = {
165
+ 'boot': boot_log,
166
+ 'test': test_log,
167
+ }
168
+
169
+ for log_type, log in logs.items():
170
+ log = self.__kernel_msgs_only(log)
171
+ suite, _ = testrun.build.project.suites.get_or_create(slug=f'log-parser-{log_type}')
172
+
173
+ regex = self.__compile_regexes(REGEXES)
174
+ matches = regex.findall(log)
175
+ snippets = self.__join_matches(matches, REGEXES)
176
+
177
+ for regex_id in range(len(REGEXES)):
178
+ test_name = REGEXES[regex_id][REGEX_NAME]
179
+ regex_pattern = REGEXES[regex_id][REGEX_EXTRACT_NAME]
180
+ test_name_regex = None
181
+ if regex_pattern:
182
+ test_name_regex = re.compile(regex_pattern, re.S | re.M)
183
+ self.__create_tests(testrun, suite, test_name, snippets[regex_id], test_name_regex)
@@ -0,0 +1 @@
1
+ __version__ = '1.89'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: squad
3
- Version: 1.88
3
+ Version: 1.89
4
4
  Summary: Software Quality Dashboard
5
5
  Home-page: https://github.com/Linaro/squad
6
6
  Author: Antonio Terceiro
@@ -448,6 +448,16 @@ class LavaTest(TestCase):
448
448
  check = lava.check_job_definition(definition)
449
449
  self.assertIn('found unexpected end of stream', check)
450
450
 
451
+ def test_lava_job_name(self):
452
+ lava = LAVABackend(None)
453
+ self.assertIsNone(lava._Backend__lava_job_name('no name:'))
454
+ self.assertIsNone(lava._Backend__lava_job_name('- list'))
455
+ self.assertIsNone(lava._Backend__lava_job_name('string'))
456
+ self.assertEqual('', lava._Backend__lava_job_name('job_name:'))
457
+ self.assertEqual('job-name', lava._Backend__lava_job_name('job_name: job-name'))
458
+ truncated_name = lava._Backend__lava_job_name('job_name: ' + ('a' * 300))
459
+ self.assertEqual(255, len(truncated_name))
460
+
451
461
  @patch("requests.post", side_effect=requests.exceptions.Timeout)
452
462
  def test_submit_timeout(self, post):
453
463
  test_definition = "foo: 1\njob_name: bar"
@@ -122,6 +122,21 @@ class FetchTest(TestCase):
122
122
  self.test_job.refresh_from_db()
123
123
  self.assertEqual(attemps + 1, self.test_job.fetch_attempts)
124
124
 
125
+ @patch('squad.ci.models.Backend.fetch')
126
+ def test_fetch_no_job_id(self, fetch_method):
127
+ testjob = models.TestJob.objects.create(
128
+ backend=self.test_job.backend,
129
+ target=self.test_job.target,
130
+ target_build=self.test_job.target_build,
131
+ )
132
+ fetch.apply(args=[testjob.id])
133
+ fetch_method.assert_not_called()
134
+
135
+ @patch('squad.ci.models.Backend.fetch')
136
+ def test_fetch_deleted_job(self, fetch_method):
137
+ fetch.apply(args=[99999999999])
138
+ fetch_method.assert_not_called()
139
+
125
140
 
126
141
  class FetchTestRaceCondition(TransactionTestCase):
127
142
 
@@ -134,21 +149,23 @@ class FetchTestRaceCondition(TransactionTestCase):
134
149
  backend=backend,
135
150
  target=project,
136
151
  target_build=build,
152
+ job_id='test',
137
153
  )
138
154
 
139
155
  def mock_backend_fetch(test_job):
140
- time.sleep(1)
156
+ time.sleep(0.5)
141
157
  status = ''
142
158
  completed = True
143
159
  metadata = {}
144
- tests = []
145
- metrics = []
160
+ tests = {}
161
+ metrics = {}
146
162
  logs = ''
147
163
  return status, completed, metadata, tests, metrics, logs
148
164
 
149
165
  @tag('skip_sqlite')
166
+ @patch('squad.ci.backend.null.Backend.job_url', return_value='http://url')
150
167
  @patch('squad.ci.backend.null.Backend.fetch', side_effect=mock_backend_fetch)
151
- def test_race_condition_on_fetch(self, fetch_method):
168
+ def test_race_condition_on_fetch(self, fetch_method, job_url_method):
152
169
 
153
170
  def thread(testjob_id):
154
171
  fetch(testjob_id)
@@ -1,4 +1,5 @@
1
1
  import json
2
+ import requests
2
3
 
3
4
 
4
5
  from django.test import TestCase
@@ -98,6 +99,19 @@ class CallbackTest(TestCase):
98
99
  callback.dispatch()
99
100
  self.assertFalse(requests_post.called)
100
101
 
102
+ @patch('requests.post')
103
+ def test_build_callback_catch_exceptions_on_dispatch(self, requests_post):
104
+ requests_post.side_effect = requests.exceptions.ConnectionError("bad connection")
105
+
106
+ url = 'http://callback-target.com'
107
+
108
+ callback = self.build.callbacks.create(url=url, event=self.event, record_response=True)
109
+ callback.dispatch()
110
+
111
+ self.assertTrue(requests_post.called)
112
+ self.assertTrue(callback.is_sent)
113
+ self.assertEqual("bad connection", callback.response_content)
114
+
101
115
  @patch('requests.post')
102
116
  def test_build_callback_gets_deleted_on_build_deletion(self, requests_post):
103
117
  url = 'http://callback-target.com'
@@ -113,3 +113,10 @@ class TestHistoryTest(TestCase):
113
113
  history = TestHistory(self.project1, test_name)
114
114
 
115
115
  self.assertIsNotNone(history.results)
116
+
117
+ def test_no_build(self):
118
+ empty_project = self.group.projects.create(slug='empty-project')
119
+ test_name = 'fake_test'
120
+
121
+ with self.assertRaises(models.Build.DoesNotExist):
122
+ TestHistory(empty_project, test_name)
@@ -1,3 +1,4 @@
1
+ from django.core.exceptions import ValidationError
1
2
  from django.utils import timezone
2
3
  from django.test import TestCase
3
4
  from dateutil.relativedelta import relativedelta
@@ -436,3 +437,19 @@ class ProjectStatusTest(TestCase):
436
437
 
437
438
  self.assertEqual(build2.status.baseline, build1)
438
439
  self.assertEqual(build3.status.baseline, build1)
440
+
441
+ def test_save_malformed_yaml(self):
442
+ build = self.project.builds.create(version="bad-yaml")
443
+ build.status.fixes = """!!python/object/apply:collections.OrderedDict
444
+ - - - env
445
+ - [suite/test"""
446
+ with self.assertRaises(ValidationError):
447
+ build.status.save()
448
+
449
+ def test_get_malformed_yaml(self):
450
+ # For backwards compatibility, records with bad yaml already saved
451
+ build = self.project.builds.create(version="bad-yaml")
452
+ build.status.fixes = """!!python/object/apply:collections.OrderedDict
453
+ - - - env
454
+ - [suite/test"""
455
+ self.assertEqual(0, len(build.status.get_fixes()))
@@ -27,13 +27,13 @@ class UpdateStatusesTest(TestCase):
27
27
  build1.save()
28
28
 
29
29
  status1 = ProjectStatus.objects.first()
30
- status1.fixes = "fixes1"
30
+ status1.fixes = "fixes:\n- fix1"
31
31
  status1.finished = True
32
32
  status1.save()
33
33
 
34
34
  self.create_build('2')
35
35
  status2 = ProjectStatus.objects.last()
36
- status2.fixes = "fixes2"
36
+ status2.fixes = "fixes:\n- fix2"
37
37
  status2.finished = True
38
38
  status2.save()
39
39
 
@@ -42,5 +42,5 @@ class UpdateStatusesTest(TestCase):
42
42
  status1.refresh_from_db()
43
43
  status2.refresh_from_db()
44
44
 
45
- self.assertEqual(status1.fixes, "fixes1")
46
- self.assertNotEqual(status2.fixes, "fixes2")
45
+ self.assertEqual(status1.get_fixes(), {"fixes": ["fix1"]})
46
+ self.assertEqual(status2.get_fixes(), {})
@@ -78,3 +78,11 @@ class ProjectComparisonTest(TestCase):
78
78
  self.assertIn('otherenv', str(response.content))
79
79
  self.assertIn('pass', str(response.content))
80
80
  self.assertIn('fail', str(response.content))
81
+
82
+
83
+ class BuildComparisonTest(TestCase):
84
+
85
+ def test_comparison_malformed_project_slug(self):
86
+ url = '/_/comparebuilds/?project=something-bad'
87
+ response = self.client.get(url)
88
+ self.assertEqual(404, response.status_code)