When you work on a project with multiple committers, it is not unusual to be greeted with this popup once in a while, especially after a Git pull:

And very often you do not execute the migrations and leave them for somebody else. After all,

  • you are not the one who introduced the migration,
  • migrations introduce unrelated code changes that pollute commit logs and pull requests,
  • incorrect migrations may break working code,
  • if multiple people execute the same migration, it may result in merge conflicts.

A better solution would be to prevent pull requests that introduce pending migrations from getting merged to the main branch. To do that, we need to check for pending migrations automatically.

To do that, we can get our inspiration from the MPS source code. It contains a test case that does exactly what we want. It uses MigrationSetup class to query for the migration status:

final MigrationSetup migrationManager = new MigrationSetup(getContextProject());
migrationRequired[0] = migrationManager.importVersionsUpdateRequired();
migrationRequired[1] = migrationManager.isMigrationRequired();

And if migrations are found to be required, this code collects the names of pending migrations to report:

projectMigrations.addAll(
    IterableUtil.asCollection(migrationManager.getProjectMigrations())
        .stream()
        .map(ProjectMigration::getDescription)
        .collect(Collectors.toList()));
getContextProject().getModelAccess().runReadAction(() -> {
    moduleMigrations.addAll(
        migrationManager.getModuleMigrations()
            .stream().map(it -> it
                .getScriptReference()
                .resolve(getContextProject(),false)
                .getCaption())
        .collect(Collectors.toList()));
});

The only problem is that if we put such code into a NodesTestCase (to run it inside an initialized MPS environment), we will get the following compilation error:

package jetbrains.mps.ide.migration does not exist (NoPendingMigrations_Test.java:14)

Compilation fails because class MigrationSetup is not part of the core MPS libraries but is supplied by the Migration Support plugin. It is visible in MPS but not available for compilation. So we have to use reflection to call it:

Of course, reflection makes the code absolutely unreadable and difficult to write, so collecting the names of pending migrations is going to be more complicated than just checking for a few Boolean flags, but I hope that it can serve as a good start.

Also note that the migration checking API has changed between MPS 2020.3 and 2021.1 but has been stable since then.