Opened 9 years ago

Closed 9 years ago

#24543 closed New feature (wontfix)

Add checks / command options for "migrations not applied" and "migrations needed"

Reported by: Daniel Hahler Owned by:
Component: Migrations Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Tim Graham)

The runserver command prints a notice in case migrations are not applied:

    def check_migrations(self):
        """
        Checks to see if the set of migrations on disk matches the
        migrations in the database. Prints a warning if they don't match.
        """
        executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS])
        plan = executor.migration_plan(executor.loader.graph.leaf_nodes())
        if plan:
            self.stdout.write(self.style.NOTICE("\nYou have unapplied migrations; your app may not work properly until they are applied."))
            self.stdout.write(self.style.NOTICE("Run 'python manage.py migrate' to apply them.\n"))

I would like to use this test during deployment.

Maybe this would be appropriate for the new --deploy option for the check
command introduced in Django 1.8?

Additionally, I'd like to check if there are no migrations required, which I
currently test by looking for "No changes detected" in `makemigrations
--dry-run`.

Even when this doesn't fit into the checks system, there should be a supported
way to get theses information by means of return codes from a command.

Change History (8)

comment:1 by Cody M Beardsley, 9 years ago

Owner: changed from nobody to Cody M Beardsley
Status: newassigned

comment:2 by Cody M Beardsley, 9 years ago

Owner: Cody M Beardsley removed
Status: assignednew

comment:3 by Tim Graham, 9 years ago

Description: modified (diff)

As for me, I simply execute migrate as part of a deployment script. If there aren't any migrations to apply, it's just a no-op. Could you elaborate on your use case for needing to know if migrations are applied or not? Currently, check --deploy is simply a static analysis of a settings file. The check you proposed would require the ability to connect to the production database which might not be possible from a development machine.

Regarding the second point, makemigrations gained an --exit option in 1.8 which does what you describe.

comment:4 by Daniel Hahler, 9 years ago

As for me, I simply execute migrate as part of a deployment script.

You are right, this is good enough and what you want to do in general.

But what I've really meant to ask for is getting the "current migration(s) being applied", in case you need to rollback during deployment.

This could be achieved manually by querying the django_migrations table etc, but then not that easy to handle in case of a rollback. It might be useful to have a way to ask the migrations system for the current ID of applied migrations (`
SELECT MAX(id) from django_migrations`) and then provide a new feature to rollback any later migrations (by some more complicated SQL).

As for the 2nd wish, the --exit option to makemigrations is what I was looking for (added in deb6076).
Thanks!

comment:5 by Tim Graham, 9 years ago

I'm still not perfectly clear on the use case. migrate does list the migrations as it runs so it seems it would be possible to roll back manually using that list. I'm not sure if an automated way to rollback is feasible or a good idea. Since migrations can often be destructive/non-reversible, I'd tend to prefer recommending to restore the database from a backup if needed rather than trying to engineer some attempt at a rollback mechanism in Django. That said, if there's an easy, simple solution I'm overlooking, maybe it's a good idea.

comment:6 by Markus Holtermann, 9 years ago

When you need to roll-back during a deployment you have already lost, from my point of view.

I agree with Tim that calling migrate as part of the deployment process is the best approach, given its noop behavior if nothing needs to be migrated. Furthermore, you can't reply on MAX(id). If you roll-back a migration the item is removed from the table and e.g. Postgres doesn't reset the sequence.

As an aside for the makemigrations idea: have a look at #24484.

in reply to:  6 comment:7 by Shai Berger, 9 years ago

This feature request would be useful, IMO, if there were easy ways to tell destructive migrations apart from non-destructive, and/or run only non-destructive ones. However, as migrations are not built to support these notions, this is a rather big "if".

This is a little academic, but (Replying to MarkusH):

Furthermore, you can't reply on MAX(id). If you roll-back a migration the item is removed from the table and e.g. Postgres doesn't reset the sequence.

... this means you can't trust MAX(id) to tell you the id of the first migration to be applied. On Postgres It is still true, though, AFAIK, that all future migrations will be recorded with larger ids. On Oracle MAX(id) really cannot be trusted, because of sequence value caching (that is, the next value retrieved from a sequence is only guaranteed to be larger than all previous ones retrieved on the same connection).

comment:8 by Tim Graham, 9 years ago

Resolution: wontfix
Status: newclosed

Closing in absence of a clear way to move this ticket forward (also it is a little confusing with multiple feature requests, some of which are already addressed.)

Note: See TracTickets for help on using tickets.
Back to Top