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.
- {squad-1.88 → squad-1.89}/CHANGELOG.md +20 -0
- {squad-1.88 → squad-1.89}/PKG-INFO +1 -1
- {squad-1.88 → squad-1.89}/squad/api/rest.py +7 -1
- {squad-1.88 → squad-1.89}/squad/ci/backend/lava.py +3 -2
- {squad-1.88 → squad-1.89}/squad/ci/tasks.py +6 -2
- {squad-1.88 → squad-1.89}/squad/core/callback.py +10 -4
- {squad-1.88 → squad-1.89}/squad/core/history.py +4 -1
- {squad-1.88 → squad-1.89}/squad/core/models.py +15 -3
- {squad-1.88 → squad-1.89}/squad/core/utils.py +1 -1
- {squad-1.88 → squad-1.89}/squad/frontend/comparison.py +6 -1
- {squad-1.88 → squad-1.89}/squad/frontend/tests.py +2 -2
- squad-1.89/squad/plugins/linux_log_parser.py +183 -0
- squad-1.89/squad/version.py +1 -0
- {squad-1.88 → squad-1.89}/squad.egg-info/PKG-INFO +1 -1
- {squad-1.88 → squad-1.89}/test/ci/backend/test_lava.py +10 -0
- {squad-1.88 → squad-1.89}/test/ci/test_tasks.py +21 -4
- {squad-1.88 → squad-1.89}/test/core/test_callback.py +14 -0
- {squad-1.88 → squad-1.89}/test/core/test_history.py +7 -0
- {squad-1.88 → squad-1.89}/test/core/test_project_status.py +17 -0
- {squad-1.88 → squad-1.89}/test/core/test_update_project_statuses.py +4 -4
- {squad-1.88 → squad-1.89}/test/frontend/test_comparison.py +8 -0
- {squad-1.88 → squad-1.89}/test/plugins/test_linux_log_parser.py +62 -19
- squad-1.88/squad/plugins/linux_log_parser.py +0 -136
- squad-1.88/squad/version.py +0 -1
- {squad-1.88 → squad-1.89}/.ackrc +0 -0
- {squad-1.88 → squad-1.89}/.coveragerc +0 -0
- {squad-1.88 → squad-1.89}/.ctags +0 -0
- {squad-1.88 → squad-1.89}/.dockerignore +0 -0
- {squad-1.88 → squad-1.89}/.github/workflows/release.yml +0 -0
- {squad-1.88 → squad-1.89}/.github/workflows/test.yml +0 -0
- {squad-1.88 → squad-1.89}/.gitignore +0 -0
- {squad-1.88 → squad-1.89}/.mailmap +0 -0
- {squad-1.88 → squad-1.89}/.readthedocs.yml +0 -0
- {squad-1.88 → squad-1.89}/.reuse/dep5 +0 -0
- {squad-1.88 → squad-1.89}/COPYING +0 -0
- {squad-1.88 → squad-1.89}/COPYRIGHTS +0 -0
- {squad-1.88 → squad-1.89}/Dockerfile +0 -0
- {squad-1.88 → squad-1.89}/LICENSES/GPL-3.0-or-later.txt +0 -0
- {squad-1.88 → squad-1.89}/LICENSES/MIT.txt +0 -0
- {squad-1.88 → squad-1.89}/LICENSES/OFL-1.1.txt +0 -0
- {squad-1.88 → squad-1.89}/MANIFEST.in +0 -0
- {squad-1.88 → squad-1.89}/Procfile +0 -0
- {squad-1.88 → squad-1.89}/README.rst +0 -0
- {squad-1.88 → squad-1.89}/babel.cfg +0 -0
- {squad-1.88 → squad-1.89}/dev-docker +0 -0
- {squad-1.88 → squad-1.89}/doc/.gitignore +0 -0
- {squad-1.88 → squad-1.89}/doc/Makefile +0 -0
- {squad-1.88 → squad-1.89}/doc/api.rst +0 -0
- {squad-1.88 → squad-1.89}/doc/ci.rst +0 -0
- {squad-1.88 → squad-1.89}/doc/conf.py +0 -0
- {squad-1.88 → squad-1.89}/doc/hacking.rst +0 -0
- {squad-1.88 → squad-1.89}/doc/index.rst +0 -0
- {squad-1.88 → squad-1.89}/doc/install.rst +0 -0
- {squad-1.88 → squad-1.89}/doc/intro.rst +0 -0
- {squad-1.88 → squad-1.89}/doc/lava_usecase.rst +0 -0
- {squad-1.88 → squad-1.89}/doc/plugins.rst +0 -0
- {squad-1.88 → squad-1.89}/doc/quickstart.rst +0 -0
- {squad-1.88 → squad-1.89}/doc/translating.rst +0 -0
- {squad-1.88 → squad-1.89}/doc/tuxsuite_usecase.rst +0 -0
- {squad-1.88 → squad-1.89}/docker/db-dumped +0 -0
- {squad-1.88 → squad-1.89}/docker/db-to-be-restored +0 -0
- {squad-1.88 → squad-1.89}/docker/docker-compose.yml +0 -0
- {squad-1.88 → squad-1.89}/docker/extra_settings.py +0 -0
- {squad-1.88 → squad-1.89}/docker/init-db.sh +0 -0
- {squad-1.88 → squad-1.89}/docker/rabbitmq.config +0 -0
- {squad-1.88 → squad-1.89}/docker/squad-apache.conf +0 -0
- {squad-1.88 → squad-1.89}/docker-compose.yaml +0 -0
- {squad-1.88 → squad-1.89}/manage.py +0 -0
- {squad-1.88 → squad-1.89}/package-lock.json +0 -0
- {squad-1.88 → squad-1.89}/package.json +0 -0
- {squad-1.88 → squad-1.89}/pytest.ini +0 -0
- {squad-1.88 → squad-1.89}/requirements-dev.txt +0 -0
- {squad-1.88 → squad-1.89}/requirements.txt +0 -0
- {squad-1.88 → squad-1.89}/scripts/build +0 -0
- {squad-1.88 → squad-1.89}/scripts/check-ci +0 -0
- {squad-1.88 → squad-1.89}/scripts/check-ignore +0 -0
- {squad-1.88 → squad-1.89}/scripts/community_connector/main.js +0 -0
- {squad-1.88 → squad-1.89}/scripts/community_connector/manifest.json +0 -0
- {squad-1.88 → squad-1.89}/scripts/dogfood +0 -0
- {squad-1.88 → squad-1.89}/scripts/get-metrics +0 -0
- {squad-1.88 → squad-1.89}/scripts/get-tests +0 -0
- {squad-1.88 → squad-1.89}/scripts/git-build +0 -0
- {squad-1.88 → squad-1.89}/scripts/pytest +0 -0
- {squad-1.88 → squad-1.89}/scripts/rabbitmq-server +0 -0
- {squad-1.88 → squad-1.89}/scripts/release +0 -0
- {squad-1.88 → squad-1.89}/scripts/release-docker +0 -0
- {squad-1.88 → squad-1.89}/scripts/squad-config +0 -0
- {squad-1.88 → squad-1.89}/scripts/test-ci +0 -0
- {squad-1.88 → squad-1.89}/scripts/test-docker +0 -0
- {squad-1.88 → squad-1.89}/scripts/testdata/gen-ci-jobs +0 -0
- {squad-1.88 → squad-1.89}/scripts/testdata/gen-metrics +0 -0
- {squad-1.88 → squad-1.89}/scripts/testdata/gen-test-data +0 -0
- {squad-1.88 → squad-1.89}/scripts/testdata/gen-tests +0 -0
- {squad-1.88 → squad-1.89}/scripts/testdata/setup-dev +0 -0
- {squad-1.88 → squad-1.89}/scripts/testdata/submit-ci-jobs +0 -0
- {squad-1.88 → squad-1.89}/scripts/testdata/submit-test-data +0 -0
- {squad-1.88 → squad-1.89}/scripts/translate +0 -0
- {squad-1.88 → squad-1.89}/scripts/travis-lava +0 -0
- {squad-1.88 → squad-1.89}/scripts/update-translation-files +0 -0
- {squad-1.88 → squad-1.89}/scripts/upload +0 -0
- {squad-1.88 → squad-1.89}/setup.cfg +0 -0
- {squad-1.88 → squad-1.89}/setup.py +0 -0
- {squad-1.88 → squad-1.89}/squad/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/admin.py +0 -0
- {squad-1.88 → squad-1.89}/squad/api/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/api/apps.py +0 -0
- {squad-1.88 → squad-1.89}/squad/api/ci.py +0 -0
- {squad-1.88 → squad-1.89}/squad/api/data.py +0 -0
- {squad-1.88 → squad-1.89}/squad/api/filters.py +0 -0
- {squad-1.88 → squad-1.89}/squad/api/urls.py +0 -0
- {squad-1.88 → squad-1.89}/squad/api/utils.py +0 -0
- {squad-1.88 → squad-1.89}/squad/api/views.py +0 -0
- {squad-1.88 → squad-1.89}/squad/celery.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/admin.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/apps.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/backend/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/backend/fake.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/backend/null.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/backend/tuxsuite.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/exceptions.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/management/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/management/commands/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/management/commands/create_tuxsuite_boot_tests.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/management/commands/listen.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/management/commands/testfetch.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0001_initial.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0002_auto_20170406_1252.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0003_backend_name.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0004_testjob_failure.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0005_remove_listener_data.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0006_simplify_backend_loading.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0007_auto_20170517_1736.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0008_testjob_testrun.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0009_slug_pattern.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0010_testjob_can_resubmit.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0011_testjob_resubmitted_count.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0012_testjob_build.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0013_testjob_name.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0014_testjob_target_build.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0015_testjob_populate_target_build.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0016_backend_max_fetch_attempts.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0017_testjob_fetch_attempts.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0018_testjob_dates.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0019_add_fake_backend.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0020_backend_settings_field.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0021_testjob_parent_job.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0022_backend_poll_enabled.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0023_remove_testjob_build.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0024_fix_testjob_environment_validation.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0025_backend_listen_enabled.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0026_job_start_end_time.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0027_add_tuxsuite_implementation_type.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0028_create_testjob_indexes.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0029_create_testjob_results_input.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/0030_testjob_subtasks_count.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/migrations/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/models.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/templates/squad/ci/testjob_resubmit.html.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/templates/squad/ci/testjob_resubmit.txt.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/templatetags/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/templatetags/filter_jobs.py +0 -0
- {squad-1.88 → squad-1.89}/squad/ci/utils.py +0 -0
- {squad-1.88 → squad-1.89}/squad/compat.py +0 -0
- {squad-1.88 → squad-1.89}/squad/container_settings.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/admin.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/apps.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/comparison.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/data.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/failures.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/locale/django.pot +0 -0
- {squad-1.88 → squad-1.89}/squad/core/locale/es_MX/LC_MESSAGES/django.po +0 -0
- {squad-1.88 → squad-1.89}/squad/core/locale/pl/LC_MESSAGES/django.po +0 -0
- {squad-1.88 → squad-1.89}/squad/core/locale/pt/LC_MESSAGES/django.po +0 -0
- {squad-1.88 → squad-1.89}/squad/core/locale/pt_BR/LC_MESSAGES/django.po +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/compute_build_summaries.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/compute_project_statuses.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/fill_test_metadata.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/fix_squadplugin_data.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/import_data.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/import_data.rst +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/migrate_test_runs.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/populate_metric_build_and_environment.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/populate_test_build_and_environment.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/prepdump.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/send-email.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/update_project_statuses.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/management/commands/users.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0001_initial.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0002_auto_20160525_1403.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0003_testrun_log_file.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0004_group_user_groups.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0005_token.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0006_auto_20160826_2242.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0007_testrun_data_processed.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0008_status.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0009_testrun_status_recorded.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0010_testrun_datetime.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0011_testrun_metadata_fields.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0012_build_datetime.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0013_testrun_resubmit_url.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0014_testrun_metadata_file.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0015_attachment.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0016_project_is_public.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0017_slug_validator.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0018_build_name.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0019_build_version.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0020_build_ordering.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0021_global_tokens.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0022_projectstatus.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0023_subscription.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0024_project_build_completion_threshold.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0025_unique_testrun_job_id.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0026_testrun_result_accept_null.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0027_project_notification_strategy.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0028_suite_and_test_name_length.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0029_subscription_email_formats.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0030_remove_project_build_completion_threshold.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0031_environment_expected_test_runs.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0032_testrun_completed.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0033_drop_debversion.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0034_prepare_to_remove_build_name.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0035_remove_build_name.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0036_status_tests_skip.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0037_project_status_test_summary_fields.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0038_populate_project_status_cache.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0039_orderings.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0040_remove_subscription_html.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0041_projectstatus_notified.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0042_set_projectstatus_notified.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0043_project_status_build.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0044_project_html_mail.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0045_adminsubscription.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0046_projectstatus_last_updated.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0047_populate_projectstatus_last_updated.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0048_moderate_notifications.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0049_projectstatus_plural.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0050_projectstatus_finished.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0051_build_status.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0052_recreate_projectstatus_data.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0053_remove_projectstatus_previous.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0054_custom_email_template.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0055_emailtemplate_subject.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0056_project_description.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0057_projectstatus_has_metrics.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0058_populate_projectstatus_has_metrics.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0059_project_important_metadata_keys.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0060_test_log.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0061_project_enabled_plugins_list.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0062_project_allow_empty_enabled_plugin_list.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0063_project_wait_before_notification.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0064_project_notification_timeout.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0065_projectstatus_notified_on_timeout.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0066_environment_description.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0067_accept_blank_suite_name.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0068_suite_version.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0069_suite_metadata.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0070_create_suite_test_and_metric_metadata.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0071_migrate_old_tokens.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0072_group_description.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0073_auto_20180420_1643.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0074_add_indexes.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0075_update_project_enabled_plugin_list.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0076_patch_builds.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0077_knownissue.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0078_cache_test_run_counts.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0079_init_cache_test_run_counts.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0080_auto_20180810_0047.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0081_status_has_metrics.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0082_populate_status_has_metrics.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0083_rename_knownissue_environments.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0084_projectstatus_regressions_fixes.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0085_projectstatus_defaults.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0086_xfail.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0087_test_known_issues.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0088_user_subscriptions.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0089_test_has_known_issues.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0090_populate_test_has_known_issues.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0091_notification_delivery_remove_unique_status.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0092_annotation.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0093_historicalemailtemplate.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0094_populatehistoricalemailtemplate.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0095_project_data_retention_days.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0096_build_keep_data.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0097_build_placeholder.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0098_blank_annotation.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0099_metricthreshold.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0100_metric_is_outlier.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0101_project_project_settings.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0102_projectstatus_null_metric_summary.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0103_populate_project_status.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0104_delayedreport.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0105_delayed_report_error_message.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0106_delayedreport_output_subject.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0107_move_notification_strategy.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0108_add_email_template_validator.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0109_group_member.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0110_move_users_from_django_groups_to_squad_groups.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0111_remove_group_user_groups.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0112_user_namespaces.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0113_group_project_blank_name_and_description.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0114_project_enabled_plugin_list_can_be_blank.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0115_fix_slug_validation.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0116_make_group_membership_unique.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0117_drop_obsolete_token_model.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0118_project_is_archived.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0119_i18n.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0120_buildsummary.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0121_add_password_patchsource.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0122_fix_patchsource_url_and_token.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0123_django_upgrade_missing_migrations.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0124_set_default_expected_test_runs_to_zero.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0125_fix_missing_status_has_metrics_for_testruns.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0126_metricthreshold_environment.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0127_metric_thresholds_migrate_data.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0128_metric_thresholds_remove_proj_col.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0129_projectstatus_nullable_notified_on_timeout.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0130_project_status_baseline_next.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0131_create_squad_auth_group_and_add_users.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0132_attachment_mimetype.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0133_append_project_permissions_to_squad_auth_group.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0134_longer_metric_name.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0135_add_privileged_access_level.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0136_migrate_submitters_to_privileged.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0137_patchsource_token_null.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0138_metric_unit.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0139_nullable_test_name.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0140_increase_gerrit_password_length.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0141_remove_test_name.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0142_add_testrun_file_storage.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0143_attachment_storage.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0144_attachment_data_null.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0145_pluginscratch.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0146_deprecate_testrun_and_attachment_data_fields.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0147_add_build_and_environment_to_test.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0148_remove_legacy_storage_fields.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0149_build_patch_url.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0150_add_new_notification_strategy.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0151_callback.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0152_add_build_patch_notified.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0153_callback_make_response_content_blob.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0154_project_add_force_finishing_builds_field.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0155_add_build_and_environment_to_metric.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0156_nullable_metric_name.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0157_remove_metric_name.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0158_add_metric_comparison_to_projectstatus.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0159_nullable_metricthreshold_value.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0160_add_project_to_metricthreshold.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0161_add_metricthreshold_perm_to_squad_group.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0162_project_add_build_confidence_settings.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0163_hirtoricalemailtemplate_update.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0164_django_update.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0165_buildsummary_uniqueness.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0166_build_is_release.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0167_add_project_datetime.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0168_add_group_settings.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/0169_userpreferences.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/migrations/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/notification.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/plugins.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/queries.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/statistics.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/tasks/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/tasks/exceptions.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/tasks/notification.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/base.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/diff.html.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/diff.txt.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/failed_test_jobs.html.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/failed_test_jobs.txt.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/moderation.html.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/core/templates/squad/notification/moderation.txt.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/core/templatetags/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/core/templatetags/squad_notification.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/__main__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/admin.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/apps.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/badges.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/build_settings.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/ci.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/extract.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/forms.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/group_settings.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/locale/django.pot +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/locale/pl/LC_MESSAGES/django.po +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/locale/pt/LC_MESSAGES/django.po +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/locale/pt_BR/LC_MESSAGES/django.po +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/management/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/management/commands/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/management/commands/get_token.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/metrics.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/project_settings.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/queries.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/setup.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/compare.css +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/download +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/download.conf +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/favicon.ico +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/main.css +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/attach_select2.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/build.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/build_compare.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/build_list.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/charts.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/common.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/compare.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/config.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/annotation.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/build_compare.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/build_list_compare.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/build_release.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/cancel.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/charts.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/compare.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/fetch.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/filter.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/metricThreshold.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/project_compare.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/resubmit.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/controllers/testjobs_progress.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/metric.threshold.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/project_compare.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/showHide.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad/table.js +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/static/squad_sign.svg +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/401.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/404.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/django/rest_framework/api.html +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/django/squad/_user_menu.html +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_builds_table.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_env_suite_data.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_metadata.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_pagination.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_permissions.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_project_list.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_regressions_and_fixes.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_results_table.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_results_transitions_filter.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_subscribe.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_results_envbox.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_results_suitebox.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_results_summary.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_results_table.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_run_metric.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_test_run_test.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_unfinished_build.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/_user_menu.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/base.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build-nav.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build_callbacks.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build_metadata.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build_metrics.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/build_settings.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/builds.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/compare.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/compare_builds.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/compare_projects.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group-nav.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/advanced.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/base.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/delete.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/index.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/members.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/new_group.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/group_settings/new_project.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/index.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/knownissues.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/login.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/metrics.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project-nav.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/_threshold_table.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/advanced.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/base.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/build_confidence.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/delete.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/environments.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/index.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/project_settings/thresholds.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/test_history.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/test_run.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/test_run_suite_metrics.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/test_run_suite_test_details.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/test_run_suite_tests.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/testjob.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/testjobs.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/testjobs_progress.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/tests-details-nav.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/tests.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/api_token.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/base.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/profile.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/projects.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/subscriptions.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templates/squad/user_settings/user_preferences.jinja2 +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templatetags/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/templatetags/squad.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/urls.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/user_settings.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/utils.py +0 -0
- {squad-1.88 → squad-1.89}/squad/frontend/views.py +0 -0
- {squad-1.88 → squad-1.89}/squad/http.py +0 -0
- {squad-1.88 → squad-1.89}/squad/jinja2.py +0 -0
- {squad-1.88 → squad-1.89}/squad/mail.py +0 -0
- {squad-1.88 → squad-1.89}/squad/manage.py +0 -0
- {squad-1.88 → squad-1.89}/squad/plugins/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/plugins/example.py +0 -0
- {squad-1.88 → squad-1.89}/squad/plugins/gerrit.py +0 -0
- {squad-1.88 → squad-1.89}/squad/plugins/github.py +0 -0
- {squad-1.88 → squad-1.89}/squad/run/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/run/__main__.py +0 -0
- {squad-1.88 → squad-1.89}/squad/run/listener.py +0 -0
- {squad-1.88 → squad-1.89}/squad/run/scheduler.py +0 -0
- {squad-1.88 → squad-1.89}/squad/run/worker.py +0 -0
- {squad-1.88 → squad-1.89}/squad/settings.py +0 -0
- {squad-1.88 → squad-1.89}/squad/socialaccount.py +0 -0
- {squad-1.88 → squad-1.89}/squad/urls.py +0 -0
- {squad-1.88 → squad-1.89}/squad/wsgi.py +0 -0
- {squad-1.88 → squad-1.89}/squad.egg-info/SOURCES.txt +0 -0
- {squad-1.88 → squad-1.89}/squad.egg-info/dependency_links.txt +0 -0
- {squad-1.88 → squad-1.89}/squad.egg-info/entry_points.txt +0 -0
- {squad-1.88 → squad-1.89}/squad.egg-info/requires.txt +0 -0
- {squad-1.88 → squad-1.89}/squad.egg-info/top_level.txt +0 -0
- {squad-1.88 → squad-1.89}/squad.svg +0 -0
- {squad-1.88 → squad-1.89}/test/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/test/api/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/test/api/benchmarks.csv +0 -0
- {squad-1.88 → squad-1.89}/test/api/benchmarks.json +0 -0
- {squad-1.88 → squad-1.89}/test/api/definition.yaml +0 -0
- {squad-1.88 → squad-1.89}/test/api/metadata.json +0 -0
- {squad-1.88 → squad-1.89}/test/api/test_ci.py +0 -0
- {squad-1.88 → squad-1.89}/test/api/test_data.py +0 -0
- {squad-1.88 → squad-1.89}/test/api/test_rest.py +0 -0
- {squad-1.88 → squad-1.89}/test/api/test_run.log +0 -0
- {squad-1.88 → squad-1.89}/test/api/tests.csv +0 -0
- {squad-1.88 → squad-1.89}/test/api/tests.json +0 -0
- {squad-1.88 → squad-1.89}/test/api/tests.py +0 -0
- {squad-1.88 → squad-1.89}/test/api/tests_log.json +0 -0
- {squad-1.88 → squad-1.89}/test/api/tests_two.json +0 -0
- {squad-1.88 → squad-1.89}/test/api/twoline_definition.yaml +0 -0
- {squad-1.88 → squad-1.89}/test/ci/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/test/ci/backend/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/test/ci/backend/example-broken-log.yaml +0 -0
- {squad-1.88 → squad-1.89}/test/ci/backend/example-lava-log.yaml +0 -0
- {squad-1.88 → squad-1.89}/test/ci/backend/lava.json +0 -0
- {squad-1.88 → squad-1.89}/test/ci/backend/test_fake.py +0 -0
- {squad-1.88 → squad-1.89}/test/ci/backend/test_real_lava.py +0 -0
- {squad-1.88 → squad-1.89}/test/ci/backend/test_tuxsuite.py +0 -0
- {squad-1.88 → squad-1.89}/test/ci/backend/tuxsuite_test_failed_result_sample.json +0 -0
- {squad-1.88 → squad-1.89}/test/ci/backend/tuxsuite_test_result_sample.json +0 -0
- {squad-1.88 → squad-1.89}/test/ci/test_listen.py +0 -0
- {squad-1.88 → squad-1.89}/test/ci/test_models.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_attachment.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_build.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_build_summary.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_emailtemplate.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_failures.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_group.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_historical_emailtemplate.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_import_data.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_import_data_input/1/default/1/metadata.json +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_import_data_input/1/default/1/metrics.json +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_import_data_input/2/default/2/metadata.json +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_import_data_input/2/default/2/metrics.json +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_import_data_input/2/default/2/screenshot.png +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_import_data_input/2/default/2/tests.json +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_import_data_missing_metadata/1/1/tests.json +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_known_issues.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_metric.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_metric_comparison.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_metric_threshold.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_metrics_data.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_metrics_summary.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_notification.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_notification_delivery.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_patch_source.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_project.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_statistics.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_tasks.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_tasks_notification.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_test.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_test_comparison.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_test_data.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_test_run.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_test_summary.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_user_namespace.py +0 -0
- {squad-1.88 → squad-1.89}/test/core/test_utils.py +0 -0
- {squad-1.88 → squad-1.89}/test/frontend/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/test/frontend/test_basics.py +0 -0
- {squad-1.88 → squad-1.89}/test/frontend/test_get_token_command.py +0 -0
- {squad-1.88 → squad-1.89}/test/frontend/test_group_settings.py +0 -0
- {squad-1.88 → squad-1.89}/test/frontend/test_history.py +0 -0
- {squad-1.88 → squad-1.89}/test/frontend/test_template_tags.py +0 -0
- {squad-1.88 → squad-1.89}/test/frontend/test_test_job.py +0 -0
- {squad-1.88 → squad-1.89}/test/frontend/test_tests.py +0 -0
- {squad-1.88 → squad-1.89}/test/frontend/test_utils.py +0 -0
- {squad-1.88 → squad-1.89}/test/integration/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/test/integration/plugins/test_tradefed.py +0 -0
- {squad-1.88 → squad-1.89}/test/integration/plugins/tradefed-output-20220608105250.tar.xz +0 -0
- {squad-1.88 → squad-1.89}/test/integration/test_build_notification_from_ci.py +0 -0
- {squad-1.88 → squad-1.89}/test/javascript.py +0 -0
- {squad-1.88 → squad-1.89}/test/karma.conf.js +0 -0
- {squad-1.88 → squad-1.89}/test/mock.py +0 -0
- {squad-1.88 → squad-1.89}/test/performance.py +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/__init__.py +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kasan.log +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kernel_bug_and_invalid_opcode.log +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kernelexceptiontrace.log +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kernelexceptiontrace_without_squarebraces.log +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kernelpanic.log +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/kfence.log +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/multiple_issues_dmesg.log +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/oops.log +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/linux_log_parser/rcu_warning.log +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/test_gerrit.py +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/test_github.py +0 -0
- {squad-1.88 → squad-1.89}/test/plugins/test_plugin.py +0 -0
- {squad-1.88 → squad-1.89}/test/settings.py +0 -0
- {squad-1.88 → squad-1.89}/test/test_architecture.py +0 -0
- {squad-1.88 → squad-1.89}/test/test_code_quality.py +0 -0
- {squad-1.88 → squad-1.89}/test/test_cors.py +0 -0
- {squad-1.88 → squad-1.89}/test/test_i18n.py +0 -0
- {squad-1.88 → squad-1.89}/test/test_mail.py +0 -0
- {squad-1.88 → squad-1.89}/test/test_pending_migrations.py +0 -0
- {squad-1.88 → squad-1.89}/test/unit/test_annotation.js +0 -0
- {squad-1.88 → squad-1.89}/test/unit/test_cancel.js +0 -0
- {squad-1.88 → squad-1.89}/test/unit/test_charts.js +0 -0
- {squad-1.88 → squad-1.89}/test/unit/test_compare.js +0 -0
- {squad-1.88 → squad-1.89}/test/unit/test_filter.js +0 -0
- {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
|
@@ -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
|
-
|
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
|
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
|
-
|
31
|
-
|
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
|
-
|
60
|
-
|
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 =
|
64
|
-
callback_object.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
|
1431
|
+
if field_value is None:
|
1432
|
+
return {}
|
1433
|
+
|
1434
|
+
try:
|
1432
1435
|
return yaml.load(field_value, Loader=yaml.Loader)
|
1433
|
-
|
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.
|
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
|
-
|
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'
|
@@ -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(
|
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 = "
|
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 = "
|
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.
|
46
|
-
self.
|
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)
|