Skip to content

Commit da17494

Browse files
authored
v4.0.0-beta.449 (#7340)
2 parents 6f0110c + 68c5ebf commit da17494

File tree

13 files changed

+543
-54
lines changed

13 files changed

+543
-54
lines changed

app/Jobs/ApplicationDeploymentJob.php

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,7 +1363,7 @@ private function save_runtime_environment_variables()
13631363
$envs_base64 = base64_encode($environment_variables->implode("\n"));
13641364

13651365
// Write .env file to workdir (for container runtime)
1366-
$this->application_deployment_queue->addLogEntry('Creating .env file with runtime variables for build phase.', hidden: true);
1366+
$this->application_deployment_queue->addLogEntry('Creating .env file with runtime variables for container.', hidden: true);
13671367
$this->execute_remote_command(
13681368
[
13691369
executeInDocker($this->deployment_uuid, "echo '$envs_base64' | base64 -d | tee $this->workdir/.env > /dev/null"),
@@ -1402,7 +1402,7 @@ private function generate_buildtime_environment_variables()
14021402
}
14031403

14041404
$envs = collect([]);
1405-
$coolify_envs = $this->generate_coolify_env_variables();
1405+
$coolify_envs = $this->generate_coolify_env_variables(forBuildTime: true);
14061406

14071407
// Add COOLIFY variables
14081408
$coolify_envs->each(function ($item, $key) use ($envs) {
@@ -1979,7 +1979,6 @@ private function set_coolify_variables()
19791979
$this->coolify_variables .= "COOLIFY_BRANCH={$this->application->git_branch} ";
19801980
}
19811981
$this->coolify_variables .= "COOLIFY_RESOURCE_UUID={$this->application->uuid} ";
1982-
$this->coolify_variables .= "COOLIFY_CONTAINER_NAME={$this->container_name} ";
19831982
}
19841983

19851984
private function check_git_if_build_needed()
@@ -2230,15 +2229,15 @@ private function generate_nixpacks_env_variables()
22302229
}
22312230

22322231
// Add COOLIFY_* environment variables to Nixpacks build context
2233-
$coolify_envs = $this->generate_coolify_env_variables();
2232+
$coolify_envs = $this->generate_coolify_env_variables(forBuildTime: true);
22342233
$coolify_envs->each(function ($value, $key) {
22352234
$this->env_nixpacks_args->push("--env {$key}={$value}");
22362235
});
22372236

22382237
$this->env_nixpacks_args = $this->env_nixpacks_args->implode(' ');
22392238
}
22402239

