Skip to content
Merged
11 changes: 8 additions & 3 deletions src/Illuminate/Console/View/Components/Task.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Illuminate\Console\View\Components;

use Illuminate\Database\Migrations\MigrationResult;
use Illuminate\Support\InteractsWithTime;
use Symfony\Component\Console\Output\OutputInterface;
use Throwable;
Expand Down Expand Up @@ -34,10 +35,10 @@ public function render($description, $task = null, $verbosity = OutputInterface:

$startTime = microtime(true);

$result = false;
$result = MigrationResult::Failure;

try {
$result = ($task ?: fn () => true)();
$result = ($task ?: fn () => MigrationResult::Success)();
} catch (Throwable $e) {
throw $e;
} finally {
Expand All @@ -53,7 +54,11 @@ public function render($description, $task = null, $verbosity = OutputInterface:
$this->output->write("<fg=gray>$runTime</>", false, $verbosity);

$this->output->writeln(
$result !== false ? ' <fg=green;options=bold>DONE</>' : ' <fg=red;options=bold>FAIL</>',
match ($result) {
MigrationResult::Failure => ' <fg=red;options=bold>FAIL</>',
MigrationResult::Skipped => ' <fg=yellow;options=bold>SKIPPED</>',
default => ' <fg=green;options=bold>DONE</>'
},
$verbosity,
);
}
Expand Down
10 changes: 10 additions & 0 deletions src/Illuminate/Database/Migrations/Migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,14 @@ public function getConnection()
{
return $this->connection;
}

/**
* Determine if this migration should run.
*
* @return bool
*/
public function shouldRun(): bool
{
return true;
}
}
10 changes: 10 additions & 0 deletions src/Illuminate/Database/Migrations/MigrationResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Illuminate\Database\Migrations;

enum MigrationResult: int
{
case Success = 1;
case Failure = 2;
case Skipped = 3;
}
27 changes: 22 additions & 5 deletions src/Illuminate/Database/Migrations/Migrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,19 @@ protected function pendingMigrations($files, $ran)
->all();
}

/**
* Determine if the migration should be ran.
*
* @param object $migration
* @return bool
*/
public function shouldSkipMigration($migration)
{
return $migration instanceof Migration
? ! $migration->shouldRun()
: false;
}

/**
* Get list of pending migrations to skip.
*
Expand Down Expand Up @@ -241,12 +254,16 @@ protected function runUp($file, $batch, $pretend)
return $this->pretendToRun($migration, 'up');
}

$this->write(Task::class, $name, fn () => $this->runMigration($migration, 'up'));
if ($this->shouldSkipMigration($migration)) {
$this->write(Task::class, $name, fn () => MigrationResult::Skipped);

This comment was marked as resolved.

This comment was marked as outdated.

} else {
$this->write(Task::class, $name, fn () => $this->runMigration($migration, 'up'));

// Once we have run a migrations class, we will log that it was run in this
// repository so that we don't try to run it next time we do a migration
// in the application. A migration repository keeps the migrate order.
$this->repository->log($name, $batch);
// Once we have run a migrations class, we will log that it was run in this
// repository so that we don't try to run it next time we do a migration
// in the application. A migration repository keeps the migrate order.
$this->repository->log($name, $batch);
}
}

/**
Expand Down
10 changes: 8 additions & 2 deletions tests/Console/View/ComponentsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Console\OutputStyle;
use Illuminate\Console\View\Components;
use Illuminate\Database\Migrations\MigrationResult;
use Mockery as m;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Output\BufferedOutput;
Expand Down Expand Up @@ -108,15 +109,20 @@ public function testTask()
{
$output = new BufferedOutput();

with(new Components\Task($output))->render('My task', fn () => true);
with(new Components\Task($output))->render('My task', fn () => MigrationResult::Success);
$result = $output->fetch();
$this->assertStringContainsString('My task', $result);
$this->assertStringContainsString('DONE', $result);

with(new Components\Task($output))->render('My task', fn () => false);
with(new Components\Task($output))->render('My task', fn () => MigrationResult::Failure);
$result = $output->fetch();
$this->assertStringContainsString('My task', $result);
$this->assertStringContainsString('FAIL', $result);

with(new Components\Task($output))->render('My task', fn () => MigrationResult::Skipped);
$result = $output->fetch();
$this->assertStringContainsString('My task', $result);
$this->assertStringContainsString('SKIPPED', $result);
}

public function testTwoColumnDetail()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateFlightsTable extends Migration
{
public function shouldRun(): bool
{
return false;
}

/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('flights', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('flights');
}
}
5 changes: 4 additions & 1 deletion tests/Integration/Migration/MigratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public function testMigrate()
$this->expectTask('2014_10_12_000000_create_people_table', 'DONE');
$this->expectTask('2015_10_04_000000_modify_people_table', 'DONE');
$this->expectTask('2016_10_04_000000_modify_people_table', 'DONE');
$this->expectTask('2017_10_04_000000_add_age_to_people', 'SKIPPED');

$this->output->shouldReceive('writeln')->once();

Expand All @@ -52,6 +53,7 @@ public function testMigrate()
$this->assertTrue(DB::getSchemaBuilder()->hasTable('people'));
$this->assertTrue(DB::getSchemaBuilder()->hasColumn('people', 'first_name'));
$this->assertTrue(DB::getSchemaBuilder()->hasColumn('people', 'last_name'));
$this->assertFalse(DB::getSchemaBuilder()->hasColumn('people', 'age'));
}

public function testMigrateWithoutOutput()
Expand All @@ -64,6 +66,7 @@ public function testMigrateWithoutOutput()
$this->assertTrue(DB::getSchemaBuilder()->hasTable('people'));
$this->assertTrue(DB::getSchemaBuilder()->hasColumn('people', 'first_name'));
$this->assertTrue(DB::getSchemaBuilder()->hasColumn('people', 'last_name'));
$this->assertFalse(DB::getSchemaBuilder()->hasColumn('people', 'age'));
}

public function testWithSkippedMigrations()
Expand Down Expand Up @@ -120,7 +123,7 @@ public function testPretendMigrate()
$this->expectTwoColumnDetail('2016_10_04_000000_modify_people_table');
$this->expectBulletList(['alter table "people" add column "last_name" varchar']);

$this->output->shouldReceive('writeln')->once();
$this->output->shouldReceive('writeln')->times(3);

$this->subject->run([__DIR__.'/fixtures'], ['pretend' => true]);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function shouldRun(): bool
{
return false;
}

/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('people', function (Blueprint $table) {
$table->unsignedInteger('age')->nullable();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('people', function (Blueprint $table) {
$table->dropColumn('age');
});
}
};
Loading