diff --git a/requirements-test.txt b/requirements-test.txt --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,6 +1,7 @@ decorator # dependency of swh.core[http] djangorestframework-stubs django-stubs +django-test-migrations hypothesis pytest pytest-django diff --git a/swh/web/common/migrations/0009_saveoriginrequest_visit_status.py b/swh/web/common/migrations/0009_saveoriginrequest_visit_status.py new file mode 100644 --- /dev/null +++ b/swh/web/common/migrations/0009_saveoriginrequest_visit_status.py @@ -0,0 +1,32 @@ +# Copyright (C) 2021 The Software Heritage developers +# See the AUTHORS file at the top-level directory of this distribution +# License: GNU General Public License version 3, or any later version +# See top-level LICENSE file for more information +# Generated by Django 2.2.19 on 2021-04-19 16:38 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("swh_web_common", "0008_save-code-now_indexes_20210106_1327"), + ] + + operations = [ + migrations.AddField( + model_name="saveoriginrequest", + name="visit_status", + field=models.TextField( + choices=[ + ("created", "created"), + ("ongoing", "ongoing"), + ("full", "full"), + ("partial", "partial"), + ("not_found", "not_found"), + ("failed", "failed"), + ], + null=True, + ), + ), + ] diff --git a/swh/web/common/models.py b/swh/web/common/models.py --- a/swh/web/common/models.py +++ b/swh/web/common/models.py @@ -65,6 +65,22 @@ (SAVE_TASK_RUNNING, SAVE_TASK_RUNNING), ] +VISIT_STATUS_CREATED = "created" +VISIT_STATUS_ONGOING = "ongoing" +VISIT_STATUS_FULL = "full" +VISIT_STATUS_PARTIAL = "partial" +VISIT_STATUS_NOT_FOUND = "not_found" +VISIT_STATUS_FAILED = "failed" + +VISIT_STATUSES = [ + (VISIT_STATUS_CREATED, VISIT_STATUS_CREATED), + (VISIT_STATUS_ONGOING, VISIT_STATUS_ONGOING), + (VISIT_STATUS_FULL, VISIT_STATUS_FULL), + (VISIT_STATUS_PARTIAL, VISIT_STATUS_PARTIAL), + (VISIT_STATUS_NOT_FOUND, VISIT_STATUS_NOT_FOUND), + (VISIT_STATUS_FAILED, VISIT_STATUS_FAILED), +] + class SaveOriginRequest(models.Model): """ @@ -74,6 +90,7 @@ id = models.BigAutoField(primary_key=True) request_date = models.DateTimeField(auto_now_add=True) visit_type = models.CharField(max_length=200, null=False) + visit_status = models.TextField(choices=VISIT_STATUSES, null=True) origin_url = models.CharField(max_length=200, null=False) status = models.TextField(choices=SAVE_REQUEST_STATUS, default=SAVE_REQUEST_PENDING) loading_task_id = models.IntegerField(default=-1) @@ -94,6 +111,7 @@ "id": self.id, "request_date": self.request_date, "visit_type": self.visit_type, + "visit_status": self.visit_status, "origin_url": self.origin_url, "status": self.status, "loading_task_id": self.loading_task_id, diff --git a/swh/web/common/origin_save.py b/swh/web/common/origin_save.py --- a/swh/web/common/origin_save.py +++ b/swh/web/common/origin_save.py @@ -294,6 +294,7 @@ return { "id": save_request.id, "visit_type": save_request.visit_type, + "visit_status": save_request.visit_status, "origin_url": save_request.origin_url, "save_request_date": save_request.request_date.isoformat(), "save_request_status": save_request.status, diff --git a/swh/web/tests/common/test_origin_save.py b/swh/web/tests/common/test_origin_save.py --- a/swh/web/tests/common/test_origin_save.py +++ b/swh/web/tests/common/test_origin_save.py @@ -239,6 +239,7 @@ SaveOriginRequest.objects.create( request_date=datetime.now(tz=timezone.utc), visit_type=_visit_type, + visit_status=visit_status, origin_url=_origin_url, status=SAVE_REQUEST_ACCEPTED, visit_date=None, @@ -288,6 +289,7 @@ assert len(sors) == 1 assert sors[0]["save_task_status"] == SAVE_TASK_RUNNING assert sors[0]["visit_date"] is None + assert sors[0]["visit_status"] == visit_status @pytest.mark.django_db @@ -311,6 +313,7 @@ sors = get_save_origin_requests(_visit_type, _origin_url) assert len(sors) == 1 assert sors[0]["save_task_status"] == SAVE_TASK_FAILED + assert sors[0]["visit_status"] == visit_status @pytest.mark.django_db @@ -327,9 +330,11 @@ assert sors[0]["save_task_status"] == SAVE_TASK_SUCCEEDED assert sors[0]["visit_date"] is not None + assert sors[0]["visit_status"] == visit_status sors = get_save_origin_requests(_visit_type, _origin_url) assert sors[0]["save_task_status"] == SAVE_TASK_SUCCEEDED + assert sors[0]["visit_status"] == visit_status @pytest.mark.django_db @@ -345,3 +350,4 @@ assert sors[0]["save_task_status"] == SAVE_TASK_SUCCEEDED assert sors[0]["visit_date"] is None + assert sors[0]["visit_status"] is None diff --git a/swh/web/tests/test_migrations.py b/swh/web/tests/test_migrations.py new file mode 100644 --- /dev/null +++ b/swh/web/tests/test_migrations.py @@ -0,0 +1,23 @@ +# Copyright (C) 2021 The Software Heritage developers +# See the AUTHORS file at the top-level directory of this distribution +# License: GNU General Public License version 3, or any later version +# See top-level LICENSE file for more information + +APP_NAME = "swh_web_common" + +MIGRATION_0008 = "0008_save-code-now_indexes_20210106_1327" +MIGRATION_0009 = "0009_saveoriginrequest_visit_status" + + +def test_migrations_09_add_visit_status_to_sor_model(migrator): + """Ensures the migration adds the visit_status field to SaveOriginRequest table""" + + old_state = migrator.apply_initial_migration((APP_NAME, MIGRATION_0008),) + old_webapp = old_state.apps.get_model(APP_NAME, "SaveOriginRequest") + + assert hasattr(old_webapp, "visit_status") is False + + new_state = migrator.apply_tested_migration((APP_NAME, MIGRATION_0009)) + new_webapp = new_state.apps.get_model(APP_NAME, "SaveOriginRequest") + + assert hasattr(new_webapp, "visit_status") is True