Skip to content

Commit 47025c7

Browse files
authored
feat: Shared server environment variables (#7764)
2 parents f01953d + acb716c commit 47025c7

File tree

28 files changed

+906
-77
lines changed

28 files changed

+906
-77
lines changed

app/Jobs/ApplicationDeploymentJob.php

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,7 +1282,7 @@ private function generate_runtime_environment_variables()
12821282
});
12831283

12841284
foreach ($runtime_environment_variables as $env) {
1285-
$envs->push($env->key.'='.$env->real_value);
1285+
$envs->push($env->key.'='.$env->getResolvedValueWithServer($this->mainServer));
12861286
}
12871287

12881288
// Check for PORT environment variable mismatch with ports_exposes
@@ -1348,7 +1348,7 @@ private function generate_runtime_environment_variables()
13481348
});
13491349

13501350
foreach ($runtime_environment_variables_preview as $env) {
1351-
$envs->push($env->key.'='.$env->real_value);
1351+
$envs->push($env->key.'='.$env->getResolvedValueWithServer($this->mainServer));
13521352
}
13531353

13541354
// Fall back to production env vars for keys not overridden by preview vars,
@@ -1362,7 +1362,7 @@ private function generate_runtime_environment_variables()
13621362
return $env->is_runtime && ! in_array($env->key, $previewKeys);
13631363
});
13641364
foreach ($fallback_production_vars as $env) {
1365-
$envs->push($env->key.'='.$env->real_value);
1365+
$envs->push($env->key.'='.$env->getResolvedValueWithServer($this->mainServer));
13661366
}
13671367
}
13681368

@@ -1604,10 +1604,11 @@ private function generate_buildtime_environment_variables()
16041604
}
16051605

