migrate --stop-before an already-applied migration is now an error

The CLI validated --stop-before names against both pending and applied
migrations, but Migrations.apply() only looked for the stop name among
pending ones - naming an applied migration passed validation and then
silently applied every migration after it, the exact outcome the option
exists to prevent. apply() now raises ValueError before applying
anything if a stop_before name matches an applied migration in its set;
names not in the set are still ignored, since unqualified CLI values are
offered to every set. The migrate command reports it as a clean error.

Refs https://github.com/simonw/sqlite-utils/issues/769#issuecomment-4900034150

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Simon Willison 2026-07-06 21:50:05 -07:00
commit b3aa3f47b7
6 changed files with 79 additions and 3 deletions

View file

@ -3462,7 +3462,10 @@ def migrate(db_path, migrations, stop_before, list_, verbose):
for migration_set in migration_sets:
matches = _stop_before_for_migration_set(stop_before, migration_set.name)
if isinstance(migration_set, sqlite_utils.Migrations):
migration_set.apply(db, stop_before=matches)
try:
migration_set.apply(db, stop_before=matches)
except ValueError as e:
raise click.ClickException(str(e))
else:
# Legacy sqlite-migrate Migrations objects take a single string
# for stop_before, not a list