2241-
private function generate_coolify_env_variables(): Collection
2240+
private function generate_coolify_env_variables(bool $forBuildTime = false): Collection
22422241
{
22432242
$coolify_envs = collect([]);
22442243
$local_branch = $this->branch;
@@ -2273,8 +2272,11 @@ private function generate_coolify_env_variables(): Collection
22732272
if ($this->application->environment_variables_preview->where('key', 'COOLIFY_RESOURCE_UUID')->isEmpty()) {
22742273
$coolify_envs->put('COOLIFY_RESOURCE_UUID', $this->application->uuid);
22752274
}
2276-
if ($this->application->environment_variables_preview->where('key', 'COOLIFY_CONTAINER_NAME')->isEmpty()) {
2277-
$coolify_envs->put('COOLIFY_CONTAINER_NAME', $this->container_name);
2275+
// Only add COOLIFY_CONTAINER_NAME for runtime (not build-time) - it changes every deployment and breaks Docker cache
2276+
if (! $forBuildTime) {
2277+
if ($this->application->environment_variables_preview->where('key', 'COOLIFY_CONTAINER_NAME')->isEmpty()) {
2278+
$coolify_envs->put('COOLIFY_CONTAINER_NAME', $this->container_name);
2279+
}
22782280
}
22792281
}
22802282

@@ -2311,8 +2313,11 @@ private function generate_coolify_env_variables(): Collection
23112313
if ($this->application->environment_variables->where('key', 'COOLIFY_RESOURCE_UUID')->isEmpty()) {
23122314
$coolify_envs->put('COOLIFY_RESOURCE_UUID', $this->application->uuid);
23132315
}
2314-
if ($this->application->environment_variables->where('key', 'COOLIFY_CONTAINER_NAME')->isEmpty()) {
2315-
$coolify_envs->put('COOLIFY_CONTAINER_NAME', $this->container_name);
2316+
// Only add COOLIFY_CONTAINER_NAME for runtime (not build-time) - it changes every deployment and breaks Docker cache
2317+
if (! $forBuildTime) {
2318+
if ($this->application->environment_variables->where('key', 'COOLIFY_CONTAINER_NAME')->isEmpty()) {
2319+
$coolify_envs->put('COOLIFY_CONTAINER_NAME', $this->container_name);
2320+
}
23162321
}
23172322
}
23182323

@@ -2328,7 +2333,7 @@ private function generate_env_variables()
23282333
$this->env_args = collect([]);
23292334
$this->env_args->put('SOURCE_COMMIT', $this->commit);
23302335

2331-
$coolify_envs = $this->generate_coolify_env_variables();
2336+
$coolify_envs = $this->generate_coolify_env_variables(forBuildTime: true);
23322337
$coolify_envs->each(function ($value, $key) {
23332338
$this->env_args->put($key, $value);
23342339
});
@@ -2748,7 +2753,7 @@ private function build_image()
27482753
} else {
27492754
// Traditional build args approach - generate COOLIFY_ variables locally
27502755
// Generate COOLIFY_ variables locally for build args
2751-
$coolify_envs = $this->generate_coolify_env_variables();
2756+
$coolify_envs = $this->generate_coolify_env_variables(forBuildTime: true);
27522757
$coolify_envs->each(function ($value, $key) {
27532758
$this->build_args->push("--build-arg '{$key}'");
27542759
});
@@ -3294,7 +3299,9 @@ private function generate_build_secrets(Collection $variables)
32943299
private function generate_secrets_hash($variables)
32953300
{
32963301
if (! $this->secrets_hash_key) {
3297-
$this->secrets_hash_key = bin2hex(random_bytes(32));
3302+
// Use APP_KEY as deterministic hash key to preserve Docker build cache
3303+
// Random keys would change every deployment, breaking cache even when secrets haven't changed
3304+
$this->secrets_hash_key = config('app.key');
32983305
}
32993306

33003307
if ($variables instanceof Collection) {

app/Livewire/SharedVariables/Environment/Show.php

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use App\Models\Application;
66
use App\Models\Project;
77
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
8+
use Illuminate\Support\Facades\DB;
89
use Livewire\Component;
910

1011
class Show extends Component
@@ -19,7 +20,11 @@ class Show extends Component
1920

2021
public array $parameters;
2122

22-
protected $listeners = ['refreshEnvs' => '$refresh', 'saveKey', 'environmentVariableDeleted' => '$refresh'];
23+
public string $view = 'normal';
24+
25+
public ?string $variables = null;
26+
27+
protected $listeners = ['refreshEnvs' => 'refreshEnvs', 'saveKey', 'environmentVariableDeleted' => 'refreshEnvs'];
2328

2429
public function saveKey($data)
2530
{
@@ -39,6 +44,7 @@ public function saveKey($data)
3944
'team_id' => currentTeam()->id,
4045
]);
4146
$this->environment->refresh();
47+
$this->getDevView();
4248
} catch (\Throwable $e) {
4349
return handleError($e, $this);
4450
}
@@ -49,6 +55,120 @@ public function mount()
4955
$this->parameters = get_route_parameters();
5056
$this->project = Project::ownedByCurrentTeam()->where('uuid', request()->route('project_uuid'))->firstOrFail();
5157
$this->environment = $this->project->environments()->where('uuid', request()->route('environment_uuid'))->firstOrFail();
58+
$this->getDevView();
59+
}
60+
61+
public function switch()
62+
{
63+
$this->authorize('view', $this->environment);
64+
$this->view = $this->view === 'normal' ? 'dev' : 'normal';
65+
$this->getDevView();
66+
}
67+
68+
public function getDevView()
69+
{
70+
$this->variables = $this->formatEnvironmentVariables($this->environment->environment_variables->sortBy('key'));
71+
}
72+
73+
private function formatEnvironmentVariables($variables)
74+
{
75+
return $variables->map(function ($item) {
76+
if ($item->is_shown_once) {
77+
return "$item->key=(Locked Secret, delete and add again to change)";
78+
}
79+
if ($item->is_multiline) {
80+
return "$item->key=(Multiline environment variable, edit in normal view)";
81+
}
82+
83+
return "$item->key=$item->value";
84+
})->join("\n");
85+
}
86+
87+
public function submit()
88+
{
89+
try {
90+
$this->authorize('update', $this->environment);
91+
$this->handleBulkSubmit();
92+
$this->getDevView();
93+
} catch (\Throwable $e) {
94+
return handleError($e, $this);
95+
} finally {
96+
$this->refreshEnvs();
97+
}
98+
}
99+
100+
private function handleBulkSubmit()
101+
{
102+
$variables = parseEnvFormatToArray($this->variables);
103+
$changesMade = false;
104+
105+
DB::transaction(function () use ($variables, &$changesMade) {
106+
// Delete removed variables
107+
$deletedCount = $this->deleteRemovedVariables($variables);
108+
if ($deletedCount > 0) {
109+
$changesMade = true;
110+
}
111+
112+
// Update or create variables
113+
$updatedCount = $this->updateOrCreateVariables($variables);
114+
if ($updatedCount > 0) {
115+
$changesMade = true;
116+
}
117+
});
118+
119+
// Only dispatch success after transaction has committed
120+
if ($changesMade) {
121+
$this->dispatch('success', 'Environment variables updated.');
122+
}
123+
}
124+
125+
private function deleteRemovedVariables($variables)
126+
{
127+
$variablesToDelete = $this->environment->environment_variables()->whereNotIn('key', array_keys($variables))->get();
128+
129+
if ($variablesToDelete->isEmpty()) {
130+
return 0;
131+
}
132+
133+
$this->environment->environment_variables()->whereNotIn('key', array_keys($variables))->delete();
134+
135+
return $variablesToDelete->count();
136+
}
137+
138+
private function updateOrCreateVariables($variables)
139+
{
140+
$count = 0;
141+
foreach ($variables as $key => $value) {
142+
$found = $this->environment->environment_variables()->where('key', $key)->first();
143+
144+
if ($found) {
145+
if (! $found->is_shown_once && ! $found->is_multiline) {
146+
if ($found->value !== $value) {
147+
$found->value = $value;
148+
$found->save();
149+
$count++;
150+
}
151+
}
152+
} else {
153+
$this->environment->environment_variables()->create([
154+
'key' => $key,
155+
'value' => $value,
156+
'is_multiline' => false,
157+
'is_literal' => false,
158+
'type' => 'environment',
159+
'team_id' => currentTeam()->id,
160+
]);
161+
$count++;
162+
}
163+
}
164+
165+
return $count;
166+
}
167+
168+
public function refreshEnvs()
169+
{
170+
$this->environment->refresh();
171+
$this->getDevView();
52172
}
53173

