Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions php/EE/Migration/CustomContainerMigrations.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

class CustomContainerMigrations {

/** @var array Migrations completed by this invocation, oldest first: name => instance. */
private static $executed = [];

/**
* Executes pending migrations of container.
*/
Expand All @@ -16,6 +19,8 @@ public static function execute_migrations() {
Utils\delem_log( 'ee migration start' );
EE::debug( 'Executing custom container migrations' );

self::$executed = [];

$migrations = self::get_all_migrations();

if ( empty( $migrations ) ) {
Expand All @@ -35,6 +40,57 @@ public static function execute_migrations() {
EE::debug( 'Successfully migrated EasyEngine' );
}

/**
* Reverts the container migrations completed by this invocation, newest first, when a later upgrade step fails.
*
* Their rows are deleted so the next attempt runs them again. Migrations recorded by earlier runs are not touched.
*/
public static function revert_executed_migrations() {

$executed = array_reverse( self::$executed, true );
self::$executed = [];

if ( empty( $executed ) ) {
return;
}

// On a fresh install they are no-ops by design, and older down() methods assume an upgrade.
if ( ! \EE\Model\Option::get( 'version' ) ) {
EE::debug( 'Fresh install: not reverting container migrations' );
return;
}

foreach ( $executed as $name => $migration ) {
EE::debug( "Reverting: $name" );
$reverted = true;
try {
$migration->down();
} catch ( \Throwable $e ) {
$reverted = false;
EE::warning( "Could not revert container migration $name: " . $e->getMessage() );
}

// Deleted even if down() failed: migrations are idempotent, and a retry must run it again.
try {
foreach ( Migration::where( 'migration', $name ) as $row ) {
$row->delete();
}
EE::debug( $reverted ? "Reverted: $name" : "Removed the migrations row of $name" );
} catch ( \Throwable $e ) {
EE::warning( "Could not delete the migrations row of $name: " . $e->getMessage() );
}
}
}

/**
* Keeps the container migrations completed by this invocation: a later failure no longer reverts them.
*/
public static function keep_executed_migrations() {

self::$executed = [];
EE::debug( 'Keeping the container migrations of this run' );
}

/**
* @return array of available migrations
*/
Expand Down Expand Up @@ -130,6 +186,7 @@ private static function execute_migration_stack( $migrations ) {
] );

$migration->status = 'complete';
self::$executed[ $migrations[0] ] = $migration;
EE::debug( "Migrated: $migrations[0]" );
$remaining_migrations = array_splice( $migrations, 1, count( $migrations ) );
self::execute_migration_stack( $remaining_migrations );
Expand All @@ -144,6 +201,7 @@ private static function execute_migration_stack( $migrations ) {
$migration->down();
$migrated[0]->delete();
}
unset( self::$executed[ $migrations[0] ] );

EE::debug( "Reverted: $migrations[0]" );
throw $e;
Expand Down
5 changes: 4 additions & 1 deletion php/EE/Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,11 @@ private function migrate() {
$rsp = new \EE\RevertableStepProcessor();

$rsp->add_step( 'ee-db-migrations', 'EE\Migration\Executor::execute_migrations' );
$rsp->add_step( 'ee-custom-container-migrations', 'EE\Migration\CustomContainerMigrations::execute_migrations' );
$rsp->add_step( 'ee-custom-container-migrations', 'EE\Migration\CustomContainerMigrations::execute_migrations', 'EE\Migration\CustomContainerMigrations::revert_executed_migrations' );
$rsp->add_step( 'ee-docker-image-migrations', 'EE\Migration\Containers::start_container_migration' );
// The new images run from here on and have no undo, so a later failure must not revert the container migrations onto them.
$rsp->add_step( 'ee-keep-container-migrations', 'EE\Migration\CustomContainerMigrations::keep_executed_migrations' );
$rsp->add_step( 'ee-after-docker-image-migrations', 'EE::do_hook', null, [ 'after_docker_image_migration' ] );
$rsp->add_step( 'ee-update-docker-compose', 'EE\Migration\Containers::update_docker_compose' );
$rsp->add_step( 'ee-update-cron-config', 'EE\Cron\Utils\update_cron_config' );
$rsp->add_step( 'ee-setup-logrotate', 'EE\Logrotate\Utils::setup_logrotate' );
Expand Down
Loading