16061606
foreach ($sorted_environment_variables as $env) {
1607+
$resolvedValue = $env->getResolvedValueWithServer($this->mainServer);
16071608
// For literal/multiline vars, real_value includes quotes that we need to remove
16081609
if ($env->is_literal || $env->is_multiline) {
16091610
// Strip outer quotes from real_value and apply proper bash escaping
1610-
$value = trim($env->real_value, "'");
1611+
$value = trim($resolvedValue, "'");
16111612
$escapedValue = escapeBashEnvValue($value);
16121613

16131614
if (isDev() && isset($envs_dict[$env->key])) {
@@ -1619,13 +1620,13 @@ private function generate_buildtime_environment_variables()
16191620
if (isDev()) {
16201621
$this->application_deployment_queue->addLogEntry("[DEBUG] Build-time env: {$env->key}");
16211622
$this->application_deployment_queue->addLogEntry('[DEBUG] Type: literal/multiline');
1622-
$this->application_deployment_queue->addLogEntry("[DEBUG] raw real_value: {$env->real_value}");
1623+
$this->application_deployment_queue->addLogEntry("[DEBUG] raw real_value: {$resolvedValue}");
16231624
$this->application_deployment_queue->addLogEntry("[DEBUG] stripped value: {$value}");
16241625
$this->application_deployment_queue->addLogEntry("[DEBUG] final escaped: {$escapedValue}");
16251626
}
16261627
} else {
16271628
// For normal vars, use double quotes to allow $VAR expansion
1628-
$escapedValue = escapeBashDoubleQuoted($env->real_value);
1629+
$escapedValue = escapeBashDoubleQuoted($resolvedValue);
16291630

16301631
if (isDev() && isset($envs_dict[$env->key])) {
16311632
$this->application_deployment_queue->addLogEntry("[DEBUG] User override: {$env->key} (was: {$envs_dict[$env->key]}, now: {$escapedValue})");
@@ -1636,7 +1637,7 @@ private function generate_buildtime_environment_variables()
16361637
if (isDev()) {
16371638
$this->application_deployment_queue->addLogEntry("[DEBUG] Build-time env: {$env->key}");
16381639
$this->application_deployment_queue->addLogEntry('[DEBUG] Type: normal (allows expansion)');
1639-
$this->application_deployment_queue->addLogEntry("[DEBUG] real_value: {$env->real_value}");
1640+
$this->application_deployment_queue->addLogEntry("[DEBUG] real_value: {$resolvedValue}");
16401641
$this->application_deployment_queue->addLogEntry("[DEBUG] final escaped: {$escapedValue}");
16411642
}
16421643
}
@@ -1655,10 +1656,11 @@ private function generate_buildtime_environment_variables()
16551656
}
16561657

16571658
foreach ($sorted_environment_variables as $env) {
1659+
$resolvedValue = $env->getResolvedValueWithServer($this->mainServer);
16581660
// For literal/multiline vars, real_value includes quotes that we need to remove
16591661
if ($env->is_literal || $env->is_multiline) {
16601662
// Strip outer quotes from real_value and apply proper bash escaping
1661-
$value = trim($env->real_value, "'");
1663+
$value = trim($resolvedValue, "'");
16621664
$escapedValue = escapeBashEnvValue($value);
16631665

16641666
if (isDev() && isset($envs_dict[$env->key])) {
@@ -1670,13 +1672,13 @@ private function generate_buildtime_environment_variables()
16701672
if (isDev()) {
16711673
$this->application_deployment_queue->addLogEntry("[DEBUG] Build-time env: {$env->key}");
16721674
$this->application_deployment_queue->addLogEntry('[DEBUG] Type: literal/multiline');
1673-
$this->application_deployment_queue->addLogEntry("[DEBUG] raw real_value: {$env->real_value}");
1675+
$this->application_deployment_queue->addLogEntry("[DEBUG] raw real_value: {$resolvedValue}");
16741676
$this->application_deployment_queue->addLogEntry("[DEBUG] stripped value: {$value}");
16751677
$this->application_deployment_queue->addLogEntry("[DEBUG] final escaped: {$escapedValue}");
16761678
}
16771679
} else {
16781680
// For normal vars, use double quotes to allow $VAR expansion
1679-
$escapedValue = escapeBashDoubleQuoted($env->real_value);
1681+
$escapedValue = escapeBashDoubleQuoted($resolvedValue);
16801682

16811683
if (isDev() && isset($envs_dict[$env->key])) {
16821684
$this->application_deployment_queue->addLogEntry("[DEBUG] User override: {$env->key} (was: {$envs_dict[$env->key]}, now: {$escapedValue})");
@@ -1687,7 +1689,7 @@ private function generate_buildtime_environment_variables()
16871689
if (isDev()) {
16881690
$this->application_deployment_queue->addLogEntry("[DEBUG] Build-time env: {$env->key}");
16891691
$this->application_deployment_queue->addLogEntry('[DEBUG] Type: normal (allows expansion)');
1690-
$this->application_deployment_queue->addLogEntry("[DEBUG] real_value: {$env->real_value}");
1692+
$this->application_deployment_queue->addLogEntry("[DEBUG] real_value: {$resolvedValue}");
16911693
$this->application_deployment_queue->addLogEntry("[DEBUG] final escaped: {$escapedValue}");
16921694
}
16931695
}
@@ -2392,15 +2394,17 @@ private function generate_nixpacks_env_variables()
23922394
$this->env_nixpacks_args = collect([]);
23932395
if ($this->pull_request_id === 0) {
23942396
foreach ($this->application->nixpacks_environment_variables as $env) {
2395-
if (! is_null($env->real_value) && $env->real_value !== '') {
2396-
$value = ($env->is_literal || $env->is_multiline) ? trim($env->real_value, "'") : $env->real_value;
2397+
$resolvedValue = $env->getResolvedValueWithServer($this->mainServer);
2398+
if (! is_null($resolvedValue) && $resolvedValue !== '') {
2399+
$value = ($env->is_literal || $env->is_multiline) ? trim($resolvedValue, "'") : $resolvedValue;
23972400
$this->env_nixpacks_args->push('--env '.escapeShellValue("{$env->key}={$value}"));
23982401
}
23992402
}
24002403
} else {
24012404
foreach ($this->application->nixpacks_environment_variables_preview as $env) {
2402-
if (! is_null($env->real_value) && $env->real_value !== '') {
2403-
$value = ($env->is_literal || $env->is_multiline) ? trim($env->real_value, "'") : $env->real_value;
2405+
$resolvedValue = $env->getResolvedValueWithServer($this->mainServer);
2406+
if (! is_null($resolvedValue) && $resolvedValue !== '') {
2407+
$value = ($env->is_literal || $env->is_multiline) ? trim($resolvedValue, "'") : $resolvedValue;
24042408
$this->env_nixpacks_args->push('--env '.escapeShellValue("{$env->key}={$value}"));
24052409
}
24062410
}
@@ -2539,8 +2543,9 @@ private function generate_env_variables()
25392543
->get();
25402544

25412545
foreach ($envs as $env) {
2542-
if (! is_null($env->real_value)) {
2543-
$this->env_args->put($env->key, $env->real_value);
2546+
$resolvedValue = $env->getResolvedValueWithServer($this->mainServer);
2547+
if (! is_null($resolvedValue)) {
2548+
$this->env_args->put($env->key, $resolvedValue);
25442549
}
25452550
}
25462551
} else {
@@ -2550,8 +2555,9 @@ private function generate_env_variables()
25502555
->get();
25512556

25522557
foreach ($envs as $env) {
2553-
if (! is_null($env->real_value)) {
2554-
$this->env_args->put($env->key, $env->real_value);
2558+
$resolvedValue = $env->getResolvedValueWithServer($this->mainServer);
2559+
if (! is_null($resolvedValue)) {
2560+
$this->env_args->put($env->key, $resolvedValue);
25552561
}
25562562
}
25572563
}
@@ -3566,7 +3572,7 @@ private function generate_secrets_hash($variables)
35663572
} else {
35673573
$secrets_string = $variables
35683574
->map(function ($env) {
3569-
return "{$env->key}={$env->real_value}";
3575+
return "{$env->key}={$env->getResolvedValueWithServer($this->mainServer)}";
35703576
})
35713577
->sort()
35723578
->implode('|');
@@ -3632,7 +3638,7 @@ private function add_build_env_variables_to_dockerfile()
36323638
if (data_get($env, 'is_multiline') === true) {
36333639
$argsToInsert->push("ARG {$env->key}");
36343640
} else {
3635-
$argsToInsert->push("ARG {$env->key}={$env->real_value}");
3641+
$argsToInsert->push("ARG {$env->key}={$env->getResolvedValueWithServer($this->mainServer)}");
36363642
}
36373643
}
36383644
// Add Coolify variables as ARGs
@@ -3654,7 +3660,7 @@ private function add_build_env_variables_to_dockerfile()
36543660
if (data_get($env, 'is_multiline') === true) {
36553661
$argsToInsert->push("ARG {$env->key}");
36563662
} else {
3657-
$argsToInsert->push("ARG {$env->key}={$env->real_value}");
3663+
$argsToInsert->push("ARG {$env->key}={$env->getResolvedValueWithServer($this->mainServer)}");
36583664
}
36593665
}
36603666
// Add Coolify variables as ARGs
@@ -3690,7 +3696,7 @@ private function add_build_env_variables_to_dockerfile()
36903696
}
36913697
}
36923698
$envs_mapped = $envs->mapWithKeys(function ($env) {
3693-
return [$env->key => $env->real_value];
3699+
return [$env->key => $env->getResolvedValueWithServer($this->mainServer)];
36943700
});
36953701
$secrets_hash = $this->generate_secrets_hash($envs_mapped);
36963702
$argsToInsert->push("ARG COOLIFY_BUILD_SECRETS_HASH={$secrets_hash}");

app/Livewire/Project/Shared/EnvironmentVariable/Add.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public function availableSharedVariables(): array
7171
'team' => [],
7272
'project' => [],
7373
'environment' => [],
74+
'server' => [],
7475
];
7576

7677
// Early return if no team
@@ -126,6 +127,66 @@ public function availableSharedVariables(): array
126127
}
127128
}
128129

130+
// Get server variables
131+
$serverUuid = data_get($this->parameters, 'server_uuid');
132+
if ($serverUuid) {
133+
// If we have a specific server_uuid, show variables for that server
134+
$server = \App\Models\Server::where('team_id', $team->id)
135+
->where('uuid', $serverUuid)
136+
->first();
137+
138+
if ($server) {
139+
try {
140+
$this->authorize('view', $server);
141+
$result['server'] = $server->environment_variables()
142+
->pluck('key')
143+
->toArray();
144+
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
145+
// User not authorized to view server variables
146+
}
147+
}
148+
} else {
149+
// For application environment variables, try to use the application's destination server
150+
$applicationUuid = data_get($this->parameters, 'application_uuid');
151+
if ($applicationUuid) {
152+
$application = \App\Models\Application::whereRelation('environment.project.team', 'id', $team->id)
153+
->where('uuid', $applicationUuid)
154+
->with('destination.server')
155+
->first();
156+
157+
if ($application && $application->destination && $application->destination->server) {
158+
try {
159+
$this->authorize('view', $application->destination->server);
160+
$result['server'] = $application->destination->server->environment_variables()
161+
->pluck('key')
162+
->toArray();
163+
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
164+
// User not authorized to view server variables
165+
}
166+
}
167+
} else {
168+
// For service environment variables, try to use the service's server
169+
$serviceUuid = data_get($this->parameters, 'service_uuid');
170+
if ($serviceUuid) {
171+
$service = \App\Models\Service::whereRelation('environment.project.team', 'id', $team->id)
172+
->where('uuid', $serviceUuid)
173+
->with('server')
174+
->first();
175+
176+
if ($service && $service->server) {
177+
try {
178+
$this->authorize('view', $service->server);
179+
$result['server'] = $service->server->environment_variables()
180+
->pluck('key')
181+
->toArray();
182+
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
183+
// User not authorized to view server variables
184+
}
185+
}
186+
}
187+
}
188+
}
189+
129190
return $result;
130191
}
131192

app/Livewire/Project/Shared/EnvironmentVariable/Show.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ public function availableSharedVariables(): array
219219
'team' => [],
220220
'project' => [],
221221
'environment' => [],
222+
'server' => [],
222223
];
223224

