Skip to content

Commit 466eb85

Browse files
committed
refactor(models): extract defaultStandaloneDockerAttributes method on Server
Extract duplicated inline StandaloneDocker attribute arrays in the Server boot lifecycle into a dedicated method, eliminating repetition between the root-server (id=0) and normal-server paths. Also harden the shared_environment_variables migration by wrapping DDL statements in DB::transaction() and using DROP CONSTRAINT IF EXISTS to make the migration safely re-runnable. Add unit test covering the extracted method to verify uuid is always present in bootstrap attributes.
1 parent 4f6e1f7 commit 466eb85

File tree

3 files changed

+61
-24
lines changed

3 files changed

+61
-24
lines changed

app/Models/Server.php

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,7 @@ protected static function booted()
155155
'server_id' => $server->id,
156156
])->save();
157157
} else {
158-
(new StandaloneDocker)->forceFill([
159-
'id' => 0,
160-
'name' => 'coolify',
161-
'network' => 'coolify',
162-
'server_id' => $server->id,
163-
])->saveQuietly();
158+
(new StandaloneDocker)->forceFill($server->defaultStandaloneDockerAttributes(id: 0))->saveQuietly();
164159
}
165160
} else {
166161
if ($server->isSwarm()) {
@@ -171,12 +166,7 @@ protected static function booted()
171166
]);
172167
} else {
173168
$standaloneDocker = new StandaloneDocker;
174-
$standaloneDocker->forceFill([
175-
'name' => 'coolify',
176-
'uuid' => (string) new Cuid2,
177-
'network' => 'coolify',
178-
'server_id' => $server->id,
179-
]);
169+
$standaloneDocker->forceFill($server->defaultStandaloneDockerAttributes());
180170
$standaloneDocker->saveQuietly();
181171
}
182172
}
@@ -1043,6 +1033,25 @@ public function team()
10431033
return $this->belongsTo(Team::class);
10441034
}
10451035

1036+
/**
1037+
* @return array{id?: int, name: string, uuid: string, network: string, server_id: int}
1038+
*/
1039+
public function defaultStandaloneDockerAttributes(?int $id = null): array
1040+
{
1041+
$attributes = [
1042+
'name' => 'coolify',
1043+
'uuid' => (string) new Cuid2,
1044+
'network' => 'coolify',
1045+
'server_id' => $this->id,
1046+
];
1047+
1048+
if (! is_null($id)) {
1049+
$attributes['id'] = $id;
1050+
}
1051+
1052+
return $attributes;
1053+
}
1054+
10461055
public function environment_variables()
10471056
{
10481057
return $this->hasMany(SharedEnvironmentVariable::class)->where('type', 'server');

database/migrations/2025_12_24_095507_add_server_to_shared_environment_variables_table.php

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,23 @@
55
use Illuminate\Support\Facades\DB;
66
use Illuminate\Support\Facades\Schema;
77

8-
return new class extends Migration {
8+
return new class extends Migration
9+
{
910
/**
1011
* Run the migrations.
1112
*/
1213
public function up(): void
1314
{
14-
DB::statement("ALTER TABLE shared_environment_variables DROP CONSTRAINT shared_environment_variables_type_check");
15-
DB::statement("ALTER TABLE shared_environment_variables ADD CONSTRAINT shared_environment_variables_type_check CHECK (type IN ('team', 'project', 'environment', 'server'))");
16-
Schema::table('shared_environment_variables', function (Blueprint $table) {
17-
$table->foreignId('server_id')->nullable()->constrained()->onDelete('cascade');
18-
$table->unique(['key', 'server_id', 'team_id']);
15+
DB::transaction(function () {
16+
DB::statement('ALTER TABLE shared_environment_variables DROP CONSTRAINT IF EXISTS shared_environment_variables_type_check');
17+
DB::statement("ALTER TABLE shared_environment_variables ADD CONSTRAINT shared_environment_variables_type_check CHECK (type IN ('team', 'project', 'environment', 'server'))");
18+
Schema::table('shared_environment_variables', function (Blueprint $table) {
19+
$table->foreignId('server_id')->nullable()->constrained()->onDelete('cascade');
20+
// NULL != NULL in PostgreSQL unique indexes, so this only enforces uniqueness
21+
// for server-scoped rows (where server_id is non-null). Other scopes are covered
22+
// by existing unique constraints on ['key', 'project_id', 'team_id'] and ['key', 'environment_id', 'team_id'].
23+
$table->unique(['key', 'server_id', 'team_id']);
24+
});
1925
});
2026
}
2127

@@ -24,12 +30,14 @@ public function up(): void
2430
*/
2531
public function down(): void
2632
{
27-
Schema::table('shared_environment_variables', function (Blueprint $table) {
28-
$table->dropUnique(['key', 'server_id', 'team_id']);
29-
$table->dropForeign(['server_id']);
30-
$table->dropColumn('server_id');
33+
DB::transaction(function () {
34+
Schema::table('shared_environment_variables', function (Blueprint $table) {
35+
$table->dropUnique(['key', 'server_id', 'team_id']);
36+
$table->dropForeign(['server_id']);
37+
$table->dropColumn('server_id');
38+
});
39+
DB::statement('ALTER TABLE shared_environment_variables DROP CONSTRAINT IF EXISTS shared_environment_variables_type_check');
40+
DB::statement("ALTER TABLE shared_environment_variables ADD CONSTRAINT shared_environment_variables_type_check CHECK (type IN ('team', 'project', 'environment'))");
3141
});
32-
DB::statement("ALTER TABLE shared_environment_variables DROP CONSTRAINT shared_environment_variables_type_check");
33-
DB::statement("ALTER TABLE shared_environment_variables ADD CONSTRAINT shared_environment_variables_type_check CHECK (type IN ('team', 'project', 'environment'))");
3442
}
3543
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
use App\Models\Server;
4+
5+
it('includes a uuid in standalone docker bootstrap attributes for the root server path', function () {
6+
$server = new Server;
7+
$server->id = 0;
8+
9+
$attributes = $server->defaultStandaloneDockerAttributes(id: 0);
10+
11+
expect($attributes)
12+
->toMatchArray([
13+
'id' => 0,
14+
'name' => 'coolify',
15+
'network' => 'coolify',
16+
'server_id' => 0,
17+
])
18+
->and($attributes['uuid'])->toBeString()
19+
->and($attributes['uuid'])->not->toBe('');
20+
});

0 commit comments

Comments
 (0)