diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md
index c139793ec..02a21573c 100644
--- a/CONTRIBUTION.md
+++ b/CONTRIBUTION.md
@@ -30,5 +30,5 @@ Your horizon (Laravel scheduler): `localhost:8000/horizon` - Only reachable if y
Mails are caught by Mailpit: `localhost:8025`
## New Service Contribution
-Check out the docs [here](https://coolify.io/docs/resources/services/add-service).
+Check out the docs [here](https://coolify.io/docs/knowledge-base/add-a-service).
diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php
index 3d04be7d3..1717c5d08 100644
--- a/app/Jobs/ApplicationDeploymentJob.php
+++ b/app/Jobs/ApplicationDeploymentJob.php
@@ -710,7 +710,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
private function save_environment_variables()
{
$envs = collect([]);
- $ports = $this->application->settings->is_static ? [80] : $this->application->ports_exposes_array;
+ $ports = $this->application->main_port();
if ($this->pull_request_id !== 0) {
$this->env_filename = ".env-pr-$this->pull_request_id";
foreach ($this->application->environment_variables_preview as $env) {
@@ -727,14 +727,15 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
$envs->push($env->key . '=' . $real_value);
}
// Add PORT if not exists, use the first port as default
- if ($this->application->environment_variables_preview->filter(fn ($env) => Str::of($env)->startsWith('PORT'))->isEmpty()) {
+ if ($this->application->environment_variables_preview->where('key', 'PORT')->isEmpty()) {
$envs->push("PORT={$ports[0]}");
}
// Add HOST if not exists
- if ($this->application->environment_variables_preview->filter(fn ($env) => Str::of($env)->startsWith('HOST'))->isEmpty()) {
+ if ($this->application->environment_variables_preview->where('key', 'HOST')->isEmpty()) {
$envs->push("HOST=0.0.0.0");
}
- if ($this->application->environment_variables_preview->filter(fn ($env) => Str::of($env)->startsWith('SOURCE_COMMIT'))->isEmpty()) {
+ // Add SOURCE_COMMIT if not exists
+ if ($this->application->environment_variables_preview->where('key', 'SOURCE_COMMIT')->isEmpty()) {
if (!is_null($this->commit)) {
$envs->push("SOURCE_COMMIT={$this->commit}");
} else {
@@ -760,14 +761,15 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
$envs->push($env->key . '=' . $real_value);
}
// Add PORT if not exists, use the first port as default
- if ($this->application->environment_variables->filter(fn ($env) => Str::of($env)->startsWith('PORT'))->isEmpty()) {
+ if ($this->application->environment_variables->where('key', 'PORT')->isEmpty()) {
$envs->push("PORT={$ports[0]}");
}
// Add HOST if not exists
- if ($this->application->environment_variables->filter(fn ($env) => Str::of($env)->startsWith('HOST'))->isEmpty()) {
+ if ($this->application->environment_variables->where('key', 'HOST')->isEmpty()) {
$envs->push("HOST=0.0.0.0");
}
- if ($this->application->environment_variables->filter(fn ($env) => Str::of($env)->startsWith('SOURCE_COMMIT'))->isEmpty()) {
+ // Add SOURCE_COMMIT if not exists
+ if ($this->application->environment_variables->where('key', 'SOURCE_COMMIT')->isEmpty()) {
if (!is_null($this->commit)) {
$envs->push("SOURCE_COMMIT={$this->commit}");
} else {
@@ -1214,7 +1216,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
private function generate_compose_file()
{
$this->create_workdir();
- $ports = $this->application->settings->is_static ? [80] : $this->application->ports_exposes_array;
+ $ports = $this->application->main_port();
$onlyPort = null;
if (count($ports) > 0) {
$onlyPort = $ports[0];
diff --git a/app/Livewire/Project/Edit.php b/app/Livewire/Project/Edit.php
index d222917a6..8a35eff7f 100644
--- a/app/Livewire/Project/Edit.php
+++ b/app/Livewire/Project/Edit.php
@@ -12,28 +12,6 @@ class Edit extends Component
'project.name' => 'required|min:3|max:255',
'project.description' => 'nullable|string|max:255',
];
- protected $listeners = ['refreshEnvs' => '$refresh', 'saveKey' => 'saveKey'];
-
- public function saveKey($data)
- {
- try {
- $found = $this->project->environment_variables()->where('key', $data['key'])->first();
- if ($found) {
- throw new \Exception('Variable already exists.');
- }
- $this->project->environment_variables()->create([
- 'key' => $data['key'],
- 'value' => $data['value'],
- 'is_multiline' => $data['is_multiline'],
- 'is_literal' => $data['is_literal'],
- 'type' => 'project',
- 'team_id' => currentTeam()->id,
- ]);
- $this->project->refresh();
- } catch (\Throwable $e) {
- return handleError($e, $this);
- }
- }
public function mount()
{
$projectUuid = request()->route('project_uuid');
diff --git a/app/Livewire/Project/EnvironmentEdit.php b/app/Livewire/Project/EnvironmentEdit.php
index 173d946f3..cd952a961 100644
--- a/app/Livewire/Project/EnvironmentEdit.php
+++ b/app/Livewire/Project/EnvironmentEdit.php
@@ -16,29 +16,6 @@ class EnvironmentEdit extends Component
'environment.name' => 'required|min:3|max:255',
'environment.description' => 'nullable|min:3|max:255',
];
- protected $listeners = ['refreshEnvs' => '$refresh', 'saveKey' => 'saveKey'];
-
- public function saveKey($data)
- {
- try {
- $found = $this->environment->environment_variables()->where('key', $data['key'])->first();
- if ($found) {
- throw new \Exception('Variable already exists.');
- }
- $this->environment->environment_variables()->create([
- 'key' => $data['key'],
- 'value' => $data['value'],
- 'is_multiline' => $data['is_multiline'],
- 'is_literal' => $data['is_literal'],
- 'type' => 'environment',
- 'team_id' => currentTeam()->id,
- ]);
- $this->environment->refresh();
- } catch (\Throwable $e) {
- return handleError($e, $this);
- }
- }
-
public function mount()
{
$this->parameters = get_route_parameters();
diff --git a/app/Livewire/SharedVariables/Environment/Index.php b/app/Livewire/SharedVariables/Environment/Index.php
new file mode 100644
index 000000000..34f33ef5d
--- /dev/null
+++ b/app/Livewire/SharedVariables/Environment/Index.php
@@ -0,0 +1,19 @@
+projects = Project::ownedByCurrentTeam()->get();
+ }
+ public function render()
+ {
+ return view('livewire.shared-variables.environment.index');
+ }
+}
diff --git a/app/Livewire/SharedVariables/Environment/Show.php b/app/Livewire/SharedVariables/Environment/Show.php
new file mode 100644
index 000000000..29fd91153
--- /dev/null
+++ b/app/Livewire/SharedVariables/Environment/Show.php
@@ -0,0 +1,47 @@
+ '$refresh', 'saveKey' => 'saveKey'];
+
+ public function saveKey($data)
+ {
+ try {
+ $found = $this->environment->environment_variables()->where('key', $data['key'])->first();
+ if ($found) {
+ throw new \Exception('Variable already exists.');
+ }
+ $this->environment->environment_variables()->create([
+ 'key' => $data['key'],
+ 'value' => $data['value'],
+ 'is_multiline' => $data['is_multiline'],
+ 'is_literal' => $data['is_literal'],
+ 'type' => 'environment',
+ 'team_id' => currentTeam()->id,
+ ]);
+ $this->environment->refresh();
+ } catch (\Throwable $e) {
+ return handleError($e, $this);
+ }
+ }
+ public function mount()
+ {
+ $this->parameters = get_route_parameters();
+ $this->project = Project::ownedByCurrentTeam()->where('uuid', request()->route('project_uuid'))->first();
+ $this->environment = $this->project->environments()->where('name', request()->route('environment_name'))->first();
+ }
+ public function render()
+ {
+ return view('livewire.shared-variables.environment.show');
+ }
+}
diff --git a/app/Livewire/SharedVariables/Index.php b/app/Livewire/SharedVariables/Index.php
new file mode 100644
index 000000000..61c31e9f8
--- /dev/null
+++ b/app/Livewire/SharedVariables/Index.php
@@ -0,0 +1,13 @@
+projects = Project::ownedByCurrentTeam()->get();
+ }
+ public function render()
+ {
+ return view('livewire.shared-variables.project.index');
+ }
+}
diff --git a/app/Livewire/SharedVariables/Project/Show.php b/app/Livewire/SharedVariables/Project/Show.php
new file mode 100644
index 000000000..a172c52f0
--- /dev/null
+++ b/app/Livewire/SharedVariables/Project/Show.php
@@ -0,0 +1,47 @@
+ '$refresh', 'saveKey' => 'saveKey'];
+
+ public function saveKey($data)
+ {
+ try {
+ $found = $this->project->environment_variables()->where('key', $data['key'])->first();
+ if ($found) {
+ throw new \Exception('Variable already exists.');
+ }
+ $this->project->environment_variables()->create([
+ 'key' => $data['key'],
+ 'value' => $data['value'],
+ 'is_multiline' => $data['is_multiline'],
+ 'is_literal' => $data['is_literal'],
+ 'type' => 'project',
+ 'team_id' => currentTeam()->id,
+ ]);
+ $this->project->refresh();
+ } catch (\Throwable $e) {
+ return handleError($e, $this);
+ }
+ }
+ public function mount()
+ {
+ $projectUuid = request()->route('project_uuid');
+ $teamId = currentTeam()->id;
+ $project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first();
+ if (!$project) {
+ return redirect()->route('dashboard');
+ }
+ $this->project = $project;
+ }
+ public function render()
+ {
+ return view('livewire.shared-variables.project.show');
+ }
+}
diff --git a/app/Livewire/TeamSharedVariablesIndex.php b/app/Livewire/SharedVariables/Team/Index.php
similarity index 88%
rename from app/Livewire/TeamSharedVariablesIndex.php
rename to app/Livewire/SharedVariables/Team/Index.php
index eeee30ab9..ef5c7472c 100644
--- a/app/Livewire/TeamSharedVariablesIndex.php
+++ b/app/Livewire/SharedVariables/Team/Index.php
@@ -1,11 +1,11 @@
'$refresh', 'saveKey' => 'saveKey'];
@@ -37,6 +37,6 @@ class TeamSharedVariablesIndex extends Component
}
public function render()
{
- return view('livewire.team-shared-variables-index');
+ return view('livewire.shared-variables.team.index');
}
}
diff --git a/app/Livewire/Team/Storage/Create.php b/app/Livewire/Storage/Create.php
similarity index 95%
rename from app/Livewire/Team/Storage/Create.php
rename to app/Livewire/Storage/Create.php
index a25fc9821..d1af807d5 100644
--- a/app/Livewire/Team/Storage/Create.php
+++ b/app/Livewire/Storage/Create.php
@@ -1,6 +1,6 @@
storage->team_id = currentTeam()->id;
$this->storage->testConnection();
$this->storage->save();
- return redirect()->route('team.storage.show', $this->storage->uuid);
+ return redirect()->route('storage.show', $this->storage->uuid);
} catch (\Throwable $e) {
$this->dispatch('error', 'Failed to create storage.', $e->getMessage());
// return handleError($e, $this);
diff --git a/app/Livewire/Team/Storage/Form.php b/app/Livewire/Storage/Form.php
similarity index 94%
rename from app/Livewire/Team/Storage/Form.php
rename to app/Livewire/Storage/Form.php
index 1fd0d470b..79c1f0c30 100644
--- a/app/Livewire/Team/Storage/Form.php
+++ b/app/Livewire/Storage/Form.php
@@ -1,6 +1,6 @@
storage->delete();
- return redirect()->route('team.storage.index');
+ return redirect()->route('storage.index');
} catch (\Throwable $e) {
return handleError($e, $this);
}
diff --git a/app/Livewire/Team/Storage/Index.php b/app/Livewire/Storage/Index.php
similarity index 73%
rename from app/Livewire/Team/Storage/Index.php
rename to app/Livewire/Storage/Index.php
index c15834564..f071a0af0 100644
--- a/app/Livewire/Team/Storage/Index.php
+++ b/app/Livewire/Storage/Index.php
@@ -1,6 +1,6 @@
storage = S3Storage::ownedByCurrentTeam()->whereUuid(request()->storage_uuid)->first();
+ if (!$this->storage) {
+ abort(404);
+ }
+ }
+ public function render()
+ {
+ return view('livewire.storage.show');
+ }
+}
diff --git a/app/Livewire/Team/Storage/Show.php b/app/Livewire/Team/Storage/Show.php
index 6fbb6034f..ab2acbbb9 100644
--- a/app/Livewire/Team/Storage/Show.php
+++ b/app/Livewire/Team/Storage/Show.php
@@ -17,6 +17,6 @@ class Show extends Component
}
public function render()
{
- return view('livewire.team.storage.show');
+ return view('livewire.storage.show');
}
}
diff --git a/app/Models/Application.php b/app/Models/Application.php
index 971f1e894..f28d389f4 100644
--- a/app/Models/Application.php
+++ b/app/Models/Application.php
@@ -346,6 +346,10 @@ class Application extends BaseModel
}
return null;
}
+ public function main_port()
+ {
+ return $this->settings->is_static ? [80] : $this->ports_exposes_array;
+ }
public function environment_variables(): HasMany
{
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->orderBy('key', 'asc');
diff --git a/app/Models/S3Storage.php b/app/Models/S3Storage.php
index 9d60ce491..dc0b93466 100644
--- a/app/Models/S3Storage.php
+++ b/app/Models/S3Storage.php
@@ -48,7 +48,7 @@ class S3Storage extends BaseModel
if ($this->unusable_email_sent === false && is_transactional_emails_active()) {
$mail = new MailMessage();
$mail->subject('Coolify: S3 Storage Connection Error');
- $mail->view('emails.s3-connection-error', ['name' => $this->name, 'reason' => $e->getMessage(), 'url' => route('team.storage.show', ['storage_uuid' => $this->uuid])]);
+ $mail->view('emails.s3-connection-error', ['name' => $this->name, 'reason' => $e->getMessage(), 'url' => route('storage.show', ['storage_uuid' => $this->uuid])]);
$users = collect([]);
$members = $this->team->members()->get();
foreach ($members as $user) {
diff --git a/app/View/Components/Forms/Textarea.php b/app/View/Components/Forms/Textarea.php
index 86547cf65..28f4a45ba 100644
--- a/app/View/Components/Forms/Textarea.php
+++ b/app/View/Components/Forms/Textarea.php
@@ -23,10 +23,11 @@ class Textarea extends Component
public bool $disabled = false,
public bool $readonly = false,
public bool $allowTab = false,
+ public bool $spellcheck = false,
public ?string $helper = null,
public bool $realtimeValidation = false,
public bool $allowToPeak = true,
- public string $defaultClass = "input scrollbar",
+ public string $defaultClass = "input scrollbar font-mono",
public string $defaultClassInput = "input"
) {
//
diff --git a/bootstrap/helpers/services.php b/bootstrap/helpers/services.php
index 8e3c0337e..5b71a8b10 100644
--- a/bootstrap/helpers/services.php
+++ b/bootstrap/helpers/services.php
@@ -18,7 +18,7 @@ function collectRegex(string $name)
}
function replaceVariables($variable)
{
- return $variable->replaceFirst('$', '')->replaceFirst('{', '')->replaceLast('}', '');
+ return $variable->after('${')->before('}');
}
function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase|Application $oneService, bool $isInit = false)
diff --git a/config/sentry.php b/config/sentry.php
index 416daa809..bfdaf0b4c 100644
--- a/config/sentry.php
+++ b/config/sentry.php
@@ -7,7 +7,7 @@ return [
// The release version of your application
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
- 'release' => '4.0.0-beta.267',
+ 'release' => '4.0.0-beta.268',
// When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'),
diff --git a/config/version.php b/config/version.php
index 66b6ee419..b65f24d33 100644
--- a/config/version.php
+++ b/config/version.php
@@ -1,3 +1,3 @@
\ No newline at end of file
diff --git a/resources/views/components/forms/textarea.blade.php b/resources/views/components/forms/textarea.blade.php
index f5bdc3e7d..2c32c585e 100644
--- a/resources/views/components/forms/textarea.blade.php
+++ b/resources/views/components/forms/textarea.blade.php
@@ -56,7 +56,7 @@
@else
-