224225
// Early return if no team
@@ -274,6 +275,66 @@ public function availableSharedVariables(): array
274275
}
275276
}
276277

278+
// Get server variables
279+
$serverUuid = data_get($this->parameters, 'server_uuid');
280+
if ($serverUuid) {
281+
// If we have a specific server_uuid, show variables for that server
282+
$server = \App\Models\Server::where('team_id', $team->id)
283+
->where('uuid', $serverUuid)
284+
->first();
285+
286+
if ($server) {
287+
try {
288+
$this->authorize('view', $server);
289+
$result['server'] = $server->environment_variables()
290+
->pluck('key')
291+
->toArray();
292+
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
293+
// User not authorized to view server variables
294+
}
295+
}
296+
} else {
297+
// For application environment variables, try to use the application's destination server
298+
$applicationUuid = data_get($this->parameters, 'application_uuid');
299+
if ($applicationUuid) {
300+
$application = \App\Models\Application::whereRelation('environment.project.team', 'id', $team->id)
301+
->where('uuid', $applicationUuid)
302+
->with('destination.server')
303+
->first();
304+
305+
if ($application && $application->destination && $application->destination->server) {
306+
try {
307+
$this->authorize('view', $application->destination->server);
308+
$result['server'] = $application->destination->server->environment_variables()
309+
->pluck('key')
310+
->toArray();
311+
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
312+
// User not authorized to view server variables
313+
}
314+
}
315+
} else {
316+
// For service environment variables, try to use the service's server
317+
$serviceUuid = data_get($this->parameters, 'service_uuid');
318+
if ($serviceUuid) {
319+
$service = \App\Models\Service::whereRelation('environment.project.team', 'id', $team->id)
320+
->where('uuid', $serviceUuid)
321+
->with('server')
322+
->first();
323+
324+
if ($service && $service->server) {
325+
try {
326+
$this->authorize('view', $service->server);
327+
$result['server'] = $service->server->environment_variables()
328+
->pluck('key')
329+
->toArray();
330+
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
331+
// User not authorized to view server variables
332+
}
333+
}
334+
}
335+
}
336+
}
337+
277338
return $result;
278339
}
279340

