charettes / django-syzygy

Django application providing database migration tooling to automate their deployment.
MIT License
85 stars 3 forks source link

"Plan contains a non-contiguous sequence of pre-deployment migrations" #34

Closed OrSecondNature closed 1 year ago

OrSecondNature commented 1 year ago

I'm using the django-syzygy library and encountered an issue.

Let's say I'm doing 2 unrelated migrations; each one generates 2 migrations: pre and post. When trying to apply both pre migrations with ./manage.py migrate --pre-deploy I get the error: CommandError: Plan contains a non-contiguous sequence of pre-deployment migrations.

Is that expected? How can I overcome this issue? I'm using: python 3.10.11 django==4.1 django-mysql==4.9.0 django-syzygy==0.1.0a10

charettes commented 1 year ago

Very hard to tell without your set of migrations. You normally get this error message when trying to combine pre and pre-post migrations that depend on each other but there was a bug in 0.1.0a11 that didn't account for some installed app order cases that was fixed in 30b348b5ebc5caae1b2c0af8ed9ade22c4fa2d91.

Can you retry with 0.1.0a11?

OrSecondNature commented 1 year ago

Hi,

Thanks for the answer. I upgraded the django-syzygy package to 0.1.0a11, and tried again. For example, I added a new field to a table, and then added another field to the same table. Here are the 4 migration files that was created:

0363_migration

# Generated by Django 4.1 on 2023-05-17 12:40

from django.db import migrations, models
import syzygy.operations

class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        syzygy.operations.AddField(
            model_name='mymodel',
            name='my_new_field1',
            field=models.CharField(max_length=200, null=True),
        ),
    ]

0364_migration

# Generated by Django 4.1 on 2023-05-17 12:40

from django.db import migrations, models
import syzygy.operations

class Migration(migrations.Migration):

    dependencies = [
        ('dialogflow', '0363_migration'),
    ]

    operations = [
        syzygy.operations.PostAddField(
            model_name='mymodel',
            name='my_new_field1',
            field=models.CharField(max_length=200, null=True),
        ),
    ]

0365_migration

# Generated by Django 4.1 on 2023-05-17 12:41

from django.db import migrations, models
import syzygy.operations

class Migration(migrations.Migration):

    dependencies = [
        ('dialogflow', '0364_migration'),
    ]

    operations = [
        syzygy.operations.AddField(
            model_name='typeformsurvey',
            name='my_new_field2',
            field=models.CharField(max_length=200, null=True),
        ),
    ]

0366_migration

# Generated by Django 4.1 on 2023-05-17 12:41

from django.db import migrations, models
import syzygy.operations

class Migration(migrations.Migration):

    dependencies = [
        ('dialogflow', '0365_migration'),
    ]

    operations = [
        syzygy.operations.PostAddField(
            model_name='mymodel',
            name='my_new_field2',
            field=models.CharField(max_length=200, null=True),
        ),
    ]

When running ./manage.py migrate --pre-deploy I still get the error CommandError: Plan contains a non-contiguous sequence of pre-deployment migrations. Since we don't have full CI/CD, many migrations that was created by several developers should run once a week, so cases like this are going to happen a lot. How can I overcome this?

charettes commented 1 year ago

I don't think you understand the purpose of this tool, it is meant to be used in a CD pipeline where changes are shipped incrementally and deployed in a way that pre-deployment and post-deploment changes are shipped with the deployment that depend on them.

From what I can see here the tool is doing exactly what it was designed for, it's telling you that it cannot deploy all migrations it has detected to be required to run pre-deployment (0363 and 0365) because 0364 must be run after a deployment completes. If you want to deploy your changes anyway simply don't pass --pre-deploy.