Skip to content

Commit

Permalink
allow migrations to be hardcoded as fake
Browse files Browse the repository at this point in the history
  • Loading branch information
dantownsend committed Jun 19, 2024
1 parent d91d59c commit 4f82908
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 9 deletions.
20 changes: 20 additions & 0 deletions docs/src/piccolo/migrations/running.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,36 @@ If you have multiple apps you can run them all using:
piccolo migrations forwards all
.. _FakeMigration:

Fake
~~~~

We can 'fake' running a migration - we record that it ran in the database
without actually running it.

There are two ways to do this - by passing in the ``--fake`` flag on the
command line:

.. code-block:: bash
piccolo migrations forwards my_app 2022-09-04T19:44:09 --fake
Or by setting ``fake=True`` on the ``MigrationManager`` within the migration
file.

.. code-block:: python
async def forwards():
manager = MigrationManager(
migration_id=ID,
app_name="app",
description=DESCRIPTION,
fake=True
)
...
This is useful if we started from an existing database using
``piccolo schema generate``, and the initial migration we generated is for
tables which already exist, hence we fake run it.
Expand Down
2 changes: 1 addition & 1 deletion docs/src/piccolo/tutorials/migrate_existing_project.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ This will create a new file in ``my_app/piccolo_migrations``:
piccolo migrations new my_app --auto
These tables already exist in the database, as it's an existing project, so
you need to fake apply this initial migration:
you need to :ref:`fake apply <FakeMigration>` this initial migration:

.. code-block:: bash
Expand Down
1 change: 1 addition & 0 deletions piccolo/apps/migrations/auto/migration_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ class MigrationManager:
raw_backwards: t.List[t.Union[t.Callable, AsyncFunction]] = field(
default_factory=list
)
fake: bool = False

def add_table(
self,
Expand Down
15 changes: 8 additions & 7 deletions piccolo/apps/migrations/commands/forwards.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,19 @@ async def run_migrations(self, app_config: AppConfig) -> MigrationResult:
print(f"🚀 Running {n} migration{'s' if n != 1 else ''}:")

for _id in subset:
if self.fake:
print(f"- {_id}: faked! ⏭️")
else:
migration_module = migration_modules[_id]
response = await migration_module.forwards()
migration_module = migration_modules[_id]
response = await migration_module.forwards()

if isinstance(response, MigrationManager):
if isinstance(response, MigrationManager):
if self.fake or response.fake:
print(f"- {_id}: faked! ⏭️")
else:
if self.preview:
response.preview = True
await response.run()

print("ok! ✔️")
print("ok! ✔️")

if not self.preview:
await Migration.insert().add(
Migration(name=_id, app_name=app_config.app_name)
Expand Down
33 changes: 32 additions & 1 deletion tests/apps/migrations/commands/test_forwards_backwards.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def test_forwards_no_migrations(self, print_: MagicMock):
@engines_only("postgres")
def test_forwards_fake(self):
"""
Test running the migrations if they've already run.
Make sure migrations can be faked on the command line.
"""
run_sync(forwards(app_name="music", migration_id="all", fake=True))

Expand All @@ -214,9 +214,40 @@ def test_forwards_fake(self):
"2021-09-06T13:58:23:024723",
"2021-11-13T14:01:46:114725",
"2024-05-28T23:15:41:018844",
"2024-06-19T18:11:05:793132",
],
)

@engines_only("postgres")
@patch("piccolo.apps.migrations.commands.forwards.print")
def test_hardcoded_fake_migrations(self, print_: MagicMock):
"""
Make sure that migrations that have been hardcoded as fake aren't
executed, even without the ``--fake`` command line flag.
See tests/example_apps/music/piccolo_migrations/music_2024_06_19t18_11_05_793132.py
""" # noqa: E501
run_sync(forwards(app_name="music", migration_id="all"))

# The migration which is hardcoded as fake:
migration_name = "2024-06-19T18:11:05:793132"

self.assertTrue(
Migration.exists()
.where(Migration.name == migration_name)
.run_sync()
)

self.assertNotIn(
call("Running fake migration"),
print_.mock_calls,
)
self.assertIn(
call(f"- {migration_name}: faked! ⏭️"),
print_.mock_calls,
)

def tearDown(self):
for table_class in TABLE_CLASSES + [Migration]:
table_class.alter().drop_table(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from piccolo.apps.migrations.auto.migration_manager import MigrationManager

ID = "2024-06-19T18:11:05:793132"
VERSION = "1.11.0"
DESCRIPTION = "An example fake migration"


async def forwards():
manager = MigrationManager(
migration_id=ID, app_name="", description=DESCRIPTION, fake=True
)

def run():
# This should never run, as this migrations is `fake=True`. It's here
# for testing purposes (to make sure it never gets triggered).
print("Running fake migration")

manager.add_raw(run)

return manager

0 comments on commit 4f82908

Please sign in to comment.