54174
public function render()

app/Livewire/SharedVariables/Project/Show.php

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use App\Models\Project;
66
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
7+
use Illuminate\Support\Facades\DB;
78
use Livewire\Component;
89

910
class Show extends Component
@@ -12,7 +13,11 @@ class Show extends Component
1213

1314
public Project $project;
1415

15-
protected $listeners = ['refreshEnvs' => '$refresh', 'saveKey' => 'saveKey', 'environmentVariableDeleted' => '$refresh'];
16+
public string $view = 'normal';
17+
18+
public ?string $variables = null;
19+
20+
protected $listeners = ['refreshEnvs' => 'refreshEnvs', 'saveKey' => 'saveKey', 'environmentVariableDeleted' => 'refreshEnvs'];
1621

1722
public function saveKey($data)
1823
{
@@ -32,6 +37,7 @@ public function saveKey($data)
3237
'team_id' => currentTeam()->id,
3338
]);
3439
$this->project->refresh();
40+
$this->getDevView();
3541
} catch (\Throwable $e) {
3642
return handleError($e, $this);
3743
}
@@ -46,6 +52,114 @@ public function mount()
4652
return redirect()->route('dashboard');
4753
}
4854
$this->project = $project;
55+
$this->getDevView();
56+
}
57+
58+
public function switch()
59+
{
60+
$this->authorize('view', $this->project);
61+
$this->view = $this->view === 'normal' ? 'dev' : 'normal';
62+
$this->getDevView();
63+
}
64+
65+
public function getDevView()
66+
{
67+
$this->variables = $this->formatEnvironmentVariables($this->project->environment_variables->sortBy('key'));
68+
}
69+
70+
private function formatEnvironmentVariables($variables)
71+
{
72+
return $variables->map(function ($item) {
73+
if ($item->is_shown_once) {
74+
return "$item->key=(Locked Secret, delete and add again to change)";
75+
}
76+
if ($item->is_multiline) {
77+
return "$item->key=(Multiline environment variable, edit in normal view)";
78+
}
79+
80+
return "$item->key=$item->value";
81+
})->join("\n");
82+
}
83+
84+
public function submit()
85+
{
86+
try {
87+
$this->authorize('update', $this->project);
88+
$this->handleBulkSubmit();
89+
$this->getDevView();
90+
} catch (\Throwable $e) {
91+
return handleError($e, $this);
92+
} finally {
93+
$this->refreshEnvs();
94+
}
95+
}
96+
97+
private function handleBulkSubmit()
98+
{
99+
$variables = parseEnvFormatToArray($this->variables);
100+
101+
$changesMade = DB::transaction(function () use ($variables) {
102+
// Delete removed variables
103+
$deletedCount = $this->deleteRemovedVariables($variables);
104+
105+
// Update or create variables
106+
$updatedCount = $this->updateOrCreateVariables($variables);
107+
108+
return $deletedCount > 0 || $updatedCount > 0;
109+
});
110+
111+
if ($changesMade) {
112+
$this->dispatch('success', 'Environment variables updated.');
113+
}
114+
}
115+
116+
private function deleteRemovedVariables($variables)
117+
{
118+
$variablesToDelete = $this->project->environment_variables()->whereNotIn('key', array_keys($variables))->get();
119+
120+
if ($variablesToDelete->isEmpty()) {
121+
return 0;
122+
}
123+
124+
$this->project->environment_variables()->whereNotIn('key', array_keys($variables))->delete();
125+
126+
return $variablesToDelete->count();
127+
}
128+
129+
private function updateOrCreateVariables($variables)
130+
{
131+
$count = 0;
132+
foreach ($variables as $key => $value) {
133+
$found = $this->project->environment_variables()->where('key', $key)->first();
134+
135+
if ($found) {
136+
if (! $found->is_shown_once && ! $found->is_multiline) {
137+
if ($found->value !== $value) {
138+
$found->value = $value;
139+
$found->save();
140+
$count++;
141+
}
142+
}
143+
} else {
144+
$this->project->environment_variables()->create([
145+
'key' => $key,
146+
'value' => $value,
147+
'is_multiline' => false,
148+
'is_literal' => false,
149+
'type' => 'project',
150+
'team_id' => currentTeam()->id,
151+
]);
152+
$count++;
153+
}
154+
}
155+
156+
return $count;
157+
}
158+
159+
public function refreshEnvs()
160+
{
161+
$this->project->refresh();
162+
$this->getDevView();
49163
}
50164

51165
public function render()

0 commit comments

Comments
 (0)