commit
d9f1c2a406
@ -46,14 +46,14 @@ public function handle(Server $server, $fromUI = false)
|
|||||||
$port443 = is_resource($connection443) && fclose($connection443);
|
$port443 = is_resource($connection443) && fclose($connection443);
|
||||||
if ($port80) {
|
if ($port80) {
|
||||||
if ($fromUI) {
|
if ($fromUI) {
|
||||||
throw new \Exception("Port 80 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a> <br> Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
|
throw new \Exception("Port 80 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a><br>Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($port443) {
|
if ($port443) {
|
||||||
if ($fromUI) {
|
if ($fromUI) {
|
||||||
throw new \Exception("Port 443 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a> <br> Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
|
throw new \Exception("Port 443 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a><br>Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -423,7 +423,7 @@ private function deploy_docker_compose_buildpack()
|
|||||||
if ($this->application->settings->is_raw_compose_deployment_enabled) {
|
if ($this->application->settings->is_raw_compose_deployment_enabled) {
|
||||||
if ($this->docker_compose_custom_start_command) {
|
if ($this->docker_compose_custom_start_command) {
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
["cd {$this->basedir} && {$this->docker_compose_custom_start_command}", "hidden" => true],
|
[executeInDocker($this->deployment_uuid, "cd {$this->workdir} && {$this->docker_compose_custom_start_command}"), "hidden" => true],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$server_workdir = $this->application->workdir();
|
$server_workdir = $this->application->workdir();
|
||||||
@ -749,7 +749,7 @@ private function rolling_update()
|
|||||||
$this->write_deployment_configurations();
|
$this->write_deployment_configurations();
|
||||||
$this->server = $this->original_server;
|
$this->server = $this->original_server;
|
||||||
}
|
}
|
||||||
if (count($this->application->ports_mappings_array) > 0 || (bool) $this->application->settings->is_consistent_container_name_enabled || $this->pull_request_id !== 0) {
|
if (count($this->application->ports_mappings_array) > 0 || (bool) $this->application->settings->is_consistent_container_name_enabled || $this->pull_request_id !== 0 || str($this->application->custom_docker_run_options)->contains('--ip') || str($this->application->custom_docker_run_options)->contains('--ip6')) {
|
||||||
$this->application_deployment_queue->addLogEntry("----------------------------------------");
|
$this->application_deployment_queue->addLogEntry("----------------------------------------");
|
||||||
if (count($this->application->ports_mappings_array) > 0) {
|
if (count($this->application->ports_mappings_array) > 0) {
|
||||||
$this->application_deployment_queue->addLogEntry("Application has ports mapped to the host system, rolling update is not supported.");
|
$this->application_deployment_queue->addLogEntry("Application has ports mapped to the host system, rolling update is not supported.");
|
||||||
@ -761,6 +761,9 @@ private function rolling_update()
|
|||||||
$this->application->settings->is_consistent_container_name_enabled = true;
|
$this->application->settings->is_consistent_container_name_enabled = true;
|
||||||
$this->application_deployment_queue->addLogEntry("Pull request deployment, rolling update is not supported.");
|
$this->application_deployment_queue->addLogEntry("Pull request deployment, rolling update is not supported.");
|
||||||
}
|
}
|
||||||
|
if (str($this->application->custom_docker_run_options)->contains('--ip') || str($this->application->custom_docker_run_options)->contains('--ip6')) {
|
||||||
|
$this->application_deployment_queue->addLogEntry("Custom IP address is set, rolling update is not supported.");
|
||||||
|
}
|
||||||
$this->stop_running_container(force: true);
|
$this->stop_running_container(force: true);
|
||||||
$this->start_by_compose_file();
|
$this->start_by_compose_file();
|
||||||
} else {
|
} else {
|
||||||
@ -1274,10 +1277,9 @@ private function generate_compose_file()
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
if ($this->pull_request_id === 0) {
|
if ($this->pull_request_id === 0) {
|
||||||
|
$custom_compose = convert_docker_run_to_compose($this->application->custom_docker_run_options);
|
||||||
if ((bool)$this->application->settings->is_consistent_container_name_enabled) {
|
if ((bool)$this->application->settings->is_consistent_container_name_enabled) {
|
||||||
$docker_compose['services'][$this->application->uuid] = $docker_compose['services'][$this->container_name];
|
$docker_compose['services'][$this->application->uuid] = $docker_compose['services'][$this->container_name];
|
||||||
data_forget($docker_compose, 'services.' . $this->container_name);
|
|
||||||
$custom_compose = convert_docker_run_to_compose($this->application->custom_docker_run_options);
|
|
||||||
if (count($custom_compose) > 0) {
|
if (count($custom_compose) > 0) {
|
||||||
$ipv4 = data_get($custom_compose, 'ip.0');
|
$ipv4 = data_get($custom_compose, 'ip.0');
|
||||||
$ipv6 = data_get($custom_compose, 'ip6.0');
|
$ipv6 = data_get($custom_compose, 'ip6.0');
|
||||||
@ -1295,7 +1297,6 @@ private function generate_compose_file()
|
|||||||
$docker_compose['services'][$this->application->uuid] = array_merge_recursive($docker_compose['services'][$this->application->uuid], $custom_compose);
|
$docker_compose['services'][$this->application->uuid] = array_merge_recursive($docker_compose['services'][$this->application->uuid], $custom_compose);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$custom_compose = convert_docker_run_to_compose($this->application->custom_docker_run_options);
|
|
||||||
if (count($custom_compose) > 0) {
|
if (count($custom_compose) > 0) {
|
||||||
$ipv4 = data_get($custom_compose, 'ip.0');
|
$ipv4 = data_get($custom_compose, 'ip.0');
|
||||||
$ipv6 = data_get($custom_compose, 'ip6.0');
|
$ipv6 = data_get($custom_compose, 'ip6.0');
|
||||||
@ -1359,23 +1360,53 @@ private function generate_environment_variables($ports)
|
|||||||
$environment_variables = collect();
|
$environment_variables = collect();
|
||||||
if ($this->pull_request_id === 0) {
|
if ($this->pull_request_id === 0) {
|
||||||
foreach ($this->application->runtime_environment_variables as $env) {
|
foreach ($this->application->runtime_environment_variables as $env) {
|
||||||
$environment_variables->push("$env->key=$env->real_value");
|
// This is necessary because we have to escape the value of the environment variable
|
||||||
|
// but only if the environment variable is created after 4.0.0-beta.240
|
||||||
|
// when I implemented the escaping feature.
|
||||||
|
|
||||||
|
// Old environment variables are not escaped, because it could break the application
|
||||||
|
// as the application could expect the unescaped value.
|
||||||
|
if ($env->version === '4.0.0-beta.239') {
|
||||||
|
$real_value = $env->value;
|
||||||
|
} else {
|
||||||
|
$real_value = escapeEnvVariables($env->real_value);
|
||||||
|
}
|
||||||
|
$environment_variables->push("$env->key=$real_value");
|
||||||
}
|
}
|
||||||
foreach ($this->application->nixpacks_environment_variables as $env) {
|
foreach ($this->application->nixpacks_environment_variables as $env) {
|
||||||
$environment_variables->push("$env->key=$env->real_value");
|
if ($env->version === '4.0.0-beta.239') {
|
||||||
|
$real_value = $env->value;
|
||||||
|
} else {
|
||||||
|
$real_value = escapeEnvVariables($env->real_value);
|
||||||
|
}
|
||||||
|
$environment_variables->push("$env->key=$real_value");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
foreach ($this->application->runtime_environment_variables_preview as $env) {
|
foreach ($this->application->runtime_environment_variables_preview as $env) {
|
||||||
$environment_variables->push("$env->key=$env->real_value");
|
if ($env->version === '4.0.0-beta.239') {
|
||||||
|
$real_value = $env->value;
|
||||||
|
} else {
|
||||||
|
$real_value = escapeEnvVariables($env->real_value);
|
||||||
|
}
|
||||||
|
$environment_variables->push("$env->key=$real_value");
|
||||||
}
|
}
|
||||||
foreach ($this->application->nixpacks_environment_variables_preview as $env) {
|
foreach ($this->application->nixpacks_environment_variables_preview as $env) {
|
||||||
$environment_variables->push("$env->key=$env->real_value");
|
if ($env->version === '4.0.0-beta.239') {
|
||||||
|
$real_value = $env->value;
|
||||||
|
} else {
|
||||||
|
$real_value = escapeEnvVariables($env->real_value);
|
||||||
|
}
|
||||||
|
$environment_variables->push("$env->key=$real_value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add PORT if not exists, use the first port as default
|
// Add PORT if not exists, use the first port as default
|
||||||
if ($environment_variables->filter(fn ($env) => Str::of($env)->startsWith('PORT'))->isEmpty()) {
|
if ($environment_variables->filter(fn ($env) => Str::of($env)->startsWith('PORT'))->isEmpty()) {
|
||||||
$environment_variables->push("PORT={$ports[0]}");
|
$environment_variables->push("PORT={$ports[0]}");
|
||||||
}
|
}
|
||||||
|
// Add HOST if not exists
|
||||||
|
if ($environment_variables->filter(fn ($env) => Str::of($env)->startsWith('HOST'))->isEmpty()) {
|
||||||
|
$environment_variables->push("HOST=0.0.0.0");
|
||||||
|
}
|
||||||
if ($environment_variables->filter(fn ($env) => Str::of($env)->startsWith('SOURCE_COMMIT'))->isEmpty()) {
|
if ($environment_variables->filter(fn ($env) => Str::of($env)->startsWith('SOURCE_COMMIT'))->isEmpty()) {
|
||||||
if (!is_null($this->commit)) {
|
if (!is_null($this->commit)) {
|
||||||
$environment_variables->push("SOURCE_COMMIT={$this->commit}");
|
$environment_variables->push("SOURCE_COMMIT={$this->commit}");
|
||||||
|
@ -17,9 +17,14 @@ class Edit extends Component
|
|||||||
public function saveKey($data)
|
public function saveKey($data)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$found = $this->project->environment_variables()->where('key', $data['key'])->first();
|
||||||
|
if ($found) {
|
||||||
|
throw new \Exception('Variable already exists.');
|
||||||
|
}
|
||||||
$this->project->environment_variables()->create([
|
$this->project->environment_variables()->create([
|
||||||
'key' => $data['key'],
|
'key' => $data['key'],
|
||||||
'value' => $data['value'],
|
'value' => $data['value'],
|
||||||
|
'is_multiline' => $data['is_multiline'],
|
||||||
'type' => 'project',
|
'type' => 'project',
|
||||||
'team_id' => currentTeam()->id,
|
'team_id' => currentTeam()->id,
|
||||||
]);
|
]);
|
||||||
|
@ -21,9 +21,14 @@ class EnvironmentEdit extends Component
|
|||||||
public function saveKey($data)
|
public function saveKey($data)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$found = $this->environment->environment_variables()->where('key', $data['key'])->first();
|
||||||
|
if ($found) {
|
||||||
|
throw new \Exception('Variable already exists.');
|
||||||
|
}
|
||||||
$this->environment->environment_variables()->create([
|
$this->environment->environment_variables()->create([
|
||||||
'key' => $data['key'],
|
'key' => $data['key'],
|
||||||
'value' => $data['value'],
|
'value' => $data['value'],
|
||||||
|
'is_multiline' => $data['is_multiline'],
|
||||||
'type' => 'environment',
|
'type' => 'environment',
|
||||||
'team_id' => currentTeam()->id,
|
'team_id' => currentTeam()->id,
|
||||||
]);
|
]);
|
||||||
|
@ -11,17 +11,20 @@ class Add extends Component
|
|||||||
public string $key;
|
public string $key;
|
||||||
public ?string $value = null;
|
public ?string $value = null;
|
||||||
public bool $is_build_time = false;
|
public bool $is_build_time = false;
|
||||||
|
public bool $is_multiline = false;
|
||||||
|
|
||||||
protected $listeners = ['clearAddEnv' => 'clear'];
|
protected $listeners = ['clearAddEnv' => 'clear'];
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
'key' => 'required|string',
|
'key' => 'required|string',
|
||||||
'value' => 'nullable',
|
'value' => 'nullable',
|
||||||
'is_build_time' => 'required|boolean',
|
'is_build_time' => 'required|boolean',
|
||||||
|
'is_multiline' => 'required|boolean',
|
||||||
];
|
];
|
||||||
protected $validationAttributes = [
|
protected $validationAttributes = [
|
||||||
'key' => 'key',
|
'key' => 'key',
|
||||||
'value' => 'value',
|
'value' => 'value',
|
||||||
'is_build_time' => 'build',
|
'is_build_time' => 'build',
|
||||||
|
'is_multiline' => 'multiline',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
@ -43,6 +46,7 @@ public function submit()
|
|||||||
'key' => $this->key,
|
'key' => $this->key,
|
||||||
'value' => $this->value,
|
'value' => $this->value,
|
||||||
'is_build_time' => $this->is_build_time,
|
'is_build_time' => $this->is_build_time,
|
||||||
|
'is_multiline' => $this->is_multiline,
|
||||||
'is_preview' => $this->is_preview,
|
'is_preview' => $this->is_preview,
|
||||||
]);
|
]);
|
||||||
$this->clear();
|
$this->clear();
|
||||||
@ -53,5 +57,6 @@ public function clear()
|
|||||||
$this->key = '';
|
$this->key = '';
|
||||||
$this->value = '';
|
$this->value = '';
|
||||||
$this->is_build_time = false;
|
$this->is_build_time = false;
|
||||||
|
$this->is_multiline = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ class All extends Component
|
|||||||
{
|
{
|
||||||
public $resource;
|
public $resource;
|
||||||
public bool $showPreview = false;
|
public bool $showPreview = false;
|
||||||
public string|null $modalId = null;
|
public ?string $modalId = null;
|
||||||
public ?string $variables = null;
|
public ?string $variables = null;
|
||||||
public ?string $variablesPreview = null;
|
public ?string $variablesPreview = null;
|
||||||
public string $view = 'normal';
|
public string $view = 'normal';
|
||||||
@ -34,6 +34,9 @@ public function getDevView()
|
|||||||
if ($item->is_shown_once) {
|
if ($item->is_shown_once) {
|
||||||
return "$item->key=(locked secret)";
|
return "$item->key=(locked secret)";
|
||||||
}
|
}
|
||||||
|
if ($item->is_multiline) {
|
||||||
|
return "$item->key=(multiline, edit in normal view)";
|
||||||
|
}
|
||||||
return "$item->key=$item->value";
|
return "$item->key=$item->value";
|
||||||
})->sort()->join('
|
})->sort()->join('
|
||||||
');
|
');
|
||||||
@ -42,6 +45,9 @@ public function getDevView()
|
|||||||
if ($item->is_shown_once) {
|
if ($item->is_shown_once) {
|
||||||
return "$item->key=(locked secret)";
|
return "$item->key=(locked secret)";
|
||||||
}
|
}
|
||||||
|
if ($item->is_multiline) {
|
||||||
|
return "$item->key=(multiline, edit in normal view)";
|
||||||
|
}
|
||||||
return "$item->key=$item->value";
|
return "$item->key=$item->value";
|
||||||
})->sort()->join('
|
})->sort()->join('
|
||||||
');
|
');
|
||||||
@ -67,7 +73,7 @@ public function saveVariables($isPreview)
|
|||||||
$found = $this->resource->environment_variables()->where('key', $key)->first();
|
$found = $this->resource->environment_variables()->where('key', $key)->first();
|
||||||
}
|
}
|
||||||
if ($found) {
|
if ($found) {
|
||||||
if ($found->is_shown_once) {
|
if ($found->is_shown_once || $found->is_multiline) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$found->value = $variable;
|
$found->value = $variable;
|
||||||
@ -144,6 +150,7 @@ public function submit($data)
|
|||||||
$environment->key = $data['key'];
|
$environment->key = $data['key'];
|
||||||
$environment->value = $data['value'];
|
$environment->value = $data['value'];
|
||||||
$environment->is_build_time = $data['is_build_time'];
|
$environment->is_build_time = $data['is_build_time'];
|
||||||
|
$environment->is_multiline = $data['is_multiline'];
|
||||||
$environment->is_preview = $data['is_preview'];
|
$environment->is_preview = $data['is_preview'];
|
||||||
|
|
||||||
switch ($this->resource->type()) {
|
switch ($this->resource->type()) {
|
||||||
|
@ -21,6 +21,7 @@ class Show extends Component
|
|||||||
'env.key' => 'required|string',
|
'env.key' => 'required|string',
|
||||||
'env.value' => 'nullable',
|
'env.value' => 'nullable',
|
||||||
'env.is_build_time' => 'required|boolean',
|
'env.is_build_time' => 'required|boolean',
|
||||||
|
'env.is_multiline' => 'required|boolean',
|
||||||
'env.is_shown_once' => 'required|boolean',
|
'env.is_shown_once' => 'required|boolean',
|
||||||
'env.real_value' => 'nullable',
|
'env.real_value' => 'nullable',
|
||||||
];
|
];
|
||||||
@ -28,6 +29,7 @@ class Show extends Component
|
|||||||
'env.key' => 'Key',
|
'env.key' => 'Key',
|
||||||
'env.value' => 'Value',
|
'env.value' => 'Value',
|
||||||
'env.is_build_time' => 'Build Time',
|
'env.is_build_time' => 'Build Time',
|
||||||
|
'env.is_multiline' => 'Multiline',
|
||||||
'env.is_shown_once' => 'Shown Once',
|
'env.is_shown_once' => 'Shown Once',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -71,6 +71,9 @@ public function instantSave()
|
|||||||
}
|
}
|
||||||
public function getLogs($refresh = false)
|
public function getLogs($refresh = false)
|
||||||
{
|
{
|
||||||
|
if (!$this->server->isFunctional()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ($this->resource?->getMorphClass() === 'App\Models\Application') {
|
if ($this->resource?->getMorphClass() === 'App\Models\Application') {
|
||||||
if (str($this->container)->contains('-pr-')) {
|
if (str($this->container)->contains('-pr-')) {
|
||||||
$this->pull_request = "Pull Request: " . str($this->container)->afterLast('-pr-')->beforeLast('_')->value();
|
$this->pull_request = "Pull Request: " . str($this->container)->afterLast('-pr-')->beforeLast('_')->value();
|
||||||
@ -79,6 +82,9 @@ public function getLogs($refresh = false)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!$refresh && ($this->resource?->getMorphClass() === 'App\Models\Service' || str($this->container)->contains('-pr-'))) return;
|
if (!$refresh && ($this->resource?->getMorphClass() === 'App\Models\Service' || str($this->container)->contains('-pr-'))) return;
|
||||||
|
if (!$this->numberOfLines) {
|
||||||
|
$this->numberOfLines = 1000;
|
||||||
|
}
|
||||||
if ($this->container) {
|
if ($this->container) {
|
||||||
if ($this->showTimeStamps) {
|
if ($this->showTimeStamps) {
|
||||||
if ($this->server->isSwarm()) {
|
if ($this->server->isSwarm()) {
|
||||||
|
@ -29,6 +29,9 @@ public function loadContainers($server_id)
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$server = $this->servers->firstWhere('id', $server_id);
|
$server = $this->servers->firstWhere('id', $server_id);
|
||||||
|
if (!$server->isFunctional()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ($server->isSwarm()) {
|
if ($server->isSwarm()) {
|
||||||
$containers = collect([
|
$containers = collect([
|
||||||
[
|
[
|
||||||
@ -96,7 +99,6 @@ public function mount()
|
|||||||
$this->resource->databases()->get()->each(function ($database) {
|
$this->resource->databases()->get()->each(function ($database) {
|
||||||
$this->containers->push(data_get($database, 'name') . '-' . data_get($this->resource, 'uuid'));
|
$this->containers->push(data_get($database, 'name') . '-' . data_get($this->resource, 'uuid'));
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($this->resource->server->isFunctional()) {
|
if ($this->resource->server->isFunctional()) {
|
||||||
$this->servers = $this->servers->push($this->resource->server);
|
$this->servers = $this->servers->push($this->resource->server);
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,14 @@ class TeamSharedVariablesIndex extends Component
|
|||||||
public function saveKey($data)
|
public function saveKey($data)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$found = $this->team->environment_variables()->where('key', $data['key'])->first();
|
||||||
|
if ($found) {
|
||||||
|
throw new \Exception('Variable already exists.');
|
||||||
|
}
|
||||||
$this->team->environment_variables()->create([
|
$this->team->environment_variables()->create([
|
||||||
'key' => $data['key'],
|
'key' => $data['key'],
|
||||||
'value' => $data['value'],
|
'value' => $data['value'],
|
||||||
|
'is_multiline' => $data['is_multiline'],
|
||||||
'type' => 'team',
|
'type' => 'team',
|
||||||
'team_id' => currentTeam()->id,
|
'team_id' => currentTeam()->id,
|
||||||
]);
|
]);
|
||||||
|
@ -752,7 +752,7 @@ function parseRawCompose()
|
|||||||
$type = data_get_str($volume, 'type');
|
$type = data_get_str($volume, 'type');
|
||||||
$source = data_get_str($volume, 'source');
|
$source = data_get_str($volume, 'source');
|
||||||
}
|
}
|
||||||
if ($type->value() === 'bind') {
|
if ($type?->value() === 'bind') {
|
||||||
if ($source->value() === "/var/run/docker.sock") {
|
if ($source->value() === "/var/run/docker.sock") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,15 @@ class EnvironmentVariable extends Model
|
|||||||
'key' => 'string',
|
'key' => 'string',
|
||||||
'value' => 'encrypted',
|
'value' => 'encrypted',
|
||||||
'is_build_time' => 'boolean',
|
'is_build_time' => 'boolean',
|
||||||
|
'is_multiline' => 'boolean',
|
||||||
|
'is_preview' => 'boolean',
|
||||||
|
'version' => 'string'
|
||||||
];
|
];
|
||||||
protected $appends = ['real_value', 'is_shared'];
|
protected $appends = ['real_value', 'is_shared'];
|
||||||
|
|
||||||
protected static function booted()
|
protected static function booted()
|
||||||
{
|
{
|
||||||
static::created(function ($environment_variable) {
|
static::created(function (EnvironmentVariable $environment_variable) {
|
||||||
if ($environment_variable->application_id && !$environment_variable->is_preview) {
|
if ($environment_variable->application_id && !$environment_variable->is_preview) {
|
||||||
$found = ModelsEnvironmentVariable::where('key', $environment_variable->key)->where('application_id', $environment_variable->application_id)->where('is_preview', true)->first();
|
$found = ModelsEnvironmentVariable::where('key', $environment_variable->key)->where('application_id', $environment_variable->application_id)->where('is_preview', true)->first();
|
||||||
$application = Application::find($environment_variable->application_id);
|
$application = Application::find($environment_variable->application_id);
|
||||||
@ -31,11 +34,15 @@ protected static function booted()
|
|||||||
'key' => $environment_variable->key,
|
'key' => $environment_variable->key,
|
||||||
'value' => $environment_variable->value,
|
'value' => $environment_variable->value,
|
||||||
'is_build_time' => $environment_variable->is_build_time,
|
'is_build_time' => $environment_variable->is_build_time,
|
||||||
|
'is_multiline' => $environment_variable->is_multiline,
|
||||||
'application_id' => $environment_variable->application_id,
|
'application_id' => $environment_variable->application_id,
|
||||||
'is_preview' => true,
|
'is_preview' => true
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$environment_variable->update([
|
||||||
|
'version' => config('version')
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public function service()
|
public function service()
|
||||||
@ -49,7 +56,7 @@ protected function value(): Attribute
|
|||||||
set: fn (?string $value = null) => $this->set_environment_variables($value),
|
set: fn (?string $value = null) => $this->set_environment_variables($value),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public function realValue(): Attribute
|
public function resource()
|
||||||
{
|
{
|
||||||
$resource = null;
|
$resource = null;
|
||||||
if ($this->application_id) {
|
if ($this->application_id) {
|
||||||
@ -71,9 +78,19 @@ public function realValue(): Attribute
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return $resource;
|
||||||
|
}
|
||||||
|
public function realValue(): Attribute
|
||||||
|
{
|
||||||
|
$resource = $this->resource();
|
||||||
return Attribute::make(
|
return Attribute::make(
|
||||||
get: function () use ($resource) {
|
get: function () use ($resource) {
|
||||||
return $this->get_real_environment_variables($this->value, $resource);
|
$env = $this->get_real_environment_variables($this->value, $resource);
|
||||||
|
return data_get($env, 'value', $env);
|
||||||
|
if (is_string($env)) {
|
||||||
|
return $env;
|
||||||
|
}
|
||||||
|
return $env->value;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -89,9 +106,9 @@ protected function isShared(): Attribute
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
private function get_real_environment_variables(?string $environment_variable = null, $resource = null): string|null
|
private function get_real_environment_variables(?string $environment_variable = null, $resource = null)
|
||||||
{
|
{
|
||||||
if (!$environment_variable || !$resource) {
|
if ((is_null($environment_variable) && $environment_variable == '') || is_null($resource)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$environment_variable = trim($environment_variable);
|
$environment_variable = trim($environment_variable);
|
||||||
@ -112,7 +129,7 @@ private function get_real_environment_variables(?string $environment_variable =
|
|||||||
}
|
}
|
||||||
$environment_variable_found = SharedEnvironmentVariable::where("type", $type)->where('key', $variable)->where('team_id', $resource->team()->id)->where("{$type}_id", $id)->first();
|
$environment_variable_found = SharedEnvironmentVariable::where("type", $type)->where('key', $variable)->where('team_id', $resource->team()->id)->where("{$type}_id", $id)->first();
|
||||||
if ($environment_variable_found) {
|
if ($environment_variable_found) {
|
||||||
return $environment_variable_found->value;
|
return $environment_variable_found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $environment_variable;
|
return $environment_variable;
|
||||||
|
@ -10,17 +10,18 @@
|
|||||||
class Input extends Component
|
class Input extends Component
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public string|null $id = null,
|
public ?string $id = null,
|
||||||
public string|null $name = null,
|
public ?string $name = null,
|
||||||
public string|null $type = 'text',
|
public ?string $type = 'text',
|
||||||
public string|null $value = null,
|
public ?string $value = null,
|
||||||
public string|null $label = null,
|
public ?string $label = null,
|
||||||
public bool $required = false,
|
public bool $required = false,
|
||||||
public bool $disabled = false,
|
public bool $disabled = false,
|
||||||
public bool $readonly = false,
|
public bool $readonly = false,
|
||||||
public string|null $helper = null,
|
public ?string $helper = null,
|
||||||
public bool $allowToPeak = true,
|
public bool $allowToPeak = true,
|
||||||
public string $defaultClass = "input input-sm bg-coolgray-100 rounded text-white w-full disabled:bg-coolgray-200/50 disabled:border-none placeholder:text-coolgray-500 read-only:text-neutral-500 read-only:bg-coolgray-200/50"
|
public bool $isMultiline = false,
|
||||||
|
public string $defaultClass = "input input-sm bg-coolgray-100 rounded text-white w-full disabled:bg-coolgray-200/50 disabled:border-none placeholder:text-coolgray-500 read-only:text-neutral-500 read-only:bg-coolgray-200/50"
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
@ -14,18 +13,20 @@ class Textarea extends Component
|
|||||||
* Create a new component instance.
|
* Create a new component instance.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public string|null $id = null,
|
public ?string $id = null,
|
||||||
public string|null $name = null,
|
public ?string $name = null,
|
||||||
public string|null $type = 'text',
|
public ?string $type = 'text',
|
||||||
public string|null $value = null,
|
public ?string $value = null,
|
||||||
public string|null $label = null,
|
public ?string $label = null,
|
||||||
public string|null $placeholder = null,
|
public ?string $placeholder = null,
|
||||||
public bool $required = false,
|
public bool $required = false,
|
||||||
public bool $disabled = false,
|
public bool $disabled = false,
|
||||||
public bool $readonly = false,
|
public bool $readonly = false,
|
||||||
public string|null $helper = null,
|
public ?string $helper = null,
|
||||||
public bool $realtimeValidation = false,
|
public bool $realtimeValidation = false,
|
||||||
public string $defaultClass = "textarea leading-normal bg-coolgray-100 rounded text-white scrollbar disabled:bg-coolgray-200/50 disabled:border-none placeholder:text-coolgray-500 read-only:text-neutral-500 read-only:bg-coolgray-200/50"
|
public bool $allowToPeak = true,
|
||||||
|
public string $defaultClass = "textarea leading-normal bg-coolgray-100 rounded text-white w-full scrollbar disabled:bg-coolgray-200/50 disabled:border-none placeholder:text-coolgray-500 read-only:text-neutral-500 read-only:bg-coolgray-200/50",
|
||||||
|
public string $defaultClassInput = "input input-sm bg-coolgray-100 rounded text-white w-full disabled:bg-coolgray-200/50 disabled:border-none placeholder:text-coolgray-500 read-only:text-neutral-500 read-only:bg-coolgray-200/50"
|
||||||
) {
|
) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
@ -557,7 +557,8 @@ function convert_docker_run_to_compose(?string $custom_docker_run_options = null
|
|||||||
return $compose_options->toArray();
|
return $compose_options->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateComposeFile(string $compose, int $server_id): string|Throwable {
|
function validateComposeFile(string $compose, int $server_id): string|Throwable
|
||||||
|
{
|
||||||
return 'OK';
|
return 'OK';
|
||||||
try {
|
try {
|
||||||
$uuid = Str::random(10);
|
$uuid = Str::random(10);
|
||||||
@ -578,3 +579,10 @@ function validateComposeFile(string $compose, int $server_id): string|Throwable
|
|||||||
], $server);
|
], $server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function escapeEnvVariables($value)
|
||||||
|
{
|
||||||
|
$search = array("\\", "\r", "\t", "\x0", '"', "'", "$");
|
||||||
|
$replace = array("\\\\", "\\r", "\\t", "\\0", '\"', "\'", "$$");
|
||||||
|
return str_replace($search, $replace, $value);
|
||||||
|
}
|
||||||
|
@ -818,7 +818,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
|||||||
$isDirectory = (bool) data_get($volume, 'isDirectory', false) || (bool) data_get($volume, 'is_directory', false);
|
$isDirectory = (bool) data_get($volume, 'isDirectory', false) || (bool) data_get($volume, 'is_directory', false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($type->value() === 'bind') {
|
if ($type?->value() === 'bind') {
|
||||||
if ($source->value() === "/var/run/docker.sock") {
|
if ($source->value() === "/var/run/docker.sock") {
|
||||||
return $volume;
|
return $volume;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// The release version of your application
|
// The release version of your application
|
||||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||||
'release' => '4.0.0-beta.239',
|
'release' => '4.0.0-beta.240',
|
||||||
// When left empty or `null` the Laravel environment will be used
|
// When left empty or `null` the Laravel environment will be used
|
||||||
'environment' => config('app.env'),
|
'environment' => config('app.env'),
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return '4.0.0-beta.239';
|
return '4.0.0-beta.240';
|
||||||
|
34
database/migrations/2024_03_14_214402_add_multiline_envs.php
Normal file
34
database/migrations/2024_03_14_214402_add_multiline_envs.php
Normal file
@ -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
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('environment_variables', function (Blueprint $table) {
|
||||||
|
$table->boolean('is_multiline')->default(false);
|
||||||
|
});
|
||||||
|
Schema::table('shared_environment_variables', function (Blueprint $table) {
|
||||||
|
$table->boolean('is_multiline')->default(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('environment_variables', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('is_multiline');
|
||||||
|
});
|
||||||
|
Schema::table('shared_environment_variables', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('is_multiline');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
@ -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
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('environment_variables', function (Blueprint $table) {
|
||||||
|
$table->string('version')->default('4.0.0-beta.239');
|
||||||
|
});
|
||||||
|
Schema::table('shared_environment_variables', function (Blueprint $table) {
|
||||||
|
$table->string('version')->default('4.0.0-beta.239');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('environment_variables', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('version');
|
||||||
|
});
|
||||||
|
Schema::table('shared_environment_variables', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('version');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
@ -1,4 +1,7 @@
|
|||||||
<div class="w-full">
|
<div @class([
|
||||||
|
'flex-1' => $isMultiline,
|
||||||
|
'w-full' => !$isMultiline,
|
||||||
|
])>
|
||||||
@if ($label)
|
@if ($label)
|
||||||
<label for="small-input" class="flex items-center gap-1 mb-1 text-sm font-medium">{{ $label }}
|
<label for="small-input" class="flex items-center gap-1 mb-1 text-sm font-medium">{{ $label }}
|
||||||
@if ($required)
|
@if ($required)
|
||||||
@ -10,7 +13,7 @@
|
|||||||
</label>
|
</label>
|
||||||
@endif
|
@endif
|
||||||
@if ($type === 'password')
|
@if ($type === 'password')
|
||||||
<div class="relative" x-data>
|
<div class="relative" x-data="{ type: 'password' }">
|
||||||
@if ($allowToPeak)
|
@if ($allowToPeak)
|
||||||
<div x-on:click="changePasswordFieldType"
|
<div x-on:click="changePasswordFieldType"
|
||||||
class="absolute inset-y-0 right-0 flex items-center pr-2 cursor-pointer hover:text-white">
|
class="absolute inset-y-0 right-0 flex items-center pr-2 cursor-pointer hover:text-white">
|
||||||
@ -22,8 +25,9 @@ class="absolute inset-y-0 right-0 flex items-center pr-2 cursor-pointer hover:te
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<input value="{{ $value }}" {{ $attributes->merge(['class' => $defaultClass]) }}
|
<input x-cloak x-show="type" value="{{ $value }}"
|
||||||
@required($required) @if ($id !== 'null') wire:model={{ $id }} @endif
|
{{ $attributes->merge(['class' => $defaultClass]) }} @required($required)
|
||||||
|
@if ($id !== 'null') wire:model={{ $id }} @endif
|
||||||
wire:dirty.class.remove='text-white' wire:dirty.class="input-warning" wire:loading.attr="disabled"
|
wire:dirty.class.remove='text-white' wire:dirty.class="input-warning" wire:loading.attr="disabled"
|
||||||
type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $id }}"
|
type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $id }}"
|
||||||
name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
|
name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
|
||||||
@ -33,9 +37,11 @@ class="absolute inset-y-0 right-0 flex items-center pr-2 cursor-pointer hover:te
|
|||||||
@else
|
@else
|
||||||
<input @if ($value) value="{{ $value }}" @endif
|
<input @if ($value) value="{{ $value }}" @endif
|
||||||
{{ $attributes->merge(['class' => $defaultClass]) }} @required($required) @readonly($readonly)
|
{{ $attributes->merge(['class' => $defaultClass]) }} @required($required) @readonly($readonly)
|
||||||
@if ($id !== 'null') wire:model={{ $id }} @endif wire:dirty.class.remove='text-white' wire:dirty.class="input-warning"
|
@if ($id !== 'null') wire:model={{ $id }} @endif
|
||||||
wire:loading.attr="disabled" type="{{ $type }}" @disabled($disabled)
|
wire:dirty.class.remove='text-white' wire:dirty.class="input-warning" wire:loading.attr="disabled"
|
||||||
@if ($id !== 'null') id={{ $id }} @endif name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}">
|
type="{{ $type }}" @disabled($disabled)
|
||||||
|
@if ($id !== 'null') id={{ $id }} @endif name="{{ $name }}"
|
||||||
|
placeholder="{{ $attributes->get('placeholder') }}">
|
||||||
@endif
|
@endif
|
||||||
@if (!$label && $helper)
|
@if (!$label && $helper)
|
||||||
<x-helper :helper="$helper" />
|
<x-helper :helper="$helper" />
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="form-control">
|
<div class="flex-1 form-control">
|
||||||
@if ($label)
|
@if ($label)
|
||||||
<label for="small-input" class="flex items-center gap-1 mb-1 text-sm font-medium">{{ $label }}
|
<label for="small-input" class="flex items-center gap-1 mb-1 text-sm font-medium">{{ $label }}
|
||||||
@if ($required)
|
@if ($required)
|
||||||
@ -9,13 +9,46 @@
|
|||||||
@endif
|
@endif
|
||||||
</label>
|
</label>
|
||||||
@endif
|
@endif
|
||||||
<textarea placeholder="{{ $placeholder }}" {{ $attributes->merge(['class' => $defaultClass]) }}
|
@if ($type === 'password')
|
||||||
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $id }}"
|
<div class="relative" x-data="{ type: 'password' }">
|
||||||
|
@if ($allowToPeak)
|
||||||
|
<div x-on:click="changePasswordFieldType"
|
||||||
|
class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer hover:text-white">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5"
|
||||||
|
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||||
|
<path d="M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
<input x-cloak x-show="type === 'password'" value="{{ $value }}"
|
||||||
|
{{ $attributes->merge(['class' => $defaultClassInput]) }} @required($required)
|
||||||
|
@if ($id !== 'null') wire:model={{ $id }} @endif
|
||||||
|
wire:dirty.class.remove='text-white' wire:dirty.class="input-warning" wire:loading.attr="disabled"
|
||||||
|
type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $id }}"
|
||||||
|
name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
|
||||||
|
aria-placeholder="{{ $attributes->get('placeholder') }}">
|
||||||
|
<textarea x-cloak x-show="type !== 'password'" placeholder="{{ $placeholder }}"
|
||||||
|
{{ $attributes->merge(['class' => $defaultClass]) }}
|
||||||
|
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $id }}"
|
||||||
|
@else
|
||||||
|
wire:model={{ $value ?? $id }}
|
||||||
|
wire:dirty.class="input-warning" @endif
|
||||||
|
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $id }}"
|
||||||
|
name="{{ $name }}" name={{ $id }}></textarea>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<textarea placeholder="{{ $placeholder }}" {{ $attributes->merge(['class' => $defaultClass]) }}
|
||||||
|
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $id }}"
|
||||||
@else
|
@else
|
||||||
wire:model={{ $value ?? $id }}
|
wire:model={{ $value ?? $id }}
|
||||||
wire:dirty.class="input-warning" @endif
|
wire:dirty.class="input-warning" @endif
|
||||||
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $id }}" name="{{ $name }}"
|
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $id }}"
|
||||||
name={{ $id }}></textarea>
|
name="{{ $name }}" name={{ $id }}></textarea>
|
||||||
|
@endif
|
||||||
|
|
||||||
@error($id)
|
@error($id)
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span class="text-red-500 label-text-alt">{{ $message }}</span>
|
<span class="text-red-500 label-text-alt">{{ $message }}</span>
|
||||||
|
@ -76,11 +76,13 @@ function changePasswordFieldType(event) {
|
|||||||
element = element.parentElement;
|
element = element.parentElement;
|
||||||
}
|
}
|
||||||
element = element.children[1];
|
element = element.children[1];
|
||||||
if (element.nodeName === 'INPUT') {
|
if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
|
||||||
if (element.type === 'password') {
|
if (element.type === 'password') {
|
||||||
element.type = 'text';
|
element.type = 'text';
|
||||||
|
this.type = 'text';
|
||||||
} else {
|
} else {
|
||||||
element.type = 'password';
|
element.type = 'password';
|
||||||
|
this.type = 'password';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,9 @@
|
|||||||
subscription is activated.<br> Please be patient.</span>
|
subscription is activated.<br> Please be patient.</span>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@if ($projects->count() === 0 && $servers->count() === 0)
|
<h3 class="pb-4">Projects</h3>
|
||||||
No resources found. Add your first server & private key <a class="text-white underline"
|
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||||
href="{{ route('server.create') }}">here</a> or go to the <a class="text-white underline" href="{{ route('onboarding') }}">onboarding page</a>.
|
@forelse ($projects as $project)
|
||||||
@endif
|
|
||||||
@if ($projects->count() > 0)
|
|
||||||
<h3 class="pb-4">Projects</h3>
|
|
||||||
@if ($projects->count() === 1)
|
|
||||||
<div class="grid grid-cols-1 gap-2">
|
|
||||||
@else
|
|
||||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
|
||||||
@endif
|
|
||||||
@foreach ($projects as $project)
|
|
||||||
<div class="gap-2 border border-transparent cursor-pointer box group">
|
<div class="gap-2 border border-transparent cursor-pointer box group">
|
||||||
@if (data_get($project, 'environments')->count() === 1)
|
@if (data_get($project, 'environments')->count() === 1)
|
||||||
<a class="flex flex-col flex-1 mx-6 hover:no-underline"
|
<a class="flex flex-col flex-1 mx-6 hover:no-underline"
|
||||||
@ -61,88 +52,96 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@empty
|
||||||
</div>
|
<div>
|
||||||
@if ($projects->count() > 0)
|
No projects found. Add your first server <a class="text-white underline"
|
||||||
|
onclick="newEmptyProject.showModal()">here</a> or
|
||||||
|
go to the <a class="text-white underline" href="{{ route('onboarding') }}">onboarding page.</a>
|
||||||
|
<livewire:project.add-empty />
|
||||||
|
</div>
|
||||||
|
@endforelse
|
||||||
|
</div>
|
||||||
<h3 class="py-4">Servers</h3>
|
<h3 class="py-4">Servers</h3>
|
||||||
@endif
|
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||||
@if ($servers->count() === 1)
|
@forelse ($servers as $server)
|
||||||
<div class="grid grid-cols-1 gap-2">
|
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
||||||
@else
|
@class([
|
||||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
'gap-2 border cursor-pointer box group',
|
||||||
@endif
|
'border-transparent' => $server->settings->is_reachable,
|
||||||
@foreach ($servers as $server)
|
'border-red-500' => !$server->settings->is_reachable,
|
||||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}" @class([
|
|
||||||
'gap-2 border cursor-pointer box group',
|
|
||||||
'border-transparent' => $server->settings->is_reachable,
|
|
||||||
'border-red-500' => !$server->settings->is_reachable,
|
|
||||||
])>
|
|
||||||
<div class="flex flex-col mx-6">
|
|
||||||
<div class="font-bold text-white">
|
|
||||||
{{ $server->name }}
|
|
||||||
</div>
|
|
||||||
<div class="description">
|
|
||||||
{{ $server->description }}</div>
|
|
||||||
<div class="flex gap-1 text-xs text-error">
|
|
||||||
@if (!$server->settings->is_reachable)
|
|
||||||
<span>Not reachable</span>
|
|
||||||
@endif
|
|
||||||
@if (!$server->settings->is_reachable && !$server->settings->is_usable)
|
|
||||||
&
|
|
||||||
@endif
|
|
||||||
@if (!$server->settings->is_usable)
|
|
||||||
<span>Not usable by Coolify</span>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1"></div>
|
|
||||||
</a>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<h3 class="py-4">Deployments</h3>
|
|
||||||
@if (count($deployments_per_server) > 0)
|
|
||||||
<x-loading />
|
|
||||||
@endif
|
|
||||||
<x-forms.button wire:click='cleanup_queue'>Cleanup Queues</x-forms.button>
|
|
||||||
</div>
|
|
||||||
<div wire:poll.1000ms="get_deployments" class="grid grid-cols-1">
|
|
||||||
@forelse ($deployments_per_server as $server_name => $deployments)
|
|
||||||
<h4 class="py-4">{{ $server_name }}</h4>
|
|
||||||
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3">
|
|
||||||
@foreach ($deployments as $deployment)
|
|
||||||
<a href="{{ data_get($deployment, 'deployment_url') }}" @class([
|
|
||||||
'gap-2 cursor-pointer box group border-l-2 border-dotted',
|
|
||||||
'border-coolgray-500' => data_get($deployment, 'status') === 'queued',
|
|
||||||
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
|
||||||
])>
|
])>
|
||||||
<div class="flex flex-col mx-6">
|
<div class="flex flex-col mx-6">
|
||||||
<div class="font-bold text-white">
|
<div class="font-bold text-white">
|
||||||
{{ data_get($deployment, 'application_name') }}
|
{{ $server->name }}
|
||||||
</div>
|
|
||||||
@if (data_get($deployment, 'pull_request_id') !== 0)
|
|
||||||
<div class="description">
|
|
||||||
PR #{{ data_get($deployment, 'pull_request_id') }}
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
<div class="description">
|
|
||||||
{{ str(data_get($deployment, 'status'))->headline() }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1"></div>
|
<div class="description">
|
||||||
</a>
|
{{ $server->description }}</div>
|
||||||
@endforeach
|
<div class="flex gap-1 text-xs text-error">
|
||||||
</div>
|
@if (!$server->settings->is_reachable)
|
||||||
@empty
|
<span>Not reachable</span>
|
||||||
<div>No deployments running.</div>
|
@endif
|
||||||
@endforelse
|
@if (!$server->settings->is_reachable && !$server->settings->is_usable)
|
||||||
</div>
|
&
|
||||||
@endif
|
@endif
|
||||||
<script>
|
@if (!$server->settings->is_usable)
|
||||||
function gotoProject(uuid, environment = 'production') {
|
<span>Not usable by Coolify</span>
|
||||||
window.location.href = '/project/' + uuid + '/' + environment;
|
@endif
|
||||||
}
|
</div>
|
||||||
</script>
|
</div>
|
||||||
{{-- <x-forms.button wire:click='getIptables'>Get IPTABLES</x-forms.button> --}}
|
<div class="flex-1"></div>
|
||||||
|
</a>
|
||||||
|
@empty
|
||||||
|
<div>
|
||||||
|
No servers found.
|
||||||
|
Add your first server <a class="text-white underline" href="{{ route('server.create') }}">here</a> or
|
||||||
|
go to the <a class="text-white underline" href="{{ route('onboarding') }}">onboarding page.</a>
|
||||||
|
</div>
|
||||||
|
@endforelse
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h3 class="py-4">Deployments</h3>
|
||||||
|
@if (count($deployments_per_server) > 0)
|
||||||
|
<x-loading />
|
||||||
|
@endif
|
||||||
|
<x-forms.button wire:click='cleanup_queue'>Cleanup Queues</x-forms.button>
|
||||||
|
</div>
|
||||||
|
<div wire:poll.1000ms="get_deployments" class="grid grid-cols-1">
|
||||||
|
@forelse ($deployments_per_server as $server_name => $deployments)
|
||||||
|
<h4 class="py-4">{{ $server_name }}</h4>
|
||||||
|
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3">
|
||||||
|
@foreach ($deployments as $deployment)
|
||||||
|
<a href="{{ data_get($deployment, 'deployment_url') }}" @class([
|
||||||
|
'gap-2 cursor-pointer box group border-l-2 border-dotted',
|
||||||
|
'border-coolgray-500' => data_get($deployment, 'status') === 'queued',
|
||||||
|
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
||||||
|
])>
|
||||||
|
<div class="flex flex-col mx-6">
|
||||||
|
<div class="font-bold text-white">
|
||||||
|
{{ data_get($deployment, 'application_name') }}
|
||||||
|
</div>
|
||||||
|
@if (data_get($deployment, 'pull_request_id') !== 0)
|
||||||
|
<div class="description">
|
||||||
|
PR #{{ data_get($deployment, 'pull_request_id') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
<div class="description">
|
||||||
|
{{ str(data_get($deployment, 'status'))->headline() }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1"></div>
|
||||||
|
</a>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@empty
|
||||||
|
<div>No deployments running.</div>
|
||||||
|
@endforelse
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function gotoProject(uuid, environment = 'production') {
|
||||||
|
window.location.href = '/project/' + uuid + '/' + environment;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{{-- <x-forms.button wire:click='getIptables'>Get IPTABLES</x-forms.button> --}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
<form class="flex flex-col gap-2 rounded" wire:submit='submit'>
|
<form class="flex flex-col gap-2 rounded" wire:submit='submit'>
|
||||||
<x-forms.input placeholder="NODE_ENV" id="key" label="Name" required />
|
<x-forms.input placeholder="NODE_ENV" id="key" label="Name" required />
|
||||||
<x-forms.input placeholder="production" id="value" label="Value" required />
|
<x-forms.textarea x-show="$wire.is_multiline === true" x-cloak id="value" label="Value" required />
|
||||||
|
<x-forms.input x-show="$wire.is_multiline === false" x-cloak placeholder="production" id="value" x-bind:label="$wire.is_multiline === false && 'Value'" required />
|
||||||
@if (data_get($parameters, 'application_uuid'))
|
@if (data_get($parameters, 'application_uuid'))
|
||||||
<x-forms.checkbox id="is_build_time" label="Build Variable?" />
|
<x-forms.checkbox id="is_build_time" label="Build Variable?" />
|
||||||
@endif
|
@endif
|
||||||
|
<x-forms.checkbox id="is_multiline" label="Is Multiline?" />
|
||||||
<x-forms.button type="submit" @click="slideOverOpen=false">
|
<x-forms.button type="submit" @click="slideOverOpen=false">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
|
@ -20,10 +20,17 @@ class="flex flex-col gap-2 p-4 m-2 border lg:items-center border-coolgray-300 lg
|
|||||||
<x-forms.checkbox instantSave id="env.is_build_time" label="Build Variable?" />
|
<x-forms.checkbox instantSave id="env.is_build_time" label="Build Variable?" />
|
||||||
@endif
|
@endif
|
||||||
@else
|
@else
|
||||||
<x-forms.input id="env.key" />
|
@if ($env->is_multiline)
|
||||||
<x-forms.input type="password" id="env.value" />
|
<x-forms.input isMultiline="{{ $env->is_multiline }}" id="env.key" />
|
||||||
|
<x-forms.textarea type="password" id="env.value" />
|
||||||
|
@else
|
||||||
|
<x-forms.input id="env.key" />
|
||||||
|
<x-forms.input type="password" id="env.value" />
|
||||||
|
@endif
|
||||||
@if ($env->is_shared)
|
@if ($env->is_shared)
|
||||||
<x-forms.input disabled type="password" id="env.real_value" />
|
<x-forms.input disabled type="password" id="env.real_value" />
|
||||||
|
@else
|
||||||
|
<x-forms.checkbox instantSave id="env.is_multiline" label="Is Multiline?" />
|
||||||
@endif
|
@endif
|
||||||
@if ($type !== 'service' && !$isSharedVariable)
|
@if ($type !== 'service' && !$isSharedVariable)
|
||||||
<x-forms.checkbox instantSave id="env.is_build_time" label="Build Variable?" />
|
<x-forms.checkbox instantSave id="env.is_build_time" label="Build Variable?" />
|
||||||
|
@ -7,16 +7,18 @@
|
|||||||
<div class="pt-2" wire:loading wire:target="loadContainers">
|
<div class="pt-2" wire:loading wire:target="loadContainers">
|
||||||
Loading containers...
|
Loading containers...
|
||||||
</div>
|
</div>
|
||||||
@foreach ($servers as $server)
|
@forelse ($servers as $server)
|
||||||
<h3 x-init="$wire.loadContainers({{ $server->id }})"></h3>
|
<h3 x-init="$wire.loadContainers({{ $server->id }})"></h3>
|
||||||
<div wire:loading.remove wire:target="loadContainers">
|
<div wire:loading.remove wire:target="loadContainers">
|
||||||
@forelse (data_get($server,'containers',[]) as $container)
|
@forelse (data_get($server,'containers',[]) as $container)
|
||||||
<livewire:project.shared.get-logs :server="$server" :resource="$resource" :container="data_get($container,'Names')" />
|
<livewire:project.shared.get-logs :server="$server" :resource="$resource" :container="data_get($container, 'Names')" />
|
||||||
@empty
|
@empty
|
||||||
<div class="pt-2">No containers are not running on server: {{$server->name}}</div>
|
<div class="pt-2">No containers are not running on server: {{ $server->name }}</div>
|
||||||
@endforelse
|
@endforelse
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@empty
|
||||||
|
<div>No functional server found for the application.</div>
|
||||||
|
@endforelse
|
||||||
</div>
|
</div>
|
||||||
@elseif ($type === 'database')
|
@elseif ($type === 'database')
|
||||||
<h1>Logs</h1>
|
<h1>Logs</h1>
|
||||||
@ -26,7 +28,11 @@
|
|||||||
@if ($loop->first)
|
@if ($loop->first)
|
||||||
<h2 class="pb-4">Logs</h2>
|
<h2 class="pb-4">Logs</h2>
|
||||||
@endif
|
@endif
|
||||||
<livewire:project.shared.get-logs :server="$servers[0]" :resource="$resource" :container="$container" />
|
@if (data_get($servers, '0'))
|
||||||
|
<livewire:project.shared.get-logs :server="data_get($servers, '0')" :resource="$resource" :container="$container" />
|
||||||
|
@else
|
||||||
|
<div> No functional server found for the database.</div>
|
||||||
|
@endif
|
||||||
@empty
|
@empty
|
||||||
<div class="pt-2">No containers are not running.</div>
|
<div class="pt-2">No containers are not running.</div>
|
||||||
@endforelse
|
@endforelse
|
||||||
@ -37,7 +43,11 @@
|
|||||||
@if ($loop->first)
|
@if ($loop->first)
|
||||||
<h2 class="pb-4">Logs</h2>
|
<h2 class="pb-4">Logs</h2>
|
||||||
@endif
|
@endif
|
||||||
<livewire:project.shared.get-logs :server="$servers[0]" :resource="$resource" :container="$container" />
|
@if (data_get($servers, '0'))
|
||||||
|
<livewire:project.shared.get-logs :server="data_get($servers, '0')" :resource="$resource" :container="$container" />
|
||||||
|
@else
|
||||||
|
<div> No functional server found for the service.</div>
|
||||||
|
@endif
|
||||||
@empty
|
@empty
|
||||||
<div class="pt-2">No containers are not running.</div>
|
<div class="pt-2">No containers are not running.</div>
|
||||||
@endforelse
|
@endforelse
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
# tags: firebase, alternative, open-source
|
# tags: firebase, alternative, open-source
|
||||||
# minversion: 4.0.0-beta.228
|
# minversion: 4.0.0-beta.228
|
||||||
# logo: svgs/supabase.svg
|
# logo: svgs/supabase.svg
|
||||||
|
# port: 8000
|
||||||
|
|
||||||
services:
|
services:
|
||||||
supabase-kong:
|
supabase-kong:
|
||||||
@ -13,7 +14,7 @@ services:
|
|||||||
supabase-analytics:
|
supabase-analytics:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
- SERVICE_FQDN_SUPABASE
|
- SERVICE_FQDN_SUPABASE_8000
|
||||||
- JWT_SERCET=${SERVICE_PASSWORD_JWT}
|
- JWT_SERCET=${SERVICE_PASSWORD_JWT}
|
||||||
- KONG_DATABASE=off
|
- KONG_DATABASE=off
|
||||||
- KONG_DECLARATIVE_CONFIG=/home/kong/kong.yml
|
- KONG_DECLARATIVE_CONFIG=/home/kong/kong.yml
|
||||||
@ -202,8 +203,8 @@ services:
|
|||||||
|
|
||||||
## Edge Functions routes
|
## Edge Functions routes
|
||||||
- name: functions-v1
|
- name: functions-v1
|
||||||
_comment: 'Edge Functions: /functions/v1/* -> http://functions:9000/*'
|
_comment: 'Edge Functions: /functions/v1/* -> http://supabase-edge-functions:9000/*'
|
||||||
url: http://functions:9000/
|
url: http://supabase-edge-functions:9000/
|
||||||
routes:
|
routes:
|
||||||
- name: functions-v1-all
|
- name: functions-v1-all
|
||||||
strip_path: true
|
strip_path: true
|
||||||
@ -256,7 +257,7 @@ services:
|
|||||||
config:
|
config:
|
||||||
hide_credentials: true
|
hide_credentials: true
|
||||||
supabase-studio:
|
supabase-studio:
|
||||||
image: supabase/studio:20240205-b145c86
|
image: supabase/studio:20240301-0942bfe
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test:
|
test:
|
||||||
[
|
[
|
||||||
@ -280,7 +281,7 @@ services:
|
|||||||
- DEFAULT_PROJECT_NAME=${STUDIO_DEFAULT_PROJECT:-Default Project}
|
- DEFAULT_PROJECT_NAME=${STUDIO_DEFAULT_PROJECT:-Default Project}
|
||||||
|
|
||||||
- SUPABASE_URL=http://supabase-kong:8000
|
- SUPABASE_URL=http://supabase-kong:8000
|
||||||
- SUPABASE_PUBLIC_URL=${SERVICE_FQDN_SUPABASE}
|
- SUPABASE_PUBLIC_URL=${SERVICE_FQDN_SUPABASE_8000}
|
||||||
- SUPABASE_ANON_KEY=${SERVICE_SUPABASEANON_KEY}
|
- SUPABASE_ANON_KEY=${SERVICE_SUPABASEANON_KEY}
|
||||||
- SUPABASE_SERVICE_KEY=${SERVICE_SUPABASESERVICE_KEY}
|
- SUPABASE_SERVICE_KEY=${SERVICE_SUPABASESERVICE_KEY}
|
||||||
|
|
||||||
@ -663,7 +664,7 @@ services:
|
|||||||
kong: 'starts_with(string!(.appname), "supabase-kong")'
|
kong: 'starts_with(string!(.appname), "supabase-kong")'
|
||||||
auth: 'starts_with(string!(.appname), "supabase-auth")'
|
auth: 'starts_with(string!(.appname), "supabase-auth")'
|
||||||
rest: 'starts_with(string!(.appname), "supabase-rest")'
|
rest: 'starts_with(string!(.appname), "supabase-rest")'
|
||||||
realtime: 'starts_with(string!(.appname), "supabase-realtime")'
|
realtime: 'starts_with(string!(.appname), "realtime-dev.supabase-realtime")'
|
||||||
storage: 'starts_with(string!(.appname), "supabase-storage")'
|
storage: 'starts_with(string!(.appname), "supabase-storage")'
|
||||||
functions: 'starts_with(string!(.appname), "supabase-functions")'
|
functions: 'starts_with(string!(.appname), "supabase-functions")'
|
||||||
db: 'starts_with(string!(.appname), "supabase-db")'
|
db: 'starts_with(string!(.appname), "supabase-db")'
|
||||||
@ -885,7 +886,7 @@ services:
|
|||||||
- PGRST_APP_SETTINGS_JWT_EXP=${JWT_EXPIRY:-3600}
|
- PGRST_APP_SETTINGS_JWT_EXP=${JWT_EXPIRY:-3600}
|
||||||
command: "postgrest"
|
command: "postgrest"
|
||||||
supabase-auth:
|
supabase-auth:
|
||||||
image: supabase/gotrue:v2.132.3
|
image: supabase/gotrue:v2.143.0
|
||||||
depends_on:
|
depends_on:
|
||||||
supabase-db:
|
supabase-db:
|
||||||
# Disable this if you are using an external Postgres database
|
# Disable this if you are using an external Postgres database
|
||||||
@ -913,7 +914,7 @@ services:
|
|||||||
- GOTRUE_DB_DRIVER=postgres
|
- GOTRUE_DB_DRIVER=postgres
|
||||||
- GOTRUE_DB_DATABASE_URL=postgres://supabase_auth_admin:${SERVICE_PASSWORD_POSTGRES}@${POSTGRES_HOST:-supabase-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-supabase}
|
- GOTRUE_DB_DATABASE_URL=postgres://supabase_auth_admin:${SERVICE_PASSWORD_POSTGRES}@${POSTGRES_HOST:-supabase-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-supabase}
|
||||||
|
|
||||||
- GOTRUE_SITE_URL=${SERVICE_FQDN_SUPABASE}
|
- GOTRUE_SITE_URL=${SERVICE_FQDN_SUPABASE_8000}
|
||||||
- GOTRUE_URI_ALLOW_LIST=${ADDITIONAL_REDIRECT_URLS}
|
- GOTRUE_URI_ALLOW_LIST=${ADDITIONAL_REDIRECT_URLS}
|
||||||
- GOTRUE_DISABLE_SIGNUP=${DISABLE_SIGNUP:-false}
|
- GOTRUE_DISABLE_SIGNUP=${DISABLE_SIGNUP:-false}
|
||||||
|
|
||||||
@ -937,12 +938,23 @@ services:
|
|||||||
- GOTRUE_MAILER_URLPATHS_CONFIRMATION=${MAILER_URLPATHS_CONFIRMATION:-/auth/v1/verify}
|
- GOTRUE_MAILER_URLPATHS_CONFIRMATION=${MAILER_URLPATHS_CONFIRMATION:-/auth/v1/verify}
|
||||||
- GOTRUE_MAILER_URLPATHS_RECOVERY=${MAILER_URLPATHS_RECOVERY:-/auth/v1/verify}
|
- GOTRUE_MAILER_URLPATHS_RECOVERY=${MAILER_URLPATHS_RECOVERY:-/auth/v1/verify}
|
||||||
- GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE=${MAILER_URLPATHS_EMAIL_CHANGE:-/auth/v1/verify}
|
- GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE=${MAILER_URLPATHS_EMAIL_CHANGE:-/auth/v1/verify}
|
||||||
|
- GOTRUE_MAILER_TEMPLATES_INVITE=${MAILER_TEMPLATES_INVITE}
|
||||||
|
- GOTRUE_MAILER_TEMPLATES_CONFIRMATION=${MAILER_TEMPLATES_CONFIRMATION}
|
||||||
|
- GOTRUE_MAILER_TEMPLATES_RECOVERY=${MAILER_TEMPLATES_RECOVERY}
|
||||||
|
- GOTRUE_MAILER_TEMPLATES_MAGIC_LINK=${MAILER_TEMPLATES_MAGIC_LINK}
|
||||||
|
- GOTRUE_MAILER_TEMPLATES_EMAIL_CHANGE=${MAILER_TEMPLATES_EMAIL_CHANGE}
|
||||||
|
|
||||||
|
- GOTRUE_MAILER_SUBJECTS_CONFIRMATION=${MAILER_SUBJECTS_CONFIRMATION}
|
||||||
|
- GOTRUE_MAILER_SUBJECTS_RECOVERY=${MAILER_SUBJECTS_RECOVERY}
|
||||||
|
- GOTRUE_MAILER_SUBJECTS_MAGIC_LINK=${MAILER_SUBJECTS_MAGIC_LINK}
|
||||||
|
- GOTRUE_MAILER_SUBJECTS_EMAIL_CHANGE=${MAILER_SUBJECTS_EMAIL_CHANGE}
|
||||||
|
- GOTRUE_MAILER_SUBJECTS_INVITE=${MAILER_SUBJECTS_INVITE}
|
||||||
|
|
||||||
- GOTRUE_EXTERNAL_PHONE_ENABLED=${ENABLE_PHONE_SIGNUP:-true}
|
- GOTRUE_EXTERNAL_PHONE_ENABLED=${ENABLE_PHONE_SIGNUP:-true}
|
||||||
- GOTRUE_SMS_AUTOCONFIRM=${ENABLE_PHONE_AUTOCONFIRM:-true}
|
- GOTRUE_SMS_AUTOCONFIRM=${ENABLE_PHONE_AUTOCONFIRM:-true}
|
||||||
supabase-realtime:
|
realtime-dev.supabase-realtime:
|
||||||
# This container name looks inconsistent but is correct because realtime constructs tenant id by parsing the subdomain
|
# This container name looks inconsistent but is correct because realtime constructs tenant id by parsing the subdomain
|
||||||
image: supabase/realtime:v2.25.50
|
image: supabase/realtime:v2.25.66
|
||||||
depends_on:
|
depends_on:
|
||||||
supabase-db:
|
supabase-db:
|
||||||
# Disable this if you are using an external Postgres database
|
# Disable this if you are using an external Postgres database
|
||||||
@ -961,7 +973,7 @@ services:
|
|||||||
- DB_USER=supabase_admin
|
- DB_USER=supabase_admin
|
||||||
- DB_PASSWORD=${SERVICE_PASSWORD_POSTGRES}
|
- DB_PASSWORD=${SERVICE_PASSWORD_POSTGRES}
|
||||||
- DB_NAME=${POSTGRES_DB:-supabase}
|
- DB_NAME=${POSTGRES_DB:-supabase}
|
||||||
- DB_AFTER_CONNECT_QUERY='SET search_path TO _realtime'
|
- DB_AFTER_CONNECT_QUERY=SET search_path TO _realtime
|
||||||
- DB_ENC_KEY=supabaserealtime
|
- DB_ENC_KEY=supabaserealtime
|
||||||
- API_JWT_SECRET=${SERVICE_PASSWORD_JWT}
|
- API_JWT_SECRET=${SERVICE_PASSWORD_JWT}
|
||||||
- FLY_ALLOC_ID=fly123
|
- FLY_ALLOC_ID=fly123
|
||||||
@ -1091,7 +1103,7 @@ services:
|
|||||||
- ./volumes/storage:/var/lib/storage
|
- ./volumes/storage:/var/lib/storage
|
||||||
|
|
||||||
supabase-meta:
|
supabase-meta:
|
||||||
image: supabase/postgres-meta:v0.77.2
|
image: supabase/postgres-meta:v0.79.0
|
||||||
depends_on:
|
depends_on:
|
||||||
supabase-db:
|
supabase-db:
|
||||||
# Disable this if you are using an external Postgres database
|
# Disable this if you are using an external Postgres database
|
||||||
@ -1107,7 +1119,7 @@ services:
|
|||||||
- PG_META_DB_PASSWORD=${SERVICE_PASSWORD_POSTGRES}
|
- PG_META_DB_PASSWORD=${SERVICE_PASSWORD_POSTGRES}
|
||||||
|
|
||||||
supabase-edge-functions:
|
supabase-edge-functions:
|
||||||
image: supabase/edge-runtime:v1.36.1
|
image: supabase/edge-runtime:v1.38.0
|
||||||
depends_on:
|
depends_on:
|
||||||
supabase-analytics:
|
supabase-analytics:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
@ -8,7 +8,7 @@ services:
|
|||||||
uptime-kuma:
|
uptime-kuma:
|
||||||
image: louislam/uptime-kuma:1
|
image: louislam/uptime-kuma:1
|
||||||
environment:
|
environment:
|
||||||
- SERVICE_FQDN_3001
|
- SERVICE_FQDN_UPTIME-KUMA_3001
|
||||||
volumes:
|
volumes:
|
||||||
- uptime-kuma:/app/data
|
- uptime-kuma:/app/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
File diff suppressed because one or more lines are too long
@ -4,7 +4,7 @@
|
|||||||
"version": "3.12.36"
|
"version": "3.12.36"
|
||||||
},
|
},
|
||||||
"v4": {
|
"v4": {
|
||||||
"version": "4.0.0-beta.239"
|
"version": "4.0.0-beta.240"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user