diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index e8a9942c8d..8fa5d73a17 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -35,6 +35,38 @@ jobs: coverage report -m bash <(curl -s https://codecov.io/bash) + test_check_unapplied_migrations_middleware: + name: middleware for unapplied migrations + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.7] + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Python dependencies + run: | + sudo apt-get install libkrb5-dev gettext + pip install -r requirements/devel.txt + pushd tcms/ && npm install && popd + + - name: Run test + run: | + export LANG=en-us + export TEST_CHECK_UNAPPLIED_MIGRATIONS_MIDDLEWARE=1 + coverage run --source='.' ./manage.py test -v2 --noinput --settings=tcms.settings.test tcms.core.tests.test_middleware.TestCheckUnappliedMigrationsMiddleware + + - name: Send coverage to codecov.io + run: | + coverage report -m + bash <(curl -s https://codecov.io/bash) + without_internal_bugtracker: name: without internal bugtracker runs-on: ubuntu-latest diff --git a/tcms/core/middleware.py b/tcms/core/middleware.py index 2464b96d91..72d238f25d 100644 --- a/tcms/core/middleware.py +++ b/tcms/core/middleware.py @@ -7,6 +7,8 @@ from django.utils.deprecation import MiddlewareMixin from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ +from django.db import DEFAULT_DB_ALIAS, connections +from django.db.migrations.executor import MigrationExecutor class CsrfDisableMiddleware(MiddlewareMixin): @@ -32,3 +34,23 @@ def process_request(self, request): } ) ) + + +class CheckUnappliedMigrationsMiddleware(MiddlewareMixin): + def process_request(self, request): + doc_url = """https://kiwitcms.readthedocs.io/en/latest/\ +installing_docker.html#initial-configuration-of-running-container""" + executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS]) + plan = executor.migration_plan(executor.loader.graph.leaf_nodes()) + if plan: + messages.add_message( + request, + messages.ERROR, + mark_safe( + _('You have %(unapplied_migration_count)s unapplied migration(s). ' + 'See documentation') % { + "unapplied_migration_count": len(plan), + "doc_url": doc_url, + } + ) + ) diff --git a/tcms/core/tests/test_middleware.py b/tcms/core/tests/test_middleware.py new file mode 100644 index 0000000000..f52e62d19a --- /dev/null +++ b/tcms/core/tests/test_middleware.py @@ -0,0 +1,26 @@ +import os +import unittest +from django import test +from django.conf import settings +from django.apps import apps +from django.contrib.messages import get_messages + + +@unittest.skipUnless( + os.getenv('TEST_CHECK_UNAPPLIED_MIGRATIONS_MIDDLEWARE'), + 'CheckUnappliedMigrationsMiddleware testing not enabled') +class TestCheckUnappliedMigrationsMiddleware(test.TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + settings.INSTALLED_APPS.append("tcms.core.tests.test_migrations_app") + apps.set_installed_apps(settings.INSTALLED_APPS) + + @test.override_settings(MIGRATION_MODULES={ + "migrations": "tcms.core.tests.test_migrations_app.migrations"}) + def test_unapplied_migrations(self): + unapplied_migration_message = """You have 1 unapplied migration(s).\ + See documentation""" + response = self.client.get('/', follow=True) + self.assertContains(response, unapplied_migration_message) diff --git a/tcms/core/tests/test_migrations_app/__init__.py b/tcms/core/tests/test_migrations_app/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tcms/core/tests/test_migrations_app/migrations/0001_initial.py b/tcms/core/tests/test_migrations_app/migrations/0001_initial.py new file mode 100644 index 0000000000..da8597c1bd --- /dev/null +++ b/tcms/core/tests/test_migrations_app/migrations/0001_initial.py @@ -0,0 +1,15 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + operations = [ + + migrations.CreateModel( + "TestPerson", + [ + ("id", models.AutoField(primary_key=True)), + ("name", models.CharField(max_length=10)), + ], + ), + ] diff --git a/tcms/core/tests/test_migrations_app/migrations/__init__.py b/tcms/core/tests/test_migrations_app/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tcms/core/tests/test_migrations_app/models.py b/tcms/core/tests/test_migrations_app/models.py new file mode 100644 index 0000000000..ba7c29523d --- /dev/null +++ b/tcms/core/tests/test_migrations_app/models.py @@ -0,0 +1,5 @@ +from django.db import models + + +class TestPerson(models.Model): + name = models.CharField(max_length=10) diff --git a/tcms/settings/common.py b/tcms/settings/common.py index c9933ccc45..30b7179c2c 100644 --- a/tcms/settings/common.py +++ b/tcms/settings/common.py @@ -130,6 +130,7 @@ 'global_login_required.GlobalLoginRequiredMiddleware', 'simple_history.middleware.HistoryRequestMiddleware', 'tcms.core.middleware.CheckSettingsMiddleware', + 'tcms.core.middleware.CheckUnappliedMigrationsMiddleware', ]