Merge remote-tracking branch 'origin/next' into feat/noindex-domains

This commit is contained in:
Andras Bacsai committed 2026-08-08 11:26:20 +02:00
commit 003e44d123
1274 files changed
+156179 -25249

No files matched your search

+2 -1
View File
@@ -6,7 +6,7 @@ use App\Models\Team;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Team>
* @extends Factory<Team>
*/
class TeamFactory extends Factory
{
@@ -24,6 +24,7 @@ class TeamFactory extends Factory
'description' => $this->faker->sentence(),
'personal_team' => false,
'show_boarding' => false,
'is_mcp_server_enabled' => true,
];
}
@@ -0,0 +1,54 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('v5_clusters', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->foreignId('team_id')->constrained('teams')->cascadeOnDelete();
$table->foreignId('created_by_user_id')->constrained('users')->cascadeOnDelete();
$table->string('name');
$table->text('description')->nullable();
$table->string('wireguard_interface')->default('wg0');
$table->string('wireguard_management_pool')->default('100.64.0.0/16');
$table->unsignedInteger('wireguard_listen_port')->default(51820);
$table->string('container_network_pool')->default('10.210.0.0/16');
$table->unsignedTinyInteger('container_network_prefix')->default(24);
$table->json('namespaces')->nullable();
$table->boolean('default_deny_containers')->default(true);
$table->string('coold_version')->default('nightly');
$table->string('corrosion_version')->default('v1.0.0');
$table->unsignedInteger('corrosion_gossip_port')->default(8787);
$table->unsignedInteger('corrosion_api_port')->default(8080);
$table->boolean('builder_enabled')->default(true);
$table->unsignedInteger('builder_capacity')->default(2);
$table->string('builder_cpu_quota')->default('200%');
$table->string('builder_memory_max')->default('2G');
$table->unsignedInteger('builder_timeout_secs')->default(1800);
$table->string('last_cli_action')->nullable();
$table->string('last_cli_status')->nullable();
$table->text('last_cli_summary')->nullable();
$table->timestamp('last_cli_ran_at')->nullable();
$table->timestamps();
$table->unique(['team_id', 'name']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('v5_clusters');
}
};
@@ -0,0 +1,63 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('v5_servers', function (Blueprint $table) {
$table->id();
$table->string('uuid')->nullable()->unique();
$table->foreignId('team_id')->constrained('teams')->cascadeOnDelete();
$table->foreignId('cluster_id')->nullable()->constrained('v5_clusters')->nullOnDelete();
$table->foreignId('created_by_user_id')->constrained('users')->cascadeOnDelete();
$table->foreignId('private_key_id')->nullable()->constrained('private_keys')->nullOnDelete();
$table->string('name');
$table->string('host');
$table->string('ssh_user');
$table->unsignedInteger('ssh_port')->default(22);
$table->string('status')->default('installed');
$table->string('ingress_type')->nullable();
$table->string('ingress_status')->nullable();
$table->json('capabilities')->nullable();
$table->boolean('builder_enabled')->default(false);
$table->unsignedInteger('builder_capacity')->default(0);
$table->string('builder_cpu_quota')->default('200%');
$table->string('node_address')->nullable();
$table->unsignedInteger('wireguard_listen_port_override')->nullable();
$table->string('wireguard_endpoint_override')->nullable();
$table->string('wireguard_management_ip')->nullable();
$table->string('wireguard_public_key')->nullable();
$table->json('container_subnets')->nullable();
$table->integer('canvas_x')->nullable();
$table->integer('canvas_y')->nullable();
$table->timestamp('last_bootstrapped_at')->nullable();
$table->string('last_bootstrap_action')->nullable();
$table->string('last_bootstrap_status')->nullable();
$table->text('last_bootstrap_output')->nullable();
$table->timestamp('last_bootstrap_ran_at')->nullable();
$table->string('last_status_check')->nullable();
$table->text('last_status_output')->nullable();
$table->timestamp('last_status_checked_at')->nullable();
$table->timestamps();
$table->unique(['team_id', 'host', 'ssh_port']);
$table->index(['team_id', 'cluster_id']);
$table->index(['team_id', 'status']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('v5_servers');
}
};
@@ -0,0 +1,58 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('v5_applications', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->foreignId('team_id')->constrained('teams')->cascadeOnDelete();
$table->foreignId('project_id')->constrained('projects')->cascadeOnDelete();
$table->foreignId('environment_id')->constrained('environments')->cascadeOnDelete();
$table->foreignId('server_id')->nullable()->constrained('v5_servers')->nullOnDelete();
$table->foreignId('created_by_user_id')->constrained('users')->cascadeOnDelete();
$table->string('name');
$table->string('image');
$table->string('container_name')->unique();
$table->string('status')->default('creating');
$table->text('status_message')->nullable();
$table->string('runtime_container_id')->nullable();
$table->string('mesh_namespace')->default('default');
$table->boolean('ingress_enabled')->default(false);
$table->unsignedSmallInteger('internal_port')->nullable();
$table->integer('canvas_x')->default(0);
$table->integer('canvas_y')->default(0);
$table->timestamps();
$table->index(['team_id', 'status']);
$table->index(['team_id', 'project_id', 'environment_id']);
$table->index(['team_id', 'server_id']);
});
Schema::create('v5_application_domains', function (Blueprint $table) {
$table->id();
$table->foreignId('application_id')->constrained('v5_applications')->cascadeOnDelete();
$table->string('domain');
$table->timestamps();
$table->unique(['application_id', 'domain']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('v5_application_domains');
Schema::dropIfExists('v5_applications');
}
};
@@ -0,0 +1,59 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('v5_resource_connections', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->foreignId('team_id')->constrained('teams')->cascadeOnDelete();
$table->foreignId('project_id')->constrained('projects')->cascadeOnDelete();
$table->foreignId('environment_id')->constrained('environments')->cascadeOnDelete();
$table->morphs('resource_one');
$table->morphs('resource_two');
$table->string('resource_pair_key');
$table->foreignId('created_by_user_id')->constrained('users')->cascadeOnDelete();
$table->timestamps();
$table->unique(['team_id', 'resource_pair_key']);
$table->index(['team_id', 'project_id', 'environment_id']);
});
Schema::create('v5_resource_connection_rules', function (Blueprint $table) {
$table->id();
$table->foreignId('connection_id')->constrained('v5_resource_connections')->cascadeOnDelete();
$table->morphs('source_resource');
$table->morphs('target_resource');
$table->string('protocol')->default('tcp');
$table->unsignedSmallInteger('port');
$table->timestamps();
$table->unique([
'connection_id',
'source_resource_type',
'source_resource_id',
'target_resource_type',
'target_resource_id',
'protocol',
'port',
], 'v5_resource_connection_rules_unique_direction_port');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('v5_resource_connection_rules');
Schema::dropIfExists('v5_resource_connections');
}
};
@@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('v5_container_statuses', function (Blueprint $table) {
$table->id();
$table->foreignId('team_id')->constrained('teams')->cascadeOnDelete();
$table->foreignId('server_id')->constrained('v5_servers')->cascadeOnDelete();
$table->string('container_id');
$table->string('container_name')->nullable();
$table->string('image')->nullable();
$table->string('status')->default('unknown');
$table->text('status_message')->nullable();
$table->timestamp('last_seen_at')->nullable();
$table->timestamps();
$table->unique(['server_id', 'container_id']);
$table->index(['team_id', 'server_id']);
$table->index(['team_id', 'status']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('v5_container_statuses');
}
};
@@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->index('wireguard_management_ip');
$table->index('node_address');
$table->index('host');
});
Schema::table('v5_applications', function (Blueprint $table) {
$table->index('runtime_container_id');
});
Schema::table('v5_container_statuses', function (Blueprint $table) {
$table->index('last_seen_at');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->dropIndex(['wireguard_management_ip']);
$table->dropIndex(['node_address']);
$table->dropIndex(['host']);
});
Schema::table('v5_applications', function (Blueprint $table) {
$table->dropIndex(['runtime_container_id']);
});
Schema::table('v5_container_statuses', function (Blueprint $table) {
$table->dropIndex(['last_seen_at']);
});
}
};
@@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
DB::table('v5_servers')
->whereNull('uuid')
->pluck('id')
->each(function (int $id): void {
DB::table('v5_servers')
->where('id', $id)
->update(['uuid' => Str::lower(Str::random(24))]);
});
Schema::table('v5_servers', function (Blueprint $table) {
$table->string('uuid')->nullable(false)->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->string('uuid')->nullable()->change();
});
}
};
@@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->timestamp('status_observed_at')->nullable()->after('status');
});
Schema::table('v5_applications', function (Blueprint $table) {
$table->timestamp('status_observed_at')->nullable()->after('status_message');
});
Schema::table('v5_container_statuses', function (Blueprint $table) {
$table->timestamp('status_observed_at')->nullable()->after('status_message');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->dropColumn('status_observed_at');
});
Schema::table('v5_applications', function (Blueprint $table) {
$table->dropColumn('status_observed_at');
});
Schema::table('v5_container_statuses', function (Blueprint $table) {
$table->dropColumn('status_observed_at');
});
}
};
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->string('coold_version')->nullable()->after('wireguard_public_key');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->dropColumn('coold_version');
});
}
};
@@ -0,0 +1,74 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
/**
* Rewrites v5 polymorphic rows that stored the Application FQCN (written
* before the 'v5.application' morph alias existed) so a future class rename
* cannot orphan them. New rows pick up the alias via getMorphClass().
*/
return new class extends Migration
{
private const FQCN = 'App\Models\V5\Application';
private const ALIAS = 'v5.application';
public function up(): void
{
$this->rewriteMorphTypes(self::FQCN, self::ALIAS);
$this->rewritePairKeys(self::FQCN, self::ALIAS);
}
public function down(): void
{
$this->rewriteMorphTypes(self::ALIAS, self::FQCN);
$this->rewritePairKeys(self::ALIAS, self::FQCN);
}
private function rewriteMorphTypes(string $from, string $to): void
{
if (Schema::hasTable('v5_resource_connections')) {
foreach (['resource_one_type', 'resource_two_type'] as $column) {
DB::table('v5_resource_connections')
->where($column, $from)
->update([$column => $to]);
}
}
if (Schema::hasTable('v5_resource_connection_rules')) {
foreach (['source_resource_type', 'target_resource_type'] as $column) {
DB::table('v5_resource_connection_rules')
->where($column, $from)
->update([$column => $to]);
}
}
}
private function rewritePairKeys(string $from, string $to): void
{
if (! Schema::hasTable('v5_resource_connections')) {
return;
}
// Backslash escaping in LIKE patterns differs between Postgres and
// SQLite, so match the FQCN in PHP instead of in SQL.
DB::table('v5_resource_connections')
->select(['id', 'resource_pair_key'])
->orderBy('id')
->chunkById(100, function ($connections) use ($from, $to): void {
foreach ($connections as $connection) {
if (! str_contains((string) $connection->resource_pair_key, $from)) {
continue;
}
DB::table('v5_resource_connections')
->where('id', $connection->id)
->update([
'resource_pair_key' => str_replace($from, $to, $connection->resource_pair_key),
]);
}
});
}
};
@@ -0,0 +1,74 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
/**
* Replaces the unindexable v5_servers.capabilities JSON array of magic strings
* with indexed has_coold / is_ingress booleans. The Server model keeps
* exposing a computed `capabilities` array so serialized payloads stay
* identical.
*/
return new class extends Migration
{
public function up(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->boolean('has_coold')->default(false)->index();
$table->boolean('is_ingress')->default(false)->index();
});
DB::table('v5_servers')
->select(['id', 'capabilities'])
->orderBy('id')
->chunkById(100, function ($servers): void {
foreach ($servers as $server) {
$capabilities = json_decode($server->capabilities ?? '[]', true);
if (! is_array($capabilities) || $capabilities === []) {
continue;
}
DB::table('v5_servers')->where('id', $server->id)->update([
'has_coold' => in_array('coold', $capabilities, true),
'is_ingress' => in_array('ingress', $capabilities, true),
]);
}
});
Schema::table('v5_servers', function (Blueprint $table) {
$table->dropColumn('capabilities');
});
}
public function down(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->json('capabilities')->nullable();
});
DB::table('v5_servers')
->select(['id', 'has_coold', 'is_ingress'])
->orderBy('id')
->chunkById(100, function ($servers): void {
foreach ($servers as $server) {
$capabilities = array_values(array_filter([
$server->has_coold ? 'coold' : null,
$server->is_ingress ? 'ingress' : null,
]));
DB::table('v5_servers')->where('id', $server->id)->update([
'capabilities' => json_encode($capabilities),
]);
}
});
Schema::table('v5_servers', function (Blueprint $table) {
$table->dropIndex(['has_coold']);
$table->dropIndex(['is_ingress']);
$table->dropColumn(['has_coold', 'is_ingress']);
});
}
};
@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->string('agent_token_jti')->nullable()->after('coold_version');
});
}
public function down(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->dropColumn('agent_token_jti');
});
}
};
@@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('v5_revoked_agent_tokens', function (Blueprint $table) {
$table->id();
$table->string('jti')->unique();
$table->foreignId('server_id')->nullable();
$table->timestamp('revoked_at')->nullable();
$table->timestamp('expires_at')->nullable()->index();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('v5_revoked_agent_tokens');
}
};
@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->timestamp('agent_token_expires_at')->nullable()->after('agent_token_jti');
});
}
public function down(): void
{
Schema::table('v5_servers', function (Blueprint $table) {
$table->dropColumn('agent_token_expires_at');
});
}
};
@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* The uuid columns were added by editing the original v5 create migrations,
* so databases that ran those migrations before the edit (including the
* checked-in testing schema dump) are missing them. Guarded so freshly
* migrated databases are untouched.
*/
return new class extends Migration
{
private const TABLES = ['v5_applications', 'v5_clusters', 'v5_resource_connections'];
public function up(): void
{
foreach (self::TABLES as $tableName) {
if (! Schema::hasTable($tableName) || Schema::hasColumn($tableName, 'uuid')) {
continue;
}
Schema::table($tableName, function (Blueprint $table) {
$table->string('uuid')->nullable()->unique();
});
}
}
public function down(): void
{
// Intentionally left empty: the uuid columns belong to the create
// migrations; dropping them here could destroy live identifiers.
}
};
@@ -1,70 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Get the migration connection name.
*/
public function getConnection(): ?string
{
return config('telescope.storage.database.connection');
}
/**
* Run the migrations.
*/
public function up(): void
{
$schema = Schema::connection($this->getConnection());
$schema->create('telescope_entries', function (Blueprint $table) {
$table->bigIncrements('sequence');
$table->uuid('uuid');
$table->uuid('batch_id');
$table->string('family_hash')->nullable();
$table->boolean('should_display_on_index')->default(true);
$table->string('type', 20);
$table->longText('content');
$table->dateTime('created_at')->nullable();
$table->unique('uuid');
$table->index('batch_id');
$table->index('family_hash');
$table->index('created_at');
$table->index(['type', 'should_display_on_index']);
});
$schema->create('telescope_entries_tags', function (Blueprint $table) {
$table->uuid('entry_uuid');
$table->string('tag');
$table->primary(['entry_uuid', 'tag']);
$table->index('tag');
$table->foreign('entry_uuid')
->references('uuid')
->on('telescope_entries')
->onDelete('cascade');
});
$schema->create('telescope_monitoring', function (Blueprint $table) {
$table->string('tag')->primary();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
$schema = Schema::connection($this->getConnection());
$schema->dropIfExists('telescope_entries_tags');
$schema->dropIfExists('telescope_entries');
$schema->dropIfExists('telescope_monitoring');
}
};
@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('gitlab_apps', function (Blueprint $table) {
$table->longText('client_id')->nullable()->after('app_secret');
$table->longText('client_secret')->nullable()->after('client_id');
$table->longText('access_token')->nullable()->after('client_secret');
$table->longText('refresh_token')->nullable()->after('access_token');
$table->integer('expires_at')->nullable()->after('refresh_token');
$table->string('redirect_uri')->nullable()->after('expires_at');
});
}
public function down(): void
{
Schema::table('gitlab_apps', function (Blueprint $table) {
$table->dropColumn([
'client_id',
'client_secret',
'access_token',
'refresh_token',
'expires_at',
'redirect_uri',
]);
});
}
};
@@ -0,0 +1,46 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('scheduled_volume_backups', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->string('backupable_type');
$table->unsignedBigInteger('backupable_id');
$table->foreignId('team_id')->constrained()->cascadeOnDelete();
$table->foreignId('s3_storage_id')->nullable()->constrained()->nullOnDelete();
$table->string('frequency');
$table->boolean('enabled')->default(true);
$table->boolean('save_s3')->default(false);
$table->boolean('disable_local_backup')->default(false);
$table->boolean('stop_during_backup')->default(false);
$table->unsignedInteger('retention_amount_locally')->default(7);
$table->unsignedInteger('retention_days_locally')->default(0);
$table->decimal('retention_max_storage_locally', 17, 7)->default(0);
$table->unsignedInteger('retention_amount_s3')->default(7);
$table->unsignedInteger('retention_days_s3')->default(0);
$table->decimal('retention_max_storage_s3', 17, 7)->default(0);
$table->unsignedInteger('timeout')->default(3600);
$table->timestamps();
$table->unique(['backupable_type', 'backupable_id']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('scheduled_volume_backups');
}
};
@@ -0,0 +1,43 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('scheduled_volume_backup_executions', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->foreignId('scheduled_volume_backup_id')->constrained()->cascadeOnDelete();
$table->foreignId('s3_storage_id')->nullable()->constrained()->nullOnDelete();
$table->enum('status', ['success', 'failed', 'running'])->default('running');
$table->longText('message')->nullable();
$table->unsignedBigInteger('size')->default(0);
$table->text('filename')->nullable();
$table->json('stop_container_ids')->nullable();
$table->boolean('stop_recovery_pending')->default(false);
$table->boolean('s3_cleanup_pending')->default(false);
$table->timestamp('finished_at')->nullable();
$table->boolean('local_storage_deleted')->default(false);
$table->boolean('s3_storage_deleted')->default(false);
$table->boolean('s3_uploaded')->nullable();
$table->timestamps();
$table->index(['scheduled_volume_backup_id', 'created_at'], 'scheduled_volume_executions_backup_created_index');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('scheduled_volume_backup_executions');
}
};
@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('applications', function (Blueprint $table) {
$table->json('domain_dns_statuses')->nullable()->after('docker_compose_domains');
});
}
public function down(): void
{
Schema::table('applications', function (Blueprint $table) {
$table->dropColumn('domain_dns_statuses');
});
}
};
@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('service_applications', function (Blueprint $table) {
$table->json('domain_dns_statuses')->nullable()->after('fqdn');
});
}
public function down(): void
{
Schema::table('service_applications', function (Blueprint $table) {
$table->dropColumn('domain_dns_statuses');
});
}
};
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('service_applications', function (Blueprint $table) {
$table->enum('redirect', ['www', 'non-www', 'both'])->default('both')->after('fqdn');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('service_applications', function (Blueprint $table) {
$table->dropColumn('redirect');
});
}
};
@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('instance_settings', function (Blueprint $table) {
$table->text('domain_connect_private_key')->nullable()->after('custom_dns_servers');
});
}
public function down(): void
{
Schema::table('instance_settings', function (Blueprint $table) {
$table->dropColumn('domain_connect_private_key');
});
}
};
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('avatar_path')->nullable();
$table->string('avatar_storage_type')->nullable();
$table->foreignId('avatar_s3_storage_id')->nullable()->constrained('s3_storages')->nullOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropConstrainedForeignId('avatar_s3_storage_id');
$table->dropColumn(['avatar_path', 'avatar_storage_type']);
});
}
};
@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('instance_settings', function (Blueprint $table) {
$table->string('avatar_storage_type')->default('local');
$table->foreignId('avatar_s3_storage_id')->nullable()->constrained('s3_storages')->nullOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('instance_settings', function (Blueprint $table) {
$table->dropConstrainedForeignId('avatar_s3_storage_id');
$table->dropColumn('avatar_storage_type');
});
}
};
+158 -25
View File
@@ -370,6 +370,12 @@ CREATE TABLE IF NOT EXISTS "gitlab_apps" (
"is_public" INTEGER DEFAULT false NOT NULL,
"app_id" INTEGER,
"app_secret" TEXT,
"client_id" TEXT,
"client_secret" TEXT,
"access_token" TEXT,
"refresh_token" TEXT,
"expires_at" INTEGER,
"redirect_uri" TEXT,
"oauth_id" INTEGER,
"group_name" TEXT,
"public_key" TEXT,
@@ -690,7 +696,7 @@ CREATE TABLE IF NOT EXISTS "servers" (
"port" INTEGER DEFAULT 22 NOT NULL,
"user" TEXT DEFAULT 'root' NOT NULL,
"team_id" INTEGER NOT NULL,
"private_key_id" INTEGER NOT NULL,
"private_key_id" INTEGER,
"proxy" TEXT,
"created_at" TEXT,
"updated_at" TEXT,
@@ -1274,25 +1280,8 @@ CREATE TABLE IF NOT EXISTS "telegram_notification_settings" (
"traefik_outdated_telegram_notifications" INTEGER DEFAULT true NOT NULL
);
CREATE TABLE IF NOT EXISTS "telescope_entries" (
"sequence" INTEGER NOT NULL,
"uuid" TEXT NOT NULL,
"batch_id" TEXT NOT NULL,
"family_hash" TEXT,
"should_display_on_index" INTEGER DEFAULT true NOT NULL,
"type" TEXT NOT NULL,
"content" TEXT NOT NULL,
"created_at" TEXT
);
CREATE TABLE IF NOT EXISTS "telescope_entries_tags" (
"entry_uuid" TEXT NOT NULL,
"tag" TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS "telescope_monitoring" (
"tag" TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS "user_changelog_reads" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
@@ -1322,6 +1311,146 @@ CREATE TABLE IF NOT EXISTS "users" (
"email_change_code_expires_at" TEXT
);
CREATE TABLE IF NOT EXISTS "v5_clusters" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"team_id" INTEGER NOT NULL,
"created_by_user_id" INTEGER NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,
"wireguard_interface" TEXT DEFAULT 'wg0' NOT NULL,
"wireguard_management_pool" TEXT DEFAULT '100.64.0.0/16' NOT NULL,
"wireguard_listen_port" INTEGER DEFAULT '51820' NOT NULL,
"container_network_pool" TEXT DEFAULT '10.210.0.0/16' NOT NULL,
"container_network_prefix" INTEGER DEFAULT '24' NOT NULL,
"namespaces" JSON,
"default_deny_containers" INTEGER DEFAULT true NOT NULL,
"coold_version" TEXT DEFAULT 'nightly' NOT NULL,
"corrosion_version" TEXT DEFAULT 'v1.0.0' NOT NULL,
"corrosion_gossip_port" INTEGER DEFAULT '8787' NOT NULL,
"corrosion_api_port" INTEGER DEFAULT '8080' NOT NULL,
"builder_enabled" INTEGER DEFAULT true NOT NULL,
"builder_capacity" INTEGER DEFAULT '2' NOT NULL,
"builder_cpu_quota" TEXT DEFAULT '200%' NOT NULL,
"builder_memory_max" TEXT DEFAULT '2G' NOT NULL,
"builder_timeout_secs" INTEGER NOT NULL DEFAULT '1800',
"last_cli_action" TEXT,
"last_cli_status" TEXT,
"last_cli_summary" TEXT,
"last_cli_ran_at" TEXT,
"created_at" TEXT,
"updated_at" TEXT
);
CREATE TABLE IF NOT EXISTS "v5_servers" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"uuid" TEXT,
"team_id" INTEGER NOT NULL,
"cluster_id" INTEGER,
"created_by_user_id" INTEGER NOT NULL,
"private_key_id" INTEGER,
"name" TEXT NOT NULL,
"host" TEXT NOT NULL,
"ssh_user" TEXT NOT NULL,
"ssh_port" INTEGER DEFAULT '22' NOT NULL,
"status" TEXT DEFAULT 'installed' NOT NULL,
"ingress_type" TEXT,
"ingress_status" TEXT,
"capabilities" TEXT,
"builder_enabled" INTEGER DEFAULT false NOT NULL,
"builder_capacity" INTEGER DEFAULT '0' NOT NULL,
"builder_cpu_quota" TEXT DEFAULT '200%' NOT NULL,
"node_address" TEXT,
"wireguard_listen_port_override" INTEGER,
"wireguard_endpoint_override" TEXT,
"wireguard_management_ip" TEXT,
"wireguard_public_key" TEXT,
"container_subnets" JSON,
"canvas_x" INTEGER,
"canvas_y" INTEGER,
"last_bootstrapped_at" TEXT,
"last_bootstrap_action" TEXT,
"last_bootstrap_status" TEXT,
"last_bootstrap_output" TEXT,
"last_bootstrap_ran_at" TEXT,
"last_status_check" TEXT,
"last_status_output" TEXT,
"last_status_checked_at" TEXT,
"created_at" TEXT,
"updated_at" TEXT
);
CREATE TABLE IF NOT EXISTS "v5_container_statuses" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"team_id" INTEGER NOT NULL,
"server_id" INTEGER NOT NULL,
"container_id" TEXT NOT NULL,
"container_name" TEXT,
"image" TEXT,
"status" TEXT DEFAULT 'unknown' NOT NULL,
"status_message" TEXT,
"last_seen_at" TEXT,
"created_at" TEXT,
"updated_at" TEXT
);
CREATE TABLE IF NOT EXISTS "v5_applications" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"team_id" INTEGER NOT NULL,
"project_id" INTEGER NOT NULL,
"environment_id" INTEGER NOT NULL,
"server_id" INTEGER,
"created_by_user_id" INTEGER NOT NULL,
"name" TEXT NOT NULL,
"image" TEXT NOT NULL,
"container_name" TEXT NOT NULL,
"status" TEXT DEFAULT 'creating' NOT NULL,
"status_message" TEXT,
"runtime_container_id" TEXT,
"mesh_namespace" TEXT DEFAULT 'default' NOT NULL,
"ingress_enabled" INTEGER DEFAULT false NOT NULL,
"internal_port" INTEGER,
"canvas_x" INTEGER DEFAULT '0' NOT NULL,
"canvas_y" INTEGER DEFAULT '0' NOT NULL,
"created_at" TEXT,
"updated_at" TEXT
);
CREATE TABLE IF NOT EXISTS "v5_application_domains" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"application_id" INTEGER NOT NULL,
"domain" TEXT NOT NULL,
"created_at" TEXT,
"updated_at" TEXT
);
CREATE TABLE IF NOT EXISTS "v5_resource_connections" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"team_id" INTEGER NOT NULL,
"project_id" INTEGER NOT NULL,
"environment_id" INTEGER NOT NULL,
"resource_one_type" TEXT NOT NULL,
"resource_one_id" INTEGER NOT NULL,
"resource_two_type" TEXT NOT NULL,
"resource_two_id" INTEGER NOT NULL,
"resource_pair_key" TEXT NOT NULL,
"created_by_user_id" INTEGER NOT NULL,
"created_at" TEXT,
"updated_at" TEXT
);
CREATE TABLE IF NOT EXISTS "v5_resource_connection_rules" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"connection_id" INTEGER NOT NULL,
"source_resource_type" TEXT NOT NULL,
"source_resource_id" INTEGER NOT NULL,
"target_resource_type" TEXT NOT NULL,
"target_resource_id" INTEGER NOT NULL,
"protocol" TEXT DEFAULT 'tcp' NOT NULL,
"port" INTEGER NOT NULL,
"created_at" TEXT,
"updated_at" TEXT
);
CREATE TABLE IF NOT EXISTS "webhook_notification_settings" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"team_id" INTEGER NOT NULL,
@@ -1426,23 +1555,21 @@ CREATE UNIQUE INDEX IF NOT EXISTS "team_invitations_team_id_email_unique" ON "te
CREATE UNIQUE INDEX IF NOT EXISTS "team_invitations_uuid_unique" ON "team_invitations" (uuid);
CREATE UNIQUE INDEX IF NOT EXISTS "team_user_team_id_user_id_unique" ON "team_user" (team_id, user_id);
CREATE UNIQUE INDEX IF NOT EXISTS "telegram_notification_settings_team_id_unique" ON "telegram_notification_settings" (team_id);
CREATE INDEX IF NOT EXISTS "telescope_entries_batch_id_index" ON "telescope_entries" (batch_id);
CREATE INDEX IF NOT EXISTS "telescope_entries_created_at_index" ON "telescope_entries" (created_at);
CREATE INDEX IF NOT EXISTS "telescope_entries_family_hash_index" ON "telescope_entries" (family_hash);
CREATE INDEX IF NOT EXISTS "telescope_entries_type_should_display_on_index_index" ON "telescope_entries" (type, should_display_on_index);
CREATE UNIQUE INDEX IF NOT EXISTS "telescope_entries_uuid_unique" ON "telescope_entries" (uuid);
CREATE INDEX IF NOT EXISTS "telescope_entries_tags_tag_index" ON "telescope_entries_tags" (tag);
CREATE INDEX IF NOT EXISTS "user_changelog_reads_release_tag_index" ON "user_changelog_reads" (release_tag);
CREATE INDEX IF NOT EXISTS "user_changelog_reads_user_id_index" ON "user_changelog_reads" (user_id);
CREATE UNIQUE INDEX IF NOT EXISTS "user_changelog_reads_user_id_release_tag_unique" ON "user_changelog_reads" (user_id, release_tag);
CREATE UNIQUE INDEX IF NOT EXISTS "users_email_unique" ON "users" (email);
CREATE UNIQUE INDEX IF NOT EXISTS "v5_applications_container_name_unique" ON "v5_applications" (container_name);
CREATE UNIQUE INDEX IF NOT EXISTS "v5_application_domains_application_id_domain_unique" ON "v5_application_domains" (application_id, domain);
CREATE UNIQUE INDEX IF NOT EXISTS "v5_resource_connections_team_id_resource_pair_key_unique" ON "v5_resource_connections" (team_id, resource_pair_key);
CREATE UNIQUE INDEX IF NOT EXISTS "v5_resource_connection_rules_unique_direction_port" ON "v5_resource_connection_rules" (connection_id, source_resource_type, source_resource_id, target_resource_type, target_resource_id, protocol, port);
CREATE UNIQUE INDEX IF NOT EXISTS "v5_servers_uuid_unique" ON "v5_servers" (uuid);
CREATE UNIQUE INDEX IF NOT EXISTS "webhook_notification_settings_team_id_unique" ON "webhook_notification_settings" (team_id);
-- Migration records
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (1, '2014_10_12_000000_create_users_table', 1);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (2, '2014_10_12_100000_create_password_reset_tokens_table', 2);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (3, '2014_10_12_200000_add_two_factor_columns_to_users_table', 3);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (4, '2018_08_08_100000_create_telescope_entries_table', 4);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (5, '2019_12_14_000001_create_personal_access_tokens_table', 5);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (6, '2023_03_20_112410_create_activity_log_table', 6);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (7, '2023_03_20_112411_add_event_column_to_activity_log_table', 7);
@@ -1753,3 +1880,9 @@ INSERT INTO "migrations" ("id", "migration", "batch") VALUES (311, '2025_12_10_1
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (312, '2025_12_15_143052_trim_s3_storage_credentials', 312);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (313, '2025_12_17_000001_add_is_wire_navigate_enabled_to_instance_settings_table', 313);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (314, '2025_12_17_000002_add_restart_tracking_to_standalone_databases', 314);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (315, '2026_06_03_000000_add_oauth_fields_to_gitlab_apps_table', 315);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (316, '2026_06_16_130649_v5_create_clusters_table', 316);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (317, '2026_06_16_130650_v5_create_servers_table', 317);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (318, '2026_06_19_140000_v5_create_applications_table', 318);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (319, '2026_06_19_142000_v5_create_resource_connections_table', 319);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (320, '2026_06_19_182231_create_container_statuses_table', 320);
@@ -26,27 +26,6 @@ class DevelopmentRailpackExamplesSeeder extends Seeder
public const REPOSITORY_PROJECT_ID = 603035348;
public const LIMA_SERVERS = [
[
'server_uuid' => 'lima-ubuntu-2404',
'server_name' => 'lima-ubuntu-2404',
'port' => 2222,
'environment_name' => 'ubuntu24',
'environment_uuid' => 'railpack-examples-ubuntu24',
'uuid_prefix' => 'ubuntu24-',
],
[
'server_uuid' => 'lima-ubuntu-2604',
'server_name' => 'lima-ubuntu-2604',
'port' => 2223,
'environment_name' => 'ubuntu26',
'environment_uuid' => 'railpack-examples-ubuntu26',
'uuid_prefix' => 'ubuntu26-',
],
];
private const LIMA_SENTINEL_URL = 'http://host.lima.internal:8000';
public function run(): void
{
if (! $this->isDevelopmentEnvironment()) {
@@ -64,15 +43,7 @@ class DevelopmentRailpackExamplesSeeder extends Seeder
$this->cleanupLegacyLimaProjects();
$this->cleanupLegacyProductionExamples();
foreach (self::LIMA_SERVERS as $limaServer) {
$this->seedEnvironment(
environmentUuid: $limaServer['environment_uuid'],
environmentName: $limaServer['environment_name'],
destination: $this->limaDestination($limaServer['server_uuid']),
uuidPrefix: $limaServer['uuid_prefix'],
nameSuffix: " ({$limaServer['environment_name']})",
);
}
$this->seedEnvironment(StandaloneDocker::query()->findOrFail(0));
}
/**
@@ -465,37 +436,6 @@ KEY,
],
);
foreach (self::LIMA_SERVERS as $limaServer) {
$server = Server::query()->firstOrCreate(
['uuid' => $limaServer['server_uuid']],
[
'name' => $limaServer['server_name'],
'description' => 'This is a Lima VM for local development testing',
'ip' => 'host.docker.internal',
'port' => $limaServer['port'],
'team_id' => 0,
'private_key_id' => 1,
'proxy' => [
'type' => ProxyTypes::TRAEFIK->value,
'status' => ProxyStatus::EXITED->value,
],
],
);
$server->settings->forceFill([
'sentinel_custom_url' => self::LIMA_SENTINEL_URL,
])->saveQuietly();
StandaloneDocker::query()->firstOrCreate(
['server_id' => $server->id],
[
'uuid' => "{$limaServer['server_uuid']}-docker",
'name' => "{$limaServer['server_name']} Docker",
'network' => 'coolify',
],
);
}
StandaloneDocker::query()->firstOrCreate(
['id' => 0],
[
@@ -545,21 +485,6 @@ KEY,
return in_array(config('app.env'), ['local', 'development', 'dev'], true);
}
private function limaDestination(string $serverUuid): StandaloneDocker
{
$limaDestination = Server::query()
->where('uuid', $serverUuid)
->first()
?->standaloneDockers()
->first();
if (! $limaDestination) {
throw new RuntimeException("Lima StandaloneDocker destination is required for {$serverUuid} before running DevelopmentRailpackExamplesSeeder.");
}
return $limaDestination;
}
private function cleanupLegacyLimaProjects(): void
{
Project::query()
@@ -595,21 +520,16 @@ KEY,
->forceDelete();
}
private function seedEnvironment(
string $environmentUuid,
string $environmentName,
StandaloneDocker $destination,
string $uuidPrefix = '',
string $nameSuffix = '',
): void {
$environment = $this->prepareEnvironment($environmentUuid, $environmentName);
private function seedEnvironment(StandaloneDocker $destination): void
{
$environment = $this->prepareEnvironment();
foreach (self::examples() as $example) {
$this->upsertApplication($environment, $destination, $example, $uuidPrefix, $nameSuffix);
$this->upsertApplication($environment, $destination, $example);
}
}
private function prepareEnvironment(string $environmentUuid, string $environmentName): Environment
private function prepareEnvironment(): Environment
{
$project = Project::query()->firstOrNew(['uuid' => self::PROJECT_UUID]);
$project->fill([
@@ -619,31 +539,20 @@ KEY,
]);
$project->save();
$environment = $project->environments()
->where(function ($query) use ($environmentName, $environmentUuid): void {
$query
->where('name', $environmentName)
->orWhere('uuid', $environmentUuid);
})
->first();
$environment = $project->environments()->firstOrCreate(['name' => 'production']);
$existingEnvironment = $project->environments()->first();
$project->environments()
->whereKeyNot($environment->id)
->get()
->each(function (Environment $obsoleteEnvironment): void {
Application::withTrashed()
->where('environment_id', $obsoleteEnvironment->id)
->get()
->each
->forceDelete();
if (! $environment && $project->environments()->count() === 1 && $existingEnvironment?->name === 'production') {
$environment = $existingEnvironment;
}
if (! $environment) {
$environment = $project->environments()->create([
'name' => $environmentName,
'uuid' => $environmentUuid,
]);
} else {
$environment->update([
'name' => $environmentName,
'uuid' => $environmentUuid,
]);
}
$obsoleteEnvironment->delete();
});
return $environment;
}
@@ -651,10 +560,10 @@ KEY,
/**
* @param array<string, mixed> $example
*/
private function upsertApplication(Environment $environment, StandaloneDocker $destination, array $example, string $uuidPrefix = '', string $nameSuffix = ''): void
private function upsertApplication(Environment $environment, StandaloneDocker $destination, array $example): void
{
$uuid = $uuidPrefix.$example['uuid'];
$name = $example['name'].$nameSuffix;
$uuid = $example['uuid'];
$name = $example['name'];
$application = Application::withTrashed()->firstOrNew(['uuid' => $uuid]);
$application->fill([
'name' => $name,
+1 -16
View File
@@ -7,28 +7,13 @@ use Illuminate\Database\Seeder;
class ProjectSeeder extends Seeder
{
private const LIMA_ENVIRONMENTS = [
['name' => 'ubuntu24', 'uuid' => 'ubuntu24'],
['name' => 'ubuntu26', 'uuid' => 'ubuntu26'],
];
public function run(): void
{
$project = Project::create([
Project::create([
'uuid' => 'project',
'name' => 'My first project',
'description' => 'This is a test project in development',
'team_id' => 0,
]);
foreach (self::LIMA_ENVIRONMENTS as $index => $environment) {
if ($index === 0) {
$project->environments()->first()->update($environment);
continue;
}
$project->environments()->create($environment);
}
}
}
-27
View File
@@ -9,13 +9,6 @@ use Illuminate\Database\Seeder;
class ServerSeeder extends Seeder
{
private const LIMA_SENTINEL_URL = 'http://host.lima.internal:8000';
private const LIMA_SERVERS = [
['uuid' => 'lima-ubuntu-2404', 'name' => 'lima-ubuntu-2404', 'port' => 2222],
['uuid' => 'lima-ubuntu-2604', 'name' => 'lima-ubuntu-2604', 'port' => 2223],
];
public function run(): void
{
Server::create([
@@ -31,25 +24,5 @@ class ServerSeeder extends Seeder
'status' => ProxyStatus::EXITED->value,
],
]);
foreach (self::LIMA_SERVERS as $limaServer) {
$server = Server::create([
'uuid' => $limaServer['uuid'],
'name' => $limaServer['name'],
'description' => 'This is a Lima VM for local development testing',
'ip' => 'host.docker.internal',
'port' => $limaServer['port'],
'team_id' => 0,
'private_key_id' => 1,
'proxy' => [
'type' => ProxyTypes::TRAEFIK->value,
'status' => ProxyStatus::EXITED->value,
],
]);
$server->settings->forceFill([
'sentinel_custom_url' => self::LIMA_SENTINEL_URL,
])->saveQuietly();
}
}
}
+74
View File
@@ -0,0 +1,74 @@
<?php
namespace Database\Seeders;
use App\Actions\V5\Server\SyncDevLimaServers;
use App\Models\PrivateKey;
use App\Models\Team;
use App\Models\User;
use Illuminate\Database\Seeder;
class V5DevLimaSeeder extends Seeder
{
private const CLUSTER_NAME = 'Development-Lima';
/**
* Run the database seeds.
*/
public function run(): void
{
$team = Team::query()->find(0) ?? Team::query()->orderBy('id')->first();
$user = User::query()->find(0) ?? User::query()->orderBy('id')->first();
if (! $team instanceof Team || ! $user instanceof User) {
return;
}
$privateKey = PrivateKey::query()
->where('team_id', $team->id)
->where('is_git_related', false)
->orderBy('id')
->first();
$sshUser = (string) config('coold.dev_ssh_user', 'coolify');
$servers = collect($this->servers())
->map(fn (array $server): array => [
...$server,
'ssh_user' => $sshUser,
])
->all();
SyncDevLimaServers::run(
team: $team,
user: $user,
privateKey: $privateKey,
clusterName: self::CLUSTER_NAME,
servers: $servers,
);
}
/**
* @return array<int, array{name: string, host: string, ssh_port: int, wireguard_management_ip: string, wireguard_listen_port_override: int, wireguard_endpoint_override: string}>
*/
private function servers(): array
{
return [
[
'name' => 'coold-dev',
'host' => 'coold-dev.local',
'ssh_port' => 22,
'wireguard_management_ip' => '100.64.0.1',
'wireguard_listen_port_override' => 51821,
'wireguard_endpoint_override' => 'coold-dev.local:51821',
],
[
'name' => 'coold-dev-2',
'host' => 'coold-dev-2.local',
'ssh_port' => 22,
'wireguard_management_ip' => '100.64.0.2',
'wireguard_listen_port_override' => 51822,
'wireguard_endpoint_override' => 'coold-dev-2.local:51822',
],
];
}
}