Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
levizoesch committed Mar 27, 2024
0 parents commit ddde9bb
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Jetbrains
.idea/*
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Check Migrations

A Laravel command scans your application for pending migrations, providing a clear overview of what needs to be migrated.
You can then choose to run individual migrations or skip them as needed, short-cutting and optimizing your development workflow.

## Support for Structured Migrations

This package seamlessly handles migrations organized within subdirectories, ensuring that no pending migrations are overlooked regardless of the project's migration structure.

```php
database
└── migrations
├── 2023_01_01
│ ├── 20230101000001_create_table_one.php
│ └── 20230101000002_create_table_two.php
└── 2023_02_01
├── 20230201000001_create_table_three.php
└── 20230201000002_create_table_four.php

```
## Installation

```bash
composer require levizoesch/laravel-check-migrations
```

## Usage

Run the following command in your terminal:

#### This will display pending migrations and prompt for confirmation before running each one.
```bash
php artisan check-migrations
```
#### This will skip confirmation and run pending migrations directly.
```bash
php artisan check-migrations --skip
```
#### This will ignore the migration named 20230101000000_create_example_table from running and prompting for confirmation.
```bash
php artisan check-migrations --ignore=20230101000000_create_example_table
```

### Notes

Ensure that your Laravel project is properly configured and migrations are set up correctly for this command to work effectively.

Always review pending migrations before running them in production environments to prevent unintended consequences.
28 changes: 28 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "levizoesch/laravel-check-migrations",
"type": "project",
"license": "MIT",
"description": "A Laravel command scans your application for pending migrations, providing a clear overview of what needs to be migrated.\nYou can then choose to run individual migrations or skip them as needed, short-cutting and optimizing your development workflow.",
"keywords": [
"Levi Zoesch",
"laravel",
"laravel commands",
"laravel helpers",
"Laravel Check Migrations"
],
"require": {
"php": "^7.0|^8.0"
},
"autoload": {
"psr-4" : {
"levizoesch\\checkmigrations\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"levizoesch\\checkmigrations\\CheckMigrationsServiceProvider"
]
}
}
}
123 changes: 123 additions & 0 deletions src/CheckMigrations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?php
namespace levizoesch\checkmigrations;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;


class CheckMigrations extends Command
{
// skip flag is redundant as you would just run native
// migrate command, but kept for possible use for pipelines/automation
protected $signature = 'check-migrations
{--skip : Skip confirmation and run migrations directly}
{--ignore= : Specify migration name to ignore from running, and prompting for confirmation}';

protected $description = 'Check for unrun migrations';

public function handle(): void
{
$this->showPendingMigrations();
}

// Function to display pending migrations and optionally run them
private function showPendingMigrations(): void
{
$pendingMigrations = $this->getPendingMigrations();

foreach ($pendingMigrations as $migrationName) {
$this->info("Pending migration found: $migrationName");

if ($this->shouldRunMigration($migrationName)) {
$this->runMigration($migrationName);
} else {
$this->comment("The migration $migrationName was not run.");
$this->line("");
}
}
}

// Function to retrieve a list of pending migrations
private function getPendingMigrations(): array
{
Artisan::call('migrate:status');

$output = trim(Artisan::output());
$lines = explode(PHP_EOL, $output);
$pendingMigrations = [];

foreach ($lines as $line) {
if (str_contains($line, 'Pending')) {
preg_match('/(\d{4}_\d{2}_\d{2}_\d{6}_\w+)/', $line, $matches);

if (!empty($matches[1])) {
$pendingMigrations[] = $matches[1];
} else {
$this->error("Unable to extract migration name from line: $line");
}
}
}

return $pendingMigrations;
}

// Function to determine whether to run a migration based on user confirmation or pipeline option
private function shouldRunMigration($migrationName): bool
{
$ignoreMigration = $this->option('ignore');

if ($ignoreMigration && $ignoreMigration === $migrationName) {
return false;
}

if ($this->option('skip')) {
return false;
}

return $this->confirm("Are you sure you want to run the migration $migrationName?");
}

// Function to run a migration
private function runMigration($migrationName): void
{
$migrationPath = $this->findMigrationPath($migrationName);

if ($migrationPath) {
Artisan::call('migrate', ['--path' => $migrationPath]);
$this->line(Artisan::output());
} else {
$this->error("Migration file not found for $migrationName");
}
}

// Function to find the path of a migration file
private function findMigrationPath($migrationName)
{
$migrationFiles = $this->getMigrationFiles('database/migrations');

foreach ($migrationFiles as $file) {
if (strpos($file, $migrationName) !== false) {
return $file;
}
}

return null;
}

// Function to retrieve migration files within a directory
private function getMigrationFiles($directory): array
{
$files = [];
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));

foreach ($iterator as $file) {
if ($file->isFile() && $file->getExtension() === 'php') {
$files[] = $file->getPathname();
}
}

return $files;
}
}
16 changes: 16 additions & 0 deletions src/CheckMigrationsServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
namespace levizoesch\checkmigrations;

use Illuminate\Support\ServiceProvider;
use levizoesch\checkmigrations\CheckMigrations;

class CheckMigrationsServiceProvider extends ServiceProvider
{

public function boot()
{
$this->commands([
CheckMigrations::class
]);
}
}

0 comments on commit ddde9bb

Please sign in to comment.