Skip to content

Commit 25a878b

Browse files
Prove carry-forward of package migrations over customized published set
Addresses zorporation/durable-workflow#400. Follows the TD-034 close (#32) which delivered fresh-install, publish-first, and repair-path tests but swapped prose for an automated test on the customized- migration path. The customized path that is actually testable in- package is the documented "publish, keep schema-compatible edits, and carry each new package migration forward in timestamp order" pattern — this test exercises it end to end. The test: 1. Publishes the package migrations, then deletes the repair migration (2026_04_16_000158) to simulate a snapshot taken before #32 fix. 2. Strips the memo column from the published workflow_run_summaries migration, simulating that older snapshot predated the memo column. 3. Adds a schema-compatible extra index on workflow_instances (workflow_class) to the published create_workflow_instances migration — a realistic user customization. 4. Drops all tables, migrates from the published path, asserts the schema came up without memo and with the custom index. 5. Copies the new repair migration from src/migrations/ into the published dir (the documented carry-forward step) and runs migrate again. 6. Asserts memo is now present AND the custom index survived the carry-forward run. Verified in isolation (phpunit --filter testCarryingForwardPackageMigrationOverCustomizedPublishedSet): 1 test, 9 assertions pass on PHP 8.4 + SQLite. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ae0192c commit 25a878b

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

tests/Unit/Providers/WorkflowServiceProviderTest.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,99 @@ public function testPublishedMigrationsCanRunAsInstallSource(): void
147147
}
148148
}
149149

150+
public function testCarryingForwardPackageMigrationOverCustomizedPublishedSet(): void
151+
{
152+
$this->deletePublishedWorkflowMigrations();
153+
154+
try {
155+
// 1. Publish the current package migrations.
156+
Artisan::call('vendor:publish', [
157+
'--tag' => 'migrations',
158+
'--force' => true,
159+
]);
160+
161+
$publishedDir = database_path('migrations');
162+
$repair = $publishedDir . '/2026_04_16_000158_repair_memo_on_workflow_run_summaries_table.php';
163+
$summaries = $publishedDir . '/2026_04_05_000106_create_workflow_run_summaries_table.php';
164+
$instances = $publishedDir . '/2026_04_05_000100_create_workflow_instances_table.php';
165+
166+
$this->assertFileExists($repair, 'Expected publish to include the repair migration.');
167+
$this->assertFileExists($summaries);
168+
$this->assertFileExists($instances);
169+
170+
// 2. Simulate a published snapshot taken before the repair
171+
// migration shipped by removing it from the published set.
172+
@unlink($repair);
173+
174+
// 3. Simulate that older snapshot's create_workflow_run_summaries
175+
// migration predating the memo column by stripping the column
176+
// declaration from the published copy only.
177+
$summariesContents = file_get_contents($summaries);
178+
$memoLine = " \$table->json('memo')\n ->nullable();\n";
179+
if (! str_contains($summariesContents, $memoLine)) {
180+
$this->markTestSkipped(
181+
'workflow_run_summaries published migration no longer matches the expected layout; adjust the test.'
182+
);
183+
}
184+
file_put_contents($summaries, str_replace($memoLine, '', $summariesContents));
185+
186+
// 4. Apply a schema-compatible user customization: an extra
187+
// secondary index on workflow_instances(workflow_class) that
188+
// the package does not ship.
189+
$instancesContents = file_get_contents($instances);
190+
$customIndex = " \$table->index('workflow_class', 'workflow_instances_workflow_class_index');\n";
191+
$hook = " \$table->string('workflow_class');\n";
192+
$this->assertStringContainsString($hook, $instancesContents);
193+
file_put_contents(
194+
$instances,
195+
str_replace($hook, $hook . $customIndex, $instancesContents),
196+
);
197+
198+
// 5. Run migrate from the customized published snapshot.
199+
Schema::dropAllTables();
200+
$this->artisan('migrate:install')
201+
->run();
202+
$this->artisan('migrate', [
203+
'--path' => $publishedDir,
204+
'--realpath' => true,
205+
])->run();
206+
207+
$this->assertTrue(Schema::hasTable('workflow_run_summaries'));
208+
$this->assertFalse(
209+
Schema::hasColumn('workflow_run_summaries', 'memo'),
210+
'Simulated older published snapshot should not yet carry the memo column.'
211+
);
212+
$this->assertTrue(
213+
Schema::hasIndex('workflow_instances', ['workflow_class']),
214+
'Custom index on the customized published migration should be present after migrate.'
215+
);
216+
217+
// 6. Carry the newer package migration forward into the published
218+
// dir in timestamp order, per the migration-guide instructions.
219+
$packageRepair = dirname(__DIR__, 3)
220+
. '/src/migrations/2026_04_16_000158_repair_memo_on_workflow_run_summaries_table.php';
221+
copy($packageRepair, $repair);
222+
223+
// 7. Re-run migrate. The repair migration should add the missing
224+
// column without disturbing the earlier customization.
225+
$this->artisan('migrate', [
226+
'--path' => $publishedDir,
227+
'--realpath' => true,
228+
])->run();
229+
230+
$this->assertTrue(
231+
Schema::hasColumn('workflow_run_summaries', 'memo'),
232+
'Carry-forward of the repair migration should add memo to workflow_run_summaries.'
233+
);
234+
$this->assertTrue(
235+
Schema::hasIndex('workflow_instances', ['workflow_class']),
236+
'User-added custom index should survive the carry-forward migrate run.'
237+
);
238+
} finally {
239+
$this->deletePublishedWorkflowMigrations();
240+
}
241+
}
242+
150243
public function testCommandsAreRegistered(): void
151244
{
152245
$registeredCommands = array_keys(Artisan::all());

0 commit comments

Comments
 (0)