Skip to content

Commit

Permalink
Add seed command with tests.
Browse files Browse the repository at this point in the history
Revert STDOUT changes as they caused problems in CI
  • Loading branch information
markstory committed Apr 1, 2024
1 parent fc2cbef commit aa9120a
Show file tree
Hide file tree
Showing 15 changed files with 326 additions and 19 deletions.
137 changes: 137 additions & 0 deletions src/Command/SeedCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php
declare(strict_types=1);

/**
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @license https://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Migrations\Command;

use Cake\Command\Command;
use Cake\Console\Arguments;
use Cake\Console\ConsoleIo;
use Cake\Console\ConsoleOptionParser;
use Cake\Event\EventDispatcherTrait;
use Migrations\Config\ConfigInterface;
use Migrations\Migration\ManagerFactory;

/**
* Seed command runs seeder scripts
*/
class SeedCommand extends Command
{
/**
* @use \Cake\Event\EventDispatcherTrait<\Migrations\Command\MigrateCommand>
*/
use EventDispatcherTrait;

/**
* The default name added to the application command list
*
* @return string
*/
public static function defaultName(): string
{
return 'migrations seed';
}

/**
* Configure the option parser
*
* @param \Cake\Console\ConsoleOptionParser $parser The option parser to configure
* @return \Cake\Console\ConsoleOptionParser
*/
public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
{
$parser->setDescription([
'Seed the database with data',
'',
'Runs a seeder script that can populate the database with data, or run mutations',
'',
'<info>migrations seed --connection secondary --seed UserSeeder</info>',
'',
'The `--seed` option can be supplied multiple times to run more than one seeder',
])->addOption('plugin', [
'short' => 'p',
'help' => 'The plugin to run seeders in',
])->addOption('connection', [
'short' => 'c',
'help' => 'The datasource connection to use',
'default' => 'default',
])->addOption('source', [
'short' => 's',
'default' => ConfigInterface::DEFAULT_SEED_FOLDER,
'help' => 'The folder where your seeders are.',
])->addOption('seed', [
'help' => 'The name of the seeder that you want to run.',
'multiple' => true,
]);

return $parser;
}

/**
* Execute the command.
*
* @param \Cake\Console\Arguments $args The command arguments.
* @param \Cake\Console\ConsoleIo $io The console io
* @return int|null The exit code or null for success
*/
public function execute(Arguments $args, ConsoleIo $io): ?int
{
$event = $this->dispatchEvent('Migration.beforeSeed');
if ($event->isStopped()) {
return $event->getResult() ? self::CODE_SUCCESS : self::CODE_ERROR;
}
$result = $this->executeSeeds($args, $io);
$this->dispatchEvent('Migration.afterSeed');

return $result;
}

/**
* Execute seeders based on console inputs.
*
* @param \Cake\Console\Arguments $args The command arguments.
* @param \Cake\Console\ConsoleIo $io The console io
* @return int|null The exit code or null for success
*/
protected function executeSeeds(Arguments $args, ConsoleIo $io): ?int
{
$factory = new ManagerFactory([
'plugin' => $args->getOption('plugin'),
'source' => $args->getOption('source'),
'connection' => $args->getOption('connection'),
]);
$manager = $factory->createManager($io);
$config = $manager->getConfig();
$seeds = (array)$args->getMultipleOption('seed');

$versionOrder = $config->getVersionOrder();
$io->out('<info>using connection</info> ' . (string)$args->getOption('connection'));
$io->out('<info>using paths</info> ' . implode(', ', $config->getMigrationPaths()));
$io->out('<info>ordering by</info> ' . $versionOrder . ' time');

$start = microtime(true);
if (empty($seeds)) {
// run all the seed(ers)
$manager->seed();

Check warning on line 124 in src/Command/SeedCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/SeedCommand.php#L124

Added line #L124 was not covered by tests
} else {
// run seed(ers) specified in a comma-separated list of classes
foreach ($seeds as $seed) {
$manager->seed(trim($seed));
}
}
$end = microtime(true);

$io->out('<comment>All Done. Took ' . sprintf('%.4fs', $end - $start) . '</comment>');

return self::CODE_SUCCESS;
}
}
1 change: 1 addition & 0 deletions src/Config/ConfigInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
interface ConfigInterface extends ArrayAccess
{
public const DEFAULT_MIGRATION_FOLDER = 'Migrations';
public const DEFAULT_SEED_FOLDER = 'Seeds';

/**
* Returns the configuration for the current environment.
Expand Down
5 changes: 1 addition & 4 deletions src/Migration/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -1006,10 +1006,7 @@ public function getSeeds(): array
ksort($seeds);
$this->setSeeds($seeds);
}

assert(!empty($this->seeds), 'seeds must be set');
$this->seeds = $this->orderSeedsByDependencies($this->seeds);

$this->seeds = $this->orderSeedsByDependencies((array)$this->seeds);
if (empty($this->seeds)) {
return [];
}
Expand Down
7 changes: 5 additions & 2 deletions src/Migration/ManagerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ManagerFactory
*
* ## Options
*
* - source - The directory in app/config that migrations should be read from.
* - source - The directory in app/config that migrations and seeds should be read from.
* - plugin - The plugin name that migrations are being run on.
* - connection - The connection name.
* - dry-run - Whether or not dry-run mode should be enabled.
Expand Down Expand Up @@ -70,7 +70,8 @@ public function createConfig(): ConfigInterface
{
$folder = (string)$this->getOption('source');

// Get the filepath for migrations and seeds(not implemented yet)
// Get the filepath for migrations and seeds.
// We rely on factory parameters to define which directory to use.
$dir = ROOT . DS . 'config' . DS . $folder;
if (defined('CONFIG')) {
$dir = CONFIG . $folder;
Expand Down Expand Up @@ -110,7 +111,9 @@ public function createConfig(): ConfigInterface

$configData = [
'paths' => [
// TODO make paths a simple list.
'migrations' => $dir,
'seeds' => $dir,
],
'templates' => [
'file' => $templatePath . 'Phinx/create.php.template',
Expand Down
6 changes: 4 additions & 2 deletions src/MigrationsPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use Migrations\Command\MigrationsSeedCommand;
use Migrations\Command\MigrationsStatusCommand;
use Migrations\Command\RollbackCommand;
use Migrations\Command\SeedCommand;
use Migrations\Command\StatusCommand;

/**
Expand Down Expand Up @@ -95,11 +96,12 @@ public function console(CommandCollection $commands): CommandCollection
{
if (Configure::read('Migrations.backend') == 'builtin') {
$classes = [
StatusCommand::class,
DumpCommand::class,
MarkMigratedCommand::class,
MigrateCommand::class,
DumpCommand::class,
RollbackCommand::class,
SeedCommand::class,
StatusCommand::class,
];
if (class_exists(SimpleBakeCommand::class)) {
$classes[] = BakeMigrationCommand::class;
Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase/Command/MigrationCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public function testRollbackWithNoLock()
protected function getMockIo()
{
$in = new StubConsoleInput([]);
$output = new StubConsoleOutput(STDOUT);
$output = new StubConsoleOutput();
$io = $this->getMockBuilder(ConsoleIo::class)
->setConstructorArgs([$output, $output, $in])
->getMock();
Expand Down
3 changes: 3 additions & 0 deletions tests/TestCase/Command/Phinx/SeedTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,11 @@ public function setUp(): void
public function tearDown(): void
{
parent::tearDown();

$this->connection->execute('DROP TABLE IF EXISTS phinxlog');
$this->connection->execute('DROP TABLE IF EXISTS numbers');
$this->connection->execute('DROP TABLE IF EXISTS letters');
$this->connection->execute('DROP TABLE IF EXISTS stores');
}

/**
Expand Down
7 changes: 5 additions & 2 deletions tests/TestCase/Command/RollbackCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
namespace Migrations\Test\TestCase\Command;

use Cake\Console\TestSuite\ConsoleIntegrationTestTrait;
use Cake\Console\TestSuite\StubConsoleOutput;
use Cake\Core\Configure;
use Cake\Database\Exception\DatabaseException;
use Cake\Event\EventInterface;
use Cake\Event\EventManager;
use Cake\TestSuite\TestCase;
use InvalidArgumentException;
use ReflectionProperty;

class RollbackCommandTest extends TestCase
{
Expand Down Expand Up @@ -46,7 +46,10 @@ public function tearDown(): void

protected function resetOutput(): void
{
$this->_out = new StubConsoleOutput(STDOUT);
if ($this->_out) {
$property = new ReflectionProperty($this->_out, '_out');
$property->setValue($this->_out, []);
}
}

public function testHelp(): void
Expand Down
Loading

0 comments on commit aa9120a

Please sign in to comment.