Duplicate Migrations
Closed this issue · 3 comments
- Testbench Version: 8.10.2
- Laravel Version: 10.23
- PHP Version: 8.1
- Database Driver & Version: SQLite - latest
Description:
When I run either of
testbench workbench:build
testbench package:test
pest --filter="some test"
I get an error saying that a table already exists
Steps To Reproduce:
I'm trying to do this on my package https://github.com/cjmellor/rating
I have a create_ratings_table.php
file within database/migrations
.
My testbench.yaml
file:
providers:
- Cjmellor\Rating\RatingServiceProvider
- Livewire\LivewireServiceProvider
migrations: true
seeders: []
workbench:
assets:
- rating-config
- rating-migrations
build:
- asset-publish
- create-sqlite-table
- migrate:fresh
guard: web
install: true
start: '/'
sync: []
user: 1
welcome: true
This is the Service Provider
<?php
namespace Cjmellor\Rating;
use Cjmellor\Rating\Livewire\Rating;
use Illuminate\Support\ServiceProvider;
use Livewire\Livewire;
class RatingServiceProvider extends ServiceProvider
{
public function boot(): void
{
$this->publishes([
__DIR__.'/../config/rating.php' => config_path('rating.php'),
], 'rating-config');
$this->loadViewsFrom(__DIR__.'/../resources/views', 'rating');
$this->publishes([
__DIR__.'/../database/migrations/create_ratings_table.php' => database_path('migrations/'.date('Y_m_d_His', time()).'_create_ratings_table.php'),
], 'rating-migrations');
Livewire::component('rating', Rating::class);
}
}
This is the TestCase.php code:
<?php
namespace Cjmellor\Rating\Tests;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Orchestra\Testbench\Concerns\WithWorkbench;
use Orchestra\Testbench\TestCase as Orchestra;
class TestCase extends Orchestra
{
use RefreshDatabase;
use WithWorkbench;
public function defineEnvironment($app): void
{
$app['config']->set('database.default', 'testing');
}
public function defineDatabaseMigrations(): void
{
$this->loadLaravelMigrations();
}
}
I ran both
testbench workbench:install
testbench workbench:build
Which gives me an output:
INFO Publishing [rating-config] assets.
Copying file [/Users/chris/Dev/Packages/rating/config/rating.php] to [config/rating.php] ................................ DONE
INFO Publishing [rating-migrations] assets.
Copying file [/Users/chris/Dev/Packages/rating/database/migrations/create_ratings_table.php] to [database/migrations/2023_09_16_002915_create_ratings_table.php] DONE
INFO No publishable resources for tag [laravel-assets].
File [database/database.sqlite] already exists ....................................................................... SKIPPED
Dropping all tables ................................................................................................. 3ms DONE
INFO Preparing database.
Creating migration table ............................................................................................ 1ms DONE
INFO Running migrations.
2014_10_12_000000_testbench_create_users_table ...................................................................... 1ms DONE
2014_10_12_100000_testbench_create_password_reset_tokens_table ...................................................... 0ms DONE
2019_08_19_000000_testbench_create_failed_jobs_table ................................................................ 1ms DONE
2023_09_14_230134_create_ratings_table .............................................................................. 2ms DONE
2023_09_14_230633_create_ratings_table .............................................................................. 0ms FAIL
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1 table "ratings" already exists (Connection: sqlite, SQL: create table "ratings" ("id" integer primary key autoincrement not null, "rateable_type" varchar not null, "rateable_id" integer not null, "user_id" integer, "rating" integer not null, "created_at" datetime, "updated_at" datetime, foreign key("user_id") references "users"("id") on delete set null))
at vendor/laravel/framework/src/Illuminate/Database/Connection.php:801
797▕ $this->getName(), $query, $this->prepareBindings($bindings), $e
798▕ );
799▕ }
800▕
➜ 801▕ throw new QueryException(
802▕ $this->getName(), $query, $this->prepareBindings($bindings), $e
803▕ );
804▕ }
805▕ }
It seems the migration is generated twice and trying to run twice.
Cannot for the life of me figure out why.
Thanks for taking the time to look.
database_path('migrations/'.date('Y_m_d_His', time()).'_create_ratings_table.php')
This pattern might work well before Laravel moves to new class extends Migration
but you should just set a fixed date.
Hmm, so I just changed it to
__DIR__.'/../workbench/database/migrations/2023_09_16_003400_create_ratings_table.php' => database_path('migrations/0000_00_00_000000_create_ratings_table.php'),
But testbench workbench:build
still produces that
INFO Running migrations.
0000_00_00_000000_create_ratings_table .............................................................................. 4ms DONE
2014_10_12_000000_testbench_create_users_table ...................................................................... 1ms DONE
2014_10_12_100000_testbench_create_password_reset_tokens_table ...................................................... 0ms DONE
2019_08_19_000000_testbench_create_failed_jobs_table ................................................................ 1ms DONE
2023_09_14_230134_create_ratings_table .............................................................................. 1ms FAIL
Not sure where 2023_09_14_230134_create_ratings_table
was coming from
I checked vendor/orchestra/testbench-core/laravel/database/migrations
and there was a ton of migrations in there with the same name but different dates (probably from the date() method) so I deleted them and now the build runs every time with the fixed date.
Is this the right way to do the migrations in the testbench package, or have I missed anything?
Thanks for the pointer!
This is an issue with any packages using new class extends Migration
+ publishing migrations in general.
Before this, each migrations has a unique class name and Laravel will throw duplicate class exception if you try publishing package migrations more than once, and it's no longer possible with new class
syntax.
You can use loadMigrationsFrom()
if you don't need to actually publish migrations or set a fixed date.