Skip to content

Add subcommand enroll_db #14

@algal

Description

@algal

Fastmigrate now has two subcommands: create_db, which creates a fastmigrate-managed db without any content, and run_migrations, which updates that db based on migrations.

None of these can be used with a db which was created outside of fastmigrate. But there is where someone who already has a system will be starting from. They need to enroll their db in fastmigrate. This is unavoidably a somewhat delicate operation, because it requires the user to assert that their existing db is in a state which matches what would be produced by a migration script which they need to author. I describe it in detail here: https://github.com/AnswerDotAI/fastmigrate/blob/main/enrolling.md

However, because this is a common, delicate, and stressful operation -- and because it is literally the user's first experience of fastmigrate -- the fastmigrate command-line client should provide a command which helps the user in this situation.

Here are my preliminary thoughts on how it would work:

  • user calls fastmigrate enroll_db, which replies on the usual mechanisms for passing in the path of the db file to which the enroll operation will be applied
  • if no migrations path is specified, fail with a helpful error.
  • if a migrations path is specified, and migration scripts exist there, fail with helpful error.
  • if no db exists, the command fails with a helpful error message
  • if a db exists which is already managed by fastmigrate, the command fails with a helpful error message
  • if an unmanaged db is found, and migration scripts are found, the command fails with a helpful error message.
  • when an unmanaged db is found, the command explains the steps of migration, roughly as follows:
    1. user should use the sqlite3 CLI to dump the OLD db to an sql script which would reproduce the current schema. Let us call that sql script the INITIALIZATION SCRIPT and name it 0001-initialize.sql.
    1. user should create a NEW sqlite3 database by using that script.
    1. user should manually inspect the NEW database and ensure that in its schema and in its contents it is in a state which is compatible with the current application code. User should be reminded to consider required database values, such as initial default values which might be required for certain fields
    1. If the user confirm that the NEW database is compatible with application code using the OLD db, then this INITIALIZATION SCRIPT is valid as the first migration script
    1. User should author a commit, which makes the following changes: (1) adds the INITIALIZATiON SCRIPT into a migrations/ directory within the application, (2) updates the application's database-initialization code to use fastmigrate, by calling create_db and run_migrations and by removing any previous legacy code for preparing the db.
    1. User should manually set the db version number of the existing db version, marking the db as fastmigrate-managed.
    1. User should deploy the commit which requires databases to be fastmigrate-managed, and will create a fastmigrate-managed db if necessary

In addition to explaining these steps, the command might also provide an interactive flow which helped with these steps. Is this a good idea? I'm not sure. If it is, I imagine it might look like this:

  1. Prompt user for confirmation before using sqlite3 to generate a candidate initialization script, then do so, placing the script into a temporary directory.
  2. prompt user before creating a new test db by using that initialization script, and then do so, placing the new db into the temporary directory
  3. ask user to verify the new db and the old db are both application compatible, and prompt user either to confirm they are compatible or to abort. On abort, report the paths of the generated candidate initialization script and new database and quit.
  4. On confirmation, write the initialization script into the migrations directory
  5. Prompt user to perform edits to application code such that the application initializes the db with fastmigrate, and expects the db in the current state, and confirm when those changes are complete and commited in some fashion (but not merged to main and/or deployed)
  6. Prompt the user for confirmation before backing up the db, and report the path of the backup.
  7. Provide the user the command which they can perform themselves manually to set the version of the existing db, and ask them to confirm when they have done so.
  8. Prompt the user the deploy the commit which introduces fastmigrate and which requires the db to be fastmigrate-managed.

Looking at this now, it strikes me as daunting to do well. That is unfortunate! I'm not sure if that is a reason not to do this, or a reason why it needs to be done because it indicates the alternative of a user doing it manually is even worse. If this is worth doing, I think it should be tackled only after other issues like #8 and #15

(per our discussion, fyi @pydanny )

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions