Skip to content

Commit 271a0c9

Browse files
Fix CLI migrator pending detection, allow default migration path registration, add regression tests and changelog entry
1 parent 96fab4b commit 271a0c9

5 files changed

Lines changed: 89 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
All significant changes to this project will be documented in this file.
44

5+
## [1.4.1] - 2025-12-10
6+
7+
### Added
8+
9+
- **CLI tests:** Added coverage for skipping already-ran migrations and for migration path resolver uniqueness/default path handling.
10+
11+
### Fixed
12+
13+
- **Migrator:** Pending detection now compares against ran migration names, preventing repeat execution of logged migrations.
14+
- **CLI path resolver:** Allows registering default migration path even if the directory does not exist yet and deduplicates entries.
15+
516
## [1.4.0] - 2025-12-10
617

718
### Added

src/Migrations/MigrationPathResolver.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ class MigrationPathResolver
1414
*/
1515
public function addPath(string $path): void
1616
{
17-
if (is_dir($path)) {
18-
$this->paths[] = rtrim($path, DIRECTORY_SEPARATOR);
19-
}
17+
// Allow registering paths even before the directory exists; it can be created later by CLI
18+
$this->paths[] = rtrim($path, DIRECTORY_SEPARATOR);
19+
20+
// Keep list unique to avoid duplicate lookups
21+
$this->paths = array_values(array_unique($this->paths));
2022
}
2123

2224
/**

src/Migrations/Migrator.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ public function migrate(): array
3232
$this->repository->ensureTableExists();
3333

3434
$files = $this->getMigrationFiles();
35-
$ran = $this->repository->getRan();
35+
// Compare by migration names only to avoid treating already-ran migrations as pending
36+
$ran = array_column($this->repository->getRan(), 'migration');
3637

3738
$pending = array_diff(array_keys($files), $ran);
3839

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Codemonster\Database\Tests\Migrations;
4+
5+
use Codemonster\Database\Migrations\MigrationPathResolver;
6+
use Codemonster\Database\Tests\TestCase;
7+
8+
class MigrationPathResolverTest extends TestCase
9+
{
10+
public function test_adds_nonexistent_path_and_keeps_unique()
11+
{
12+
$resolver = new MigrationPathResolver();
13+
14+
$path = sys_get_temp_dir() . '/cm_db_missing_' . uniqid('', true);
15+
16+
$resolver->addPath($path);
17+
// Duplicate with trailing slash to ensure it stays unique
18+
$resolver->addPath($path . DIRECTORY_SEPARATOR);
19+
20+
$paths = $resolver->getPaths();
21+
22+
$this->assertSame([$path], $paths);
23+
$this->assertFalse(is_dir($path));
24+
}
25+
}
26+

tests/Migrations/MigratorTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,49 @@ public function down(): void {}
5555
unlink($file);
5656
rmdir($dir);
5757
}
58+
59+
public function test_migrator_skips_already_ran_migrations()
60+
{
61+
$dir = sys_get_temp_dir() . '/cm_db_migrations_' . uniqid('', true);
62+
63+
mkdir($dir);
64+
65+
$first = '2025_01_01_000000_first_migration';
66+
$second = '2025_01_02_000000_second_migration';
67+
68+
foreach ([$first, $second] as $name) {
69+
file_put_contents($dir . DIRECTORY_SEPARATOR . $name . '.php', <<<PHP
70+
<?php
71+
72+
use Codemonster\\Database\\Migrations\\Migration;
73+
74+
return new class extends Migration {
75+
public function up(): void {}
76+
public function down(): void {}
77+
};
78+
PHP);
79+
}
80+
81+
$conn = new FakeConnection();
82+
$conn->migrations = [$first];
83+
84+
$repo = new MigrationRepository($conn);
85+
86+
/** @var MigrationPathResolver $paths */
87+
$paths = $this->createStub(MigrationPathResolver::class);
88+
$paths->method('getPaths')->willReturn([$dir]);
89+
90+
$migrator = new Migrator($repo, $conn, $paths);
91+
92+
$ran = $migrator->migrate();
93+
94+
$this->assertSame([$second], $ran);
95+
$this->assertSame([$first, $second], $conn->migrations);
96+
97+
foreach ([$first, $second] as $name) {
98+
unlink($dir . DIRECTORY_SEPARATOR . $name . '.php');
99+
}
100+
101+
rmdir($dir);
102+
}
58103
}

0 commit comments

Comments
 (0)