Allow ignoring sqlmigrate errors.

This commit is contained in:
Artem Streltsov authored and David Wobrock committed 2024-03-30 11:36:10 +01:00
1 parent a3acff2fef
commit b15924ca0f
7 files changed
+50 -2

No files matched your search

+1
View File
@@ -2,6 +2,7 @@
Feature:
- Support Django 5.0 `db_default` attribute (issue #275)
- Allow ignoring the failures of `sqlmigrate` commands, with `--ignore-sqlmigrate-errors` option (issue #274)
Bug:
- Don't detect 'IS NOT NULL' as backward incompatible changes (issue #263)
+1
View File
@@ -47,6 +47,7 @@ If you are using a config file, replace any dashes (`-`) with an underscore (`_`
| `--quiet or -q {ok,ignore,warning,error}` | Suppress certain output messages, instead of writing them to stdout. |
| `--warnings-as-errors [MIGRATION_TEST_CODE [...]]` | Handle warnings as errors and therefore return an error status code if we should. Optionally specify migration test codes to handle as errors. When no test code specified, all warnings are handled as errors. |
| `--sql-analyser` | Specify the SQL analyser that should be used. Allowed values: 'sqlite', 'mysql', 'postgresql'. |
| `--ignore-sqlmigrate-errors` | Ignore failures of sqlmigrate commands. |
## Django settings configuration
@@ -175,6 +175,7 @@ class Command(BaseCommand):
all_warnings_as_errors=all_warnings_as_errors,
no_output=options["verbosity"] == 0,
analyser_string=options["sql_analyser"],
ignore_sqlmigrate_errors=options["ignore_sqlmigrate_errors"],
)
linter.lint_all_migrations(
app_label=options["app_label"],
@@ -52,6 +52,7 @@ class Command(MakeMigrationsCommand):
self.exclude_migrations_tests = options["exclude_migration_tests"]
self.warnings_as_errors = options["warnings_as_errors"]
self.sql_analyser = options["sql_analyser"]
self.ignore_sqlmigrate_errors = options["ignore_sqlmigrate_errors"]
configure_logging(options["verbosity"])
return super().handle(*app_labels, **options)
@@ -92,6 +93,7 @@ class Command(MakeMigrationsCommand):
warnings_as_errors_tests=warnings_as_errors_tests,
all_warnings_as_errors=all_warnings_as_errors,
analyser_string=self.sql_analyser,
ignore_sqlmigrate_errors=self.ignore_sqlmigrate_errors,
)
for app_label, app_migrations in changes.items():
@@ -40,6 +40,12 @@ def register_linting_configuration_options(parser: CommandParser) -> None:
help="select the SQL analyser",
)
parser.add_argument(
"--ignore-sqlmigrate-errors",
action="store_true",
help="ignore failures of sqlmigrate command",
)
def configure_logging(verbosity: int) -> None:
logger = logging.getLogger("django_migration_linter")
@@ -63,6 +63,7 @@ class MigrationLinter:
all_warnings_as_errors: bool = False,
no_output: bool = False,
analyser_string: str | None = None,
ignore_sqlmigrate_errors: bool = False,
):
# Store parameters and options
self.django_path = path
@@ -86,6 +87,7 @@ class MigrationLinter:
settings.DATABASES[self.database]["ENGINE"],
analyser_string=analyser_string,
)
self.ignore_sqlmigrate_errors = ignore_sqlmigrate_errors
# Initialise counters
self.reset_counters()
@@ -321,11 +323,22 @@ class MigrationLinter:
database=self.database,
stdout=dev_null,
)
except (ValueError, ProgrammingError):
except (ValueError, ProgrammingError) as err:
if self.ignore_sqlmigrate_errors:
logger.warning(
"Error while executing sqlmigrate on (%s, %s).",
"Error while executing sqlmigrate on (%s, %s) with exception: %s. "
"Continuing execution with empty SQL.",
app_label,
migration_name,
str(err),
)
sql_statement = ""
else:
logger.warning(
"Error while executing sqlmigrate on (%s, %s) with exception: %s.",
app_label,
migration_name,
str(err),
)
raise
return sql_statement.splitlines()
+24
View File
@@ -2,7 +2,9 @@ from __future__ import annotations
import tempfile
import unittest
from unittest.mock import patch
from django.db import ProgrammingError
from django.db.migrations import Migration
from django_migration_linter import MigrationLinter
@@ -109,6 +111,28 @@ class LinterFunctionsTestCase(unittest.TestCase):
with self.assertRaises(Exception):
MigrationLinter.read_migrations_list(file_path)
@patch(
"django_migration_linter.migration_linter.call_command",
side_effect=ProgrammingError,
)
def test_raise_exception_on_sqlmigrate_error(self, call_command_mock):
linter = MigrationLinter(
exclude_migration_tests=[], database="mysql", ignore_sqlmigrate_errors=False
)
with self.assertRaises(ProgrammingError):
linter.get_sql("app_correct", "0002_foo")
@patch(
"django_migration_linter.migration_linter.call_command",
side_effect=ProgrammingError,
)
def test_ignore_exception_on_sqlmigrate_error(self, call_command_mock):
linter = MigrationLinter(
exclude_migration_tests=[], database="mysql", ignore_sqlmigrate_errors=True
)
sql_result = linter.get_sql("app_correct", "0002_foo")
self.assertEqual([], sql_result)
def test_read_migrations_no_file(self):
migration_list = MigrationLinter.read_migrations_list(None)
self.assertIsNone(migration_list)