app/Livewire/SharedVariables/Environment/Show.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,14 @@ public function saveKey($data)
5151
}
5252
}
5353

54-
public function mount()
54+
public function mount(?string $project_uuid = null, ?string $environment_uuid = null)
5555
{
5656
$this->parameters = get_route_parameters();
57-
$this->project = Project::ownedByCurrentTeam()->where('uuid', request()->route('project_uuid'))->firstOrFail();
58-
$this->environment = $this->project->environments()->where('uuid', request()->route('environment_uuid'))->firstOrFail();
57+
$projectUuid = $project_uuid ?? request()->route('project_uuid');
58+
$environmentUuid = $environment_uuid ?? request()->route('environment_uuid');
59+
60+
$this->project = Project::ownedByCurrentTeam()->where('uuid', $projectUuid)->firstOrFail();
61+
$this->environment = $this->project->environments()->where('uuid', $environmentUuid)->firstOrFail();
5962
$this->getDevView();
6063
}
6164

app/Livewire/SharedVariables/Project/Show.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ public function saveKey($data)
4444
}
4545
}
4646

47-
public function mount()
47+
public function mount(?string $project_uuid = null)
4848
{
49-
$projectUuid = request()->route('project_uuid');
49+
$projectUuid = $project_uuid ?? request()->route('project_uuid');
5050
$teamId = currentTeam()->id;
5151
$project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first();
5252
if (! $project) {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace App\Livewire\SharedVariables\Server;
4+
5+
use App\Models\Server;
6+
use Illuminate\Support\Collection;
7+
use Livewire\Component;
8+
9+
class Index extends Component
10+
{
11+
public Collection $servers;
12+
13+
public function mount()
14+
{
15+
$this->servers = Server::ownedByCurrentTeamCached();
16+
}
17+
18+
public function render()
19+
{
20+
return view('livewire.shared-variables.server.index');
21+
}
22+
}

0 commit comments

Comments
 (0)