Allow ignoring initial migrations

Sometimes, if your apps have cyclic dependencies or complicated FK structure,
django migrations creates multiple initial migration files, which can very
easily fail linting because they are adding foreign keys or constraints etc.

This adds an option to automatically ignore all initial migrations.
This commit is contained in:
Mikuláš Poul authored and David Wobrock committed 2025-03-30 19:29:56 +02:00
1 parent dfd83cf9b8
commit 979b6b1046
6 files changed
+35 -2

No files matched your search

+3
View File
@@ -1,5 +1,8 @@
## 5.x.y
Feature:
- Allow ignoring all initial migrations, with `--ignore-initial-migrations`
Bug:
- Don't detect an index creation during a transaction with an exclusive lock, when the table is being created (#264)
+2
View File
@@ -48,6 +48,7 @@ If you are using a config file, replace any dashes (`-`) with an underscore (`_`
| `--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. |
| `--ignore-initial-migrations` | Ignore initial migrations. |
## Django settings configuration
@@ -86,6 +87,7 @@ class Migration(migrations.Migration):
```
Or you can restrict the migrations that should be selected by a file containing there paths with the `--include-migrations-from` option.
Or you can ignore all initial migrations with the `--ignore-initial-migrations` option.
## Ignoring migration tests
@@ -176,6 +176,7 @@ class Command(BaseCommand):
no_output=options["verbosity"] == 0,
analyser_string=options["sql_analyser"],
ignore_sqlmigrate_errors=options["ignore_sqlmigrate_errors"],
ignore_initial_migrations=options["ignore_initial_migrations"],
)
linter.lint_all_migrations(
app_label=options["app_label"],
@@ -46,6 +46,12 @@ def register_linting_configuration_options(parser: CommandParser) -> None:
help="ignore failures of sqlmigrate command",
)
parser.add_argument(
"--ignore-initial-migrations",
action="store_true",
help="ignore initial migrations",
)
def configure_logging(verbosity: int) -> None:
logger = logging.getLogger("django_migration_linter")
@@ -64,6 +64,7 @@ class MigrationLinter:
no_output: bool = False,
analyser_string: str | None = None,
ignore_sqlmigrate_errors: bool = False,
ignore_initial_migrations: bool = False,
):
# Store parameters and options
self.django_path = path
@@ -88,6 +89,7 @@ class MigrationLinter:
analyser_string=analyser_string,
)
self.ignore_sqlmigrate_errors = ignore_sqlmigrate_errors
self.ignore_initial_migrations = ignore_initial_migrations
# Initialise counters
self.reset_counters()
@@ -161,7 +163,9 @@ class MigrationLinter:
md5hash = self.get_migration_hash(app_label, migration_name)
if self.should_ignore_migration(app_label, migration_name, operations):
if self.should_ignore_migration(
app_label, migration_name, operations, is_initial=migration.initial
):
self.print_linting_msg(
app_label, migration_name, "IGNORE", MessageType.IGNORE
)
@@ -445,7 +449,11 @@ class MigrationLinter:
yield migration
def should_ignore_migration(
self, app_label: str, migration_name: str, operations: Iterable[Operation] = ()
self,
app_label: str,
migration_name: str,
operations: Iterable[Operation] = (),
is_initial: bool = False,
) -> bool:
return (
(self.include_apps and app_label not in self.include_apps)
@@ -471,6 +479,7 @@ class MigrationLinter:
and (app_label, migration_name)
in self.migration_loader.applied_migrations
)
or (self.ignore_initial_migrations and is_initial)
)
def analyse_data_migration(
+12
View File
@@ -170,3 +170,15 @@ class LinterFunctionsTestCase(unittest.TestCase):
]
)
self.assertEqual(2, len(list(migrations)))
def test_ignore_initial_migrations(self):
linter = MigrationLinter(ignore_initial_migrations=True)
self.assertTrue(
linter.should_ignore_migration(
"app_correct", "0001_initial", is_initial=True
)
)
self.assertFalse(
linter.should_ignore_migration("app_correct", "0002_foo", is_initial=False)
)