Skip to content

Commit

Permalink
add migrate replay command
Browse files Browse the repository at this point in the history
  • Loading branch information
wakebit committed Apr 16, 2022
1 parent a947508 commit 3fbb82c
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ See more on [the official Cycle ORM documentation](https://cycle-orm.dev/docs/re
| `cycle:migrate:init` | Initialize migrator: create a table for migrations | | `\Wakebit\CycleBridge\Console\Command\Migrate\InitCommand::class` |
| `cycle:migrate` | Run all outstanding migrations | - `--one`: Execute only one (first) migration.<br>- `--force`: Force the operation to run when in production. | `\Wakebit\CycleBridge\Console\Command\Migrate\MigrateCommand::class` |
| `cycle:migrate:rollback` | Rollback the last migration | - `--all`: Rollback all executed migrations.<br>- `--force`: Force the operation to run when in production. | `\Wakebit\CycleBridge\Console\Command\Migrate\RollbackCommand::class` |
| `cycle:migrate:replay` | Replay (down, up) one or multiple migrations. | - `--all`: Replay all migrations. | `\Wakebit\CycleBridge\Console\Command\Migrate\ReplayCommand::class` |
| `cycle:migrate:status` | Get a list of available migrations | | `\Wakebit\CycleBridge\Console\Command\Migrate\StatusCommand::class` |

### Database commands
Expand Down
70 changes: 70 additions & 0 deletions src/Console/Command/Migrate/ReplayCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

/**
* Credits: Spiral Cycle Bridge.
*
* @see https://github.com/spiral/cycle-bridge
*/

declare(strict_types=1);

namespace Wakebit\CycleBridge\Console\Command\Migrate;

use Cycle\Migrations\Config\MigrationConfig;
use Cycle\Migrations\Migrator;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

final class ReplayCommand extends AbstractCommand
{
private string $name = 'cycle:migrate:replay';
private string $description = 'Replay (down, up) one or multiple migrations.';

public function __construct(
protected Migrator $migrator,
protected MigrationConfig $migrationConfig,
private RollbackCommand $rollbackCommand,
private MigrateCommand $migrateCommand,
) {
parent::__construct($migrator, $migrationConfig);
}

protected function configure(): void
{
$this
->setName($this->name)
->setDescription($this->description)
->addOption('force', 's', InputOption::VALUE_NONE, 'Force the operation to run when in production.')
->addOption('all', 'a', InputOption::VALUE_NONE, 'Replay all migrations.');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
if (!$this->verifyEnvironment()) {
// Making sure we can safely migrate in this environment
return self::FAILURE;
}

$rollback = ['--force' => true];
$migrate = ['--force' => true];

if ($input->getOption('all')) {
$rollback['--all'] = true;
} else {
$migrate['--one'] = true;
}

$output->writeln('Rolling back executed migration(s)...');
$this->rollbackCommand->run(new ArrayInput($rollback), $output);

$output->writeln('');

$output->writeln('Executing outstanding migration(s)...');
$this->migrateCommand->run(new ArrayInput($migrate), $output);

return Command::SUCCESS;
}
}
76 changes: 76 additions & 0 deletions tests/src/Console/Command/Migrate/ReplayCommandTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

declare(strict_types=1);

namespace Wakebit\CycleBridge\Tests\Console\Command\Migrate;

use Cycle\Database\DatabaseInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Tester\CommandTester;
use Wakebit\CycleBridge\Console\Command\Migrate\MigrateCommand;
use Wakebit\CycleBridge\Console\Command\Migrate\ReplayCommand;
use Wakebit\CycleBridge\Tests\Constraints\SeeInOrder;
use Wakebit\CycleBridge\Tests\TestCase;

final class ReplayCommandTest extends TestCase
{
public function testOneMigration(): void
{
$dbal = $this->container->get(DatabaseInterface::class);
$this->assertSame([], $dbal->getTables());

$migrateCommand = $this->container->get(MigrateCommand::class);
$commandTester = new CommandTester($migrateCommand);
$this->assertSame(Command::SUCCESS, $commandTester->execute([]));
$this->assertCount(3, $dbal->getTables());

$replayCommand = $this->container->get(ReplayCommand::class);
$commandTester = new CommandTester($replayCommand);
$exitCode = $commandTester->execute([]);
$realOutput = $commandTester->getDisplay();
$expectedOutput = [
'Rolling back executed migration(s)...',
'Migration 0_default_create_customers was successfully rolled back.',

'Executing outstanding migration(s)...',
'Migration 0_default_create_customers was successfully executed.',
];

$this->assertSame(Command::SUCCESS, $exitCode);
$this->assertCount(3, $dbal->getTables());
$this->assertThat($expectedOutput, new SeeInOrder($realOutput));
$this->assertStringNotContainsString('0_default_change_articles_add_description', $realOutput);
$this->assertStringNotContainsString('0_default_create_articles', $realOutput);
}

public function testAllMigrations(): void
{
$dbal = $this->container->get(DatabaseInterface::class);
$this->assertSame([], $dbal->getTables());

$migrateCommand = $this->container->get(MigrateCommand::class);
$commandTester = new CommandTester($migrateCommand);
$this->assertSame(Command::SUCCESS, $commandTester->execute([]));
$this->assertCount(3, $dbal->getTables());

$replayCommand = $this->container->get(ReplayCommand::class);
$commandTester = new CommandTester($replayCommand);
$exitCode = $commandTester->execute(['--all' => true]);
$realOutput = $commandTester->getDisplay();
$expectedOutput = [
'Rolling back executed migration(s)...',
'Migration 0_default_create_customers was successfully rolled back.',
'Migration 0_default_change_articles_add_description was successfully rolled back.',
'Migration 0_default_create_articles was successfully rolled back.',

'Executing outstanding migration(s)...',
'Migration 0_default_create_articles was successfully executed.',
'Migration 0_default_change_articles_add_description was successfully executed.',
'Migration 0_default_create_customers was successfully executed.',
];

$this->assertSame(Command::SUCCESS, $exitCode);
$this->assertCount(3, $dbal->getTables());
$this->assertThat($expectedOutput, new SeeInOrder($realOutput));
}
}

0 comments on commit 3fbb82c

Please sign in to comment.