Merge remote-tracking branch 'origin/next' into fix/database-import-modal-not-closing-v2
This commit is contained in:
commit
db55c8160a
38 changed files with 364 additions and 17 deletions
|
|
@ -51,9 +51,11 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St
|
|||
}
|
||||
|
||||
$configuration_dir = database_proxy_dir($database->uuid);
|
||||
$host_configuration_dir = $configuration_dir;
|
||||
if (isDev()) {
|
||||
$configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$database->uuid.'/proxy';
|
||||
$host_configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$database->uuid.'/proxy';
|
||||
}
|
||||
$timeoutConfig = $this->buildProxyTimeoutConfig($database->public_port_timeout);
|
||||
$nginxconf = <<<EOF
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
|
@ -67,6 +69,7 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St
|
|||
server {
|
||||
listen $database->public_port;
|
||||
proxy_pass $containerName:$internalPort;
|
||||
$timeoutConfig
|
||||
}
|
||||
}
|
||||
EOF;
|
||||
|
|
@ -85,7 +88,7 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St
|
|||
'volumes' => [
|
||||
[
|
||||
'type' => 'bind',
|
||||
'source' => "$configuration_dir/nginx.conf",
|
||||
'source' => "$host_configuration_dir/nginx.conf",
|
||||
'target' => '/etc/nginx/nginx.conf',
|
||||
],
|
||||
],
|
||||
|
|
@ -160,4 +163,13 @@ private function isNonTransientError(string $message): bool
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function buildProxyTimeoutConfig(?int $timeout): string
|
||||
{
|
||||
if ($timeout === null || $timeout < 1) {
|
||||
$timeout = 3600;
|
||||
}
|
||||
|
||||
return "proxy_timeout {$timeout}s;";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -805,9 +805,15 @@ private function deploy_docker_compose_buildpack()
|
|||
);
|
||||
|
||||
$this->write_deployment_configurations();
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, "cd {$this->basedir} && {$start_command}"), 'hidden' => true],
|
||||
);
|
||||
if ($this->preserveRepository) {
|
||||
$this->execute_remote_command(
|
||||
['command' => "cd {$server_workdir} && {$start_command}", 'hidden' => true],
|
||||
);
|
||||
} else {
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, "cd {$this->basedir} && {$start_command}"), 'hidden' => true],
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$command = "{$this->coolify_variables} docker compose";
|
||||
if ($this->preserveRepository) {
|
||||
|
|
|
|||
|
|
@ -51,9 +51,7 @@ public function mount()
|
|||
$this->environment = $environment;
|
||||
$this->application = $application;
|
||||
|
||||
if ($this->application->deploymentType() === 'deploy_key' && $this->currentRoute === 'project.application.preview-deployments') {
|
||||
return redirect()->route('project.application.configuration', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]);
|
||||
}
|
||||
|
||||
|
||||
if ($this->application->build_pack === 'dockercompose' && $this->currentRoute === 'project.application.healthcheck') {
|
||||
return redirect()->route('project.application.configuration', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ class General extends Component
|
|||
|
||||
public ?int $publicPort = null;
|
||||
|
||||
public ?int $publicPortTimeout = 3600;
|
||||
|
||||
public ?string $customDockerRunOptions = null;
|
||||
|
||||
public ?string $dbUrl = null;
|
||||
|
|
@ -80,6 +82,7 @@ protected function rules(): array
|
|||
'portsMappings' => 'nullable|string',
|
||||
'isPublic' => 'nullable|boolean',
|
||||
'publicPort' => 'nullable|integer',
|
||||
'publicPortTimeout' => 'nullable|integer|min:1',
|
||||
'customDockerRunOptions' => 'nullable|string',
|
||||
'dbUrl' => 'nullable|string',
|
||||
'dbUrlPublic' => 'nullable|string',
|
||||
|
|
@ -99,6 +102,8 @@ protected function messages(): array
|
|||
'image.required' => 'The Docker Image field is required.',
|
||||
'image.string' => 'The Docker Image must be a string.',
|
||||
'publicPort.integer' => 'The Public Port must be an integer.',
|
||||
'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.',
|
||||
'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
@ -115,6 +120,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->database->ports_mappings = $this->portsMappings;
|
||||
$this->database->is_public = $this->isPublic;
|
||||
$this->database->public_port = $this->publicPort;
|
||||
$this->database->public_port_timeout = $this->publicPortTimeout;
|
||||
$this->database->custom_docker_run_options = $this->customDockerRunOptions;
|
||||
$this->database->is_log_drain_enabled = $this->isLogDrainEnabled;
|
||||
$this->database->save();
|
||||
|
|
@ -130,6 +136,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->portsMappings = $this->database->ports_mappings;
|
||||
$this->isPublic = $this->database->is_public;
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->dbUrl = $this->database->internal_db_url;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ class General extends Component
|
|||
|
||||
public ?int $publicPort = null;
|
||||
|
||||
public ?int $publicPortTimeout = 3600;
|
||||
|
||||
public ?string $customDockerRunOptions = null;
|
||||
|
||||
public ?string $dbUrl = null;
|
||||
|
|
@ -91,6 +93,7 @@ protected function rules(): array
|
|||
'portsMappings' => 'nullable|string',
|
||||
'isPublic' => 'nullable|boolean',
|
||||
'publicPort' => 'nullable|integer',
|
||||
'publicPortTimeout' => 'nullable|integer|min:1',
|
||||
'customDockerRunOptions' => 'nullable|string',
|
||||
'dbUrl' => 'nullable|string',
|
||||
'dbUrlPublic' => 'nullable|string',
|
||||
|
|
@ -109,6 +112,8 @@ protected function messages(): array
|
|||
'image.required' => 'The Docker Image field is required.',
|
||||
'image.string' => 'The Docker Image must be a string.',
|
||||
'publicPort.integer' => 'The Public Port must be an integer.',
|
||||
'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.',
|
||||
'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
@ -124,6 +129,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->database->ports_mappings = $this->portsMappings;
|
||||
$this->database->is_public = $this->isPublic;
|
||||
$this->database->public_port = $this->publicPort;
|
||||
$this->database->public_port_timeout = $this->publicPortTimeout;
|
||||
$this->database->custom_docker_run_options = $this->customDockerRunOptions;
|
||||
$this->database->is_log_drain_enabled = $this->isLogDrainEnabled;
|
||||
$this->database->enable_ssl = $this->enable_ssl;
|
||||
|
|
@ -139,6 +145,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->portsMappings = $this->database->ports_mappings;
|
||||
$this->isPublic = $this->database->is_public;
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->enable_ssl = $this->database->enable_ssl;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ class General extends Component
|
|||
|
||||
public ?int $publicPort = null;
|
||||
|
||||
public ?int $publicPortTimeout = 3600;
|
||||
|
||||
public ?string $customDockerRunOptions = null;
|
||||
|
||||
public ?string $dbUrl = null;
|
||||
|
|
@ -94,6 +96,7 @@ protected function rules(): array
|
|||
'portsMappings' => 'nullable|string',
|
||||
'isPublic' => 'nullable|boolean',
|
||||
'publicPort' => 'nullable|integer',
|
||||
'publicPortTimeout' => 'nullable|integer|min:1',
|
||||
'customDockerRunOptions' => 'nullable|string',
|
||||
'dbUrl' => 'nullable|string',
|
||||
'dbUrlPublic' => 'nullable|string',
|
||||
|
|
@ -114,6 +117,8 @@ protected function messages(): array
|
|||
'image.required' => 'The Docker Image field is required.',
|
||||
'image.string' => 'The Docker Image must be a string.',
|
||||
'publicPort.integer' => 'The Public Port must be an integer.',
|
||||
'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.',
|
||||
'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
@ -130,6 +135,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->database->ports_mappings = $this->portsMappings;
|
||||
$this->database->is_public = $this->isPublic;
|
||||
$this->database->public_port = $this->publicPort;
|
||||
$this->database->public_port_timeout = $this->publicPortTimeout;
|
||||
$this->database->custom_docker_run_options = $this->customDockerRunOptions;
|
||||
$this->database->is_log_drain_enabled = $this->isLogDrainEnabled;
|
||||
$this->database->enable_ssl = $this->enable_ssl;
|
||||
|
|
@ -146,6 +152,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->portsMappings = $this->database->ports_mappings;
|
||||
$this->isPublic = $this->database->is_public;
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->enable_ssl = $this->database->enable_ssl;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ class General extends Component
|
|||
|
||||
public ?int $publicPort = null;
|
||||
|
||||
public ?int $publicPortTimeout = 3600;
|
||||
|
||||
public bool $isLogDrainEnabled = false;
|
||||
|
||||
public ?string $customDockerRunOptions = null;
|
||||
|
|
@ -79,6 +81,7 @@ protected function rules(): array
|
|||
'portsMappings' => 'nullable',
|
||||
'isPublic' => 'nullable|boolean',
|
||||
'publicPort' => 'nullable|integer',
|
||||
'publicPortTimeout' => 'nullable|integer|min:1',
|
||||
'isLogDrainEnabled' => 'nullable|boolean',
|
||||
'customDockerRunOptions' => 'nullable',
|
||||
'enableSsl' => 'boolean',
|
||||
|
|
@ -97,6 +100,8 @@ protected function messages(): array
|
|||
'mariadbDatabase.required' => 'The MariaDB Database field is required.',
|
||||
'image.required' => 'The Docker Image field is required.',
|
||||
'publicPort.integer' => 'The Public Port must be an integer.',
|
||||
'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.',
|
||||
'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
@ -113,6 +118,7 @@ protected function messages(): array
|
|||
'portsMappings' => 'Port Mapping',
|
||||
'isPublic' => 'Is Public',
|
||||
'publicPort' => 'Public Port',
|
||||
'publicPortTimeout' => 'Public Port Timeout',
|
||||
'customDockerRunOptions' => 'Custom Docker Options',
|
||||
'enableSsl' => 'Enable SSL',
|
||||
];
|
||||
|
|
@ -154,6 +160,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->database->ports_mappings = $this->portsMappings;
|
||||
$this->database->is_public = $this->isPublic;
|
||||
$this->database->public_port = $this->publicPort;
|
||||
$this->database->public_port_timeout = $this->publicPortTimeout;
|
||||
$this->database->is_log_drain_enabled = $this->isLogDrainEnabled;
|
||||
$this->database->custom_docker_run_options = $this->customDockerRunOptions;
|
||||
$this->database->enable_ssl = $this->enableSsl;
|
||||
|
|
@ -173,6 +180,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->portsMappings = $this->database->ports_mappings;
|
||||
$this->isPublic = $this->database->is_public;
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->enableSsl = $this->database->enable_ssl;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ class General extends Component
|
|||
|
||||
public ?int $publicPort = null;
|
||||
|
||||
public ?int $publicPortTimeout = 3600;
|
||||
|
||||
public bool $isLogDrainEnabled = false;
|
||||
|
||||
public ?string $customDockerRunOptions = null;
|
||||
|
|
@ -78,6 +80,7 @@ protected function rules(): array
|
|||
'portsMappings' => 'nullable',
|
||||
'isPublic' => 'nullable|boolean',
|
||||
'publicPort' => 'nullable|integer',
|
||||
'publicPortTimeout' => 'nullable|integer|min:1',
|
||||
'isLogDrainEnabled' => 'nullable|boolean',
|
||||
'customDockerRunOptions' => 'nullable',
|
||||
'enableSsl' => 'boolean',
|
||||
|
|
@ -96,6 +99,8 @@ protected function messages(): array
|
|||
'mongoInitdbDatabase.required' => 'The MongoDB Database field is required.',
|
||||
'image.required' => 'The Docker Image field is required.',
|
||||
'publicPort.integer' => 'The Public Port must be an integer.',
|
||||
'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.',
|
||||
'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.',
|
||||
'sslMode.in' => 'The SSL Mode must be one of: allow, prefer, require, verify-full.',
|
||||
]
|
||||
);
|
||||
|
|
@ -112,6 +117,7 @@ protected function messages(): array
|
|||
'portsMappings' => 'Port Mapping',
|
||||
'isPublic' => 'Is Public',
|
||||
'publicPort' => 'Public Port',
|
||||
'publicPortTimeout' => 'Public Port Timeout',
|
||||
'customDockerRunOptions' => 'Custom Docker Run Options',
|
||||
'enableSsl' => 'Enable SSL',
|
||||
'sslMode' => 'SSL Mode',
|
||||
|
|
@ -153,6 +159,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->database->ports_mappings = $this->portsMappings;
|
||||
$this->database->is_public = $this->isPublic;
|
||||
$this->database->public_port = $this->publicPort;
|
||||
$this->database->public_port_timeout = $this->publicPortTimeout;
|
||||
$this->database->is_log_drain_enabled = $this->isLogDrainEnabled;
|
||||
$this->database->custom_docker_run_options = $this->customDockerRunOptions;
|
||||
$this->database->enable_ssl = $this->enableSsl;
|
||||
|
|
@ -172,6 +179,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->portsMappings = $this->database->ports_mappings;
|
||||
$this->isPublic = $this->database->is_public;
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->enableSsl = $this->database->enable_ssl;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ class General extends Component
|
|||
|
||||
public ?int $publicPort = null;
|
||||
|
||||
public ?int $publicPortTimeout = 3600;
|
||||
|
||||
public bool $isLogDrainEnabled = false;
|
||||
|
||||
public ?string $customDockerRunOptions = null;
|
||||
|
|
@ -81,6 +83,7 @@ protected function rules(): array
|
|||
'portsMappings' => 'nullable',
|
||||
'isPublic' => 'nullable|boolean',
|
||||
'publicPort' => 'nullable|integer',
|
||||
'publicPortTimeout' => 'nullable|integer|min:1',
|
||||
'isLogDrainEnabled' => 'nullable|boolean',
|
||||
'customDockerRunOptions' => 'nullable',
|
||||
'enableSsl' => 'boolean',
|
||||
|
|
@ -100,6 +103,8 @@ protected function messages(): array
|
|||
'mysqlDatabase.required' => 'The MySQL Database field is required.',
|
||||
'image.required' => 'The Docker Image field is required.',
|
||||
'publicPort.integer' => 'The Public Port must be an integer.',
|
||||
'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.',
|
||||
'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.',
|
||||
'sslMode.in' => 'The SSL Mode must be one of: PREFERRED, REQUIRED, VERIFY_CA, VERIFY_IDENTITY.',
|
||||
]
|
||||
);
|
||||
|
|
@ -117,6 +122,7 @@ protected function messages(): array
|
|||
'portsMappings' => 'Port Mapping',
|
||||
'isPublic' => 'Is Public',
|
||||
'publicPort' => 'Public Port',
|
||||
'publicPortTimeout' => 'Public Port Timeout',
|
||||
'customDockerRunOptions' => 'Custom Docker Run Options',
|
||||
'enableSsl' => 'Enable SSL',
|
||||
'sslMode' => 'SSL Mode',
|
||||
|
|
@ -159,6 +165,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->database->ports_mappings = $this->portsMappings;
|
||||
$this->database->is_public = $this->isPublic;
|
||||
$this->database->public_port = $this->publicPort;
|
||||
$this->database->public_port_timeout = $this->publicPortTimeout;
|
||||
$this->database->is_log_drain_enabled = $this->isLogDrainEnabled;
|
||||
$this->database->custom_docker_run_options = $this->customDockerRunOptions;
|
||||
$this->database->enable_ssl = $this->enableSsl;
|
||||
|
|
@ -179,6 +186,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->portsMappings = $this->database->ports_mappings;
|
||||
$this->isPublic = $this->database->is_public;
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->enableSsl = $this->database->enable_ssl;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ class General extends Component
|
|||
|
||||
public ?int $publicPort = null;
|
||||
|
||||
public ?int $publicPortTimeout = 3600;
|
||||
|
||||
public bool $isLogDrainEnabled = false;
|
||||
|
||||
public ?string $customDockerRunOptions = null;
|
||||
|
|
@ -93,6 +95,7 @@ protected function rules(): array
|
|||
'portsMappings' => 'nullable',
|
||||
'isPublic' => 'nullable|boolean',
|
||||
'publicPort' => 'nullable|integer',
|
||||
'publicPortTimeout' => 'nullable|integer|min:1',
|
||||
'isLogDrainEnabled' => 'nullable|boolean',
|
||||
'customDockerRunOptions' => 'nullable',
|
||||
'enableSsl' => 'boolean',
|
||||
|
|
@ -111,6 +114,8 @@ protected function messages(): array
|
|||
'postgresDb.required' => 'The Postgres Database field is required.',
|
||||
'image.required' => 'The Docker Image field is required.',
|
||||
'publicPort.integer' => 'The Public Port must be an integer.',
|
||||
'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.',
|
||||
'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.',
|
||||
'sslMode.in' => 'The SSL Mode must be one of: allow, prefer, require, verify-ca, verify-full.',
|
||||
]
|
||||
);
|
||||
|
|
@ -130,6 +135,7 @@ protected function messages(): array
|
|||
'portsMappings' => 'Port Mapping',
|
||||
'isPublic' => 'Is Public',
|
||||
'publicPort' => 'Public Port',
|
||||
'publicPortTimeout' => 'Public Port Timeout',
|
||||
'customDockerRunOptions' => 'Custom Docker Run Options',
|
||||
'enableSsl' => 'Enable SSL',
|
||||
'sslMode' => 'SSL Mode',
|
||||
|
|
@ -174,6 +180,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->database->ports_mappings = $this->portsMappings;
|
||||
$this->database->is_public = $this->isPublic;
|
||||
$this->database->public_port = $this->publicPort;
|
||||
$this->database->public_port_timeout = $this->publicPortTimeout;
|
||||
$this->database->is_log_drain_enabled = $this->isLogDrainEnabled;
|
||||
$this->database->custom_docker_run_options = $this->customDockerRunOptions;
|
||||
$this->database->enable_ssl = $this->enableSsl;
|
||||
|
|
@ -196,6 +203,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->portsMappings = $this->database->ports_mappings;
|
||||
$this->isPublic = $this->database->is_public;
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->enableSsl = $this->database->enable_ssl;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ class General extends Component
|
|||
|
||||
public ?int $publicPort = null;
|
||||
|
||||
public ?int $publicPortTimeout = 3600;
|
||||
|
||||
public bool $isLogDrainEnabled = false;
|
||||
|
||||
public ?string $customDockerRunOptions = null;
|
||||
|
|
@ -74,6 +76,7 @@ protected function rules(): array
|
|||
'portsMappings' => 'nullable',
|
||||
'isPublic' => 'nullable|boolean',
|
||||
'publicPort' => 'nullable|integer',
|
||||
'publicPortTimeout' => 'nullable|integer|min:1',
|
||||
'isLogDrainEnabled' => 'nullable|boolean',
|
||||
'customDockerRunOptions' => 'nullable',
|
||||
'redisUsername' => 'required',
|
||||
|
|
@ -90,6 +93,8 @@ protected function messages(): array
|
|||
'name.required' => 'The Name field is required.',
|
||||
'image.required' => 'The Docker Image field is required.',
|
||||
'publicPort.integer' => 'The Public Port must be an integer.',
|
||||
'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.',
|
||||
'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.',
|
||||
'redisUsername.required' => 'The Redis Username field is required.',
|
||||
'redisPassword.required' => 'The Redis Password field is required.',
|
||||
]
|
||||
|
|
@ -104,6 +109,7 @@ protected function messages(): array
|
|||
'portsMappings' => 'Port Mapping',
|
||||
'isPublic' => 'Is Public',
|
||||
'publicPort' => 'Public Port',
|
||||
'publicPortTimeout' => 'Public Port Timeout',
|
||||
'customDockerRunOptions' => 'Custom Docker Options',
|
||||
'redisUsername' => 'Redis Username',
|
||||
'redisPassword' => 'Redis Password',
|
||||
|
|
@ -143,6 +149,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->database->ports_mappings = $this->portsMappings;
|
||||
$this->database->is_public = $this->isPublic;
|
||||
$this->database->public_port = $this->publicPort;
|
||||
$this->database->public_port_timeout = $this->publicPortTimeout;
|
||||
$this->database->is_log_drain_enabled = $this->isLogDrainEnabled;
|
||||
$this->database->custom_docker_run_options = $this->customDockerRunOptions;
|
||||
$this->database->enable_ssl = $this->enableSsl;
|
||||
|
|
@ -158,6 +165,7 @@ public function syncData(bool $toModel = false)
|
|||
$this->portsMappings = $this->database->ports_mappings;
|
||||
$this->isPublic = $this->database->is_public;
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->enableSsl = $this->database->enable_ssl;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ class Index extends Component
|
|||
|
||||
public ?int $publicPort = null;
|
||||
|
||||
public ?int $publicPortTimeout = 3600;
|
||||
|
||||
public bool $isPublic = false;
|
||||
|
||||
public bool $isLogDrainEnabled = false;
|
||||
|
|
@ -90,6 +92,7 @@ class Index extends Component
|
|||
'image' => 'required',
|
||||
'excludeFromStatus' => 'required|boolean',
|
||||
'publicPort' => 'nullable|integer',
|
||||
'publicPortTimeout' => 'nullable|integer|min:1',
|
||||
'isPublic' => 'required|boolean',
|
||||
'isLogDrainEnabled' => 'required|boolean',
|
||||
// Application-specific rules
|
||||
|
|
@ -158,6 +161,7 @@ private function syncDatabaseData(bool $toModel = false): void
|
|||
$this->serviceDatabase->image = $this->image;
|
||||
$this->serviceDatabase->exclude_from_status = $this->excludeFromStatus;
|
||||
$this->serviceDatabase->public_port = $this->publicPort;
|
||||
$this->serviceDatabase->public_port_timeout = $this->publicPortTimeout;
|
||||
$this->serviceDatabase->is_public = $this->isPublic;
|
||||
$this->serviceDatabase->is_log_drain_enabled = $this->isLogDrainEnabled;
|
||||
} else {
|
||||
|
|
@ -166,6 +170,7 @@ private function syncDatabaseData(bool $toModel = false): void
|
|||
$this->image = $this->serviceDatabase->image;
|
||||
$this->excludeFromStatus = $this->serviceDatabase->exclude_from_status ?? false;
|
||||
$this->publicPort = $this->serviceDatabase->public_port;
|
||||
$this->publicPortTimeout = $this->serviceDatabase->public_port_timeout;
|
||||
$this->isPublic = $this->serviceDatabase->is_public ?? false;
|
||||
$this->isLogDrainEnabled = $this->serviceDatabase->is_log_drain_enabled ?? false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ class ServiceDatabase extends BaseModel
|
|||
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
'public_port_timeout' => 'integer',
|
||||
];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::deleting(function ($service) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ class StandaloneClickhouse extends BaseModel
|
|||
|
||||
protected $casts = [
|
||||
'clickhouse_password' => 'encrypted',
|
||||
'public_port_timeout' => 'integer',
|
||||
'restart_count' => 'integer',
|
||||
'last_restart_at' => 'datetime',
|
||||
'last_restart_type' => 'string',
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ class StandaloneDragonfly extends BaseModel
|
|||
|
||||
protected $casts = [
|
||||
'dragonfly_password' => 'encrypted',
|
||||
'public_port_timeout' => 'integer',
|
||||
'restart_count' => 'integer',
|
||||
'last_restart_at' => 'datetime',
|
||||
'last_restart_type' => 'string',
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ class StandaloneKeydb extends BaseModel
|
|||
|
||||
protected $casts = [
|
||||
'keydb_password' => 'encrypted',
|
||||
'public_port_timeout' => 'integer',
|
||||
'restart_count' => 'integer',
|
||||
'last_restart_at' => 'datetime',
|
||||
'last_restart_type' => 'string',
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ class StandaloneMariadb extends BaseModel
|
|||
|
||||
protected $casts = [
|
||||
'mariadb_password' => 'encrypted',
|
||||
'public_port_timeout' => 'integer',
|
||||
'restart_count' => 'integer',
|
||||
'last_restart_at' => 'datetime',
|
||||
'last_restart_type' => 'string',
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class StandaloneMongodb extends BaseModel
|
|||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
protected $casts = [
|
||||
'public_port_timeout' => 'integer',
|
||||
'restart_count' => 'integer',
|
||||
'last_restart_at' => 'datetime',
|
||||
'last_restart_type' => 'string',
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ class StandaloneMysql extends BaseModel
|
|||
protected $casts = [
|
||||
'mysql_password' => 'encrypted',
|
||||
'mysql_root_password' => 'encrypted',
|
||||
'public_port_timeout' => 'integer',
|
||||
'restart_count' => 'integer',
|
||||
'last_restart_at' => 'datetime',
|
||||
'last_restart_type' => 'string',
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ class StandalonePostgresql extends BaseModel
|
|||
protected $casts = [
|
||||
'init_scripts' => 'array',
|
||||
'postgres_password' => 'encrypted',
|
||||
'public_port_timeout' => 'integer',
|
||||
'restart_count' => 'integer',
|
||||
'last_restart_at' => 'datetime',
|
||||
'last_restart_type' => 'string',
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class StandaloneRedis extends BaseModel
|
|||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
protected $casts = [
|
||||
'public_port_timeout' => 'integer',
|
||||
'restart_count' => 'integer',
|
||||
'last_restart_at' => 'datetime',
|
||||
'last_restart_type' => 'string',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
<?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
|
||||
{
|
||||
$tables = [
|
||||
'standalone_postgresqls',
|
||||
'standalone_mysqls',
|
||||
'standalone_mariadbs',
|
||||
'standalone_redis',
|
||||
'standalone_mongodbs',
|
||||
'standalone_clickhouses',
|
||||
'standalone_keydbs',
|
||||
'standalone_dragonflies',
|
||||
'service_databases',
|
||||
];
|
||||
|
||||
foreach ($tables as $table) {
|
||||
if (Schema::hasTable($table) && !Schema::hasColumn($table, 'public_port_timeout')) {
|
||||
Schema::table($table, function (Blueprint $table) {
|
||||
$table->integer('public_port_timeout')->nullable()->default(3600)->after('public_port');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
$tables = [
|
||||
'standalone_postgresqls',
|
||||
'standalone_mysqls',
|
||||
'standalone_mariadbs',
|
||||
'standalone_redis',
|
||||
'standalone_mongodbs',
|
||||
'standalone_clickhouses',
|
||||
'standalone_keydbs',
|
||||
'standalone_dragonflies',
|
||||
'service_databases',
|
||||
];
|
||||
|
||||
foreach ($tables as $table) {
|
||||
if (Schema::hasTable($table) && Schema::hasColumn($table, 'public_port_timeout')) {
|
||||
Schema::table($table, function (Blueprint $table) {
|
||||
$table->dropColumn('public_port_timeout');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
href="{{ route('project.application.scheduled-tasks.show', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]) }}"><span class="menu-item-label">Scheduled Tasks</span></a>
|
||||
<a class="sub-menu-item" {{ wireNavigate() }} wire:current.exact="menu-item-active"
|
||||
href="{{ route('project.application.webhooks', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]) }}"><span class="menu-item-label">Webhooks</span></a>
|
||||
@if ($application->deploymentType() !== 'deploy_key')
|
||||
@if ($application->git_based())
|
||||
<a class="sub-menu-item" {{ wireNavigate() }} wire:current.exact="menu-item-active"
|
||||
href="{{ route('project.application.preview-deployments', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]) }}"><span class="menu-item-label">Preview Deployments</span></a>
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
<div class="pb-4">Code source of your application.</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
@if (!$privateKeyId)
|
||||
@if (blank($privateKeyId))
|
||||
<div>Currently connected source: <span
|
||||
class="font-bold text-warning">{{ data_get($application, 'source.name', 'No source connected') }}</span>
|
||||
</div>
|
||||
|
|
@ -44,7 +44,7 @@ class="font-bold text-warning">{{ data_get($application, 'source.name', 'No sour
|
|||
</div>
|
||||
</div>
|
||||
|
||||
@if ($privateKeyId)
|
||||
@if (filled($privateKeyId))
|
||||
<h3 class="pt-4">Deploy Key</h3>
|
||||
<div class="py-2 pt-4">Currently attached Private Key: <span
|
||||
class="dark:text-warning">{{ $privateKeyName }}</span>
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@
|
|||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port"
|
||||
canGate="update" :canResource="$database" />
|
||||
<x-forms.input placeholder="3600" disabled="{{ $isPublic }}" id="publicPortTimeout"
|
||||
label="Proxy Timeout (seconds)" helper="Timeout for the public TCP proxy connection in seconds. Default: 3600 (1 hour)." canGate="update" :canResource="$database" />
|
||||
</div>
|
||||
</form>
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@
|
|||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port"
|
||||
canGate="update" :canResource="$database" />
|
||||
<x-forms.input placeholder="3600" disabled="{{ $isPublic }}" id="publicPortTimeout"
|
||||
label="Proxy Timeout (seconds)" helper="Timeout for the public TCP proxy connection in seconds. Default: 3600 (1 hour)." canGate="update" :canResource="$database" />
|
||||
</div>
|
||||
</form>
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@
|
|||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port"
|
||||
canGate="update" :canResource="$database" />
|
||||
<x-forms.input placeholder="3600" disabled="{{ $isPublic }}" id="publicPortTimeout"
|
||||
label="Proxy Timeout (seconds)" helper="Timeout for the public TCP proxy connection in seconds. Default: 3600 (1 hour)." canGate="update" :canResource="$database" />
|
||||
</div>
|
||||
<x-forms.textarea
|
||||
helper="<a target='_blank' class='underline dark:text-white' href='https://raw.githubusercontent.com/Snapchat/KeyDB/unstable/keydb.conf'>KeyDB Default Configuration</a>"
|
||||
|
|
|
|||
|
|
@ -139,6 +139,8 @@
|
|||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}"
|
||||
id="publicPort" label="Public Port" canGate="update" :canResource="$database" />
|
||||
<x-forms.input placeholder="3600" disabled="{{ $isPublic }}" id="publicPortTimeout"
|
||||
label="Proxy Timeout (seconds)" helper="Timeout for the public TCP proxy connection in seconds. Default: 3600 (1 hour)." canGate="update" :canResource="$database" />
|
||||
</div>
|
||||
<x-forms.textarea label="Custom MariaDB Configuration" rows="10" id="mariadbConf"
|
||||
canGate="update" :canResource="$database" />
|
||||
|
|
|
|||
|
|
@ -153,6 +153,8 @@
|
|||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}"
|
||||
id="publicPort" label="Public Port" canGate="update" :canResource="$database" />
|
||||
<x-forms.input placeholder="3600" disabled="{{ $isPublic }}" id="publicPortTimeout"
|
||||
label="Proxy Timeout (seconds)" helper="Timeout for the public TCP proxy connection in seconds. Default: 3600 (1 hour)." canGate="update" :canResource="$database" />
|
||||
</div>
|
||||
<x-forms.textarea label="Custom MongoDB Configuration" rows="10" id="mongoConf"
|
||||
canGate="update" :canResource="$database" />
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@
|
|||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}"
|
||||
id="publicPort" label="Public Port" canGate="update" :canResource="$database" />
|
||||
<x-forms.input placeholder="3600" disabled="{{ $isPublic }}" id="publicPortTimeout"
|
||||
label="Proxy Timeout (seconds)" helper="Timeout for the public TCP proxy connection in seconds. Default: 3600 (1 hour)." canGate="update" :canResource="$database" />
|
||||
</div>
|
||||
<x-forms.textarea label="Custom Mysql Configuration" rows="10" id="mysqlConf" canGate="update" :canResource="$database" />
|
||||
<h3 class="pt-4">Advanced</h3>
|
||||
|
|
|
|||
|
|
@ -165,6 +165,8 @@
|
|||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort"
|
||||
label="Public Port" canGate="update" :canResource="$database" />
|
||||
<x-forms.input placeholder="3600" disabled="{{ $isPublic }}" id="publicPortTimeout"
|
||||
label="Proxy Timeout (seconds)" helper="Timeout for the public TCP proxy connection in seconds. Default: 3600 (1 hour)." canGate="update" :canResource="$database" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
|
|
|
|||
|
|
@ -134,6 +134,8 @@
|
|||
</div>
|
||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}"
|
||||
id="publicPort" label="Public Port" canGate="update" :canResource="$database" />
|
||||
<x-forms.input placeholder="3600" disabled="{{ $isPublic }}" id="publicPortTimeout"
|
||||
label="Proxy Timeout (seconds)" helper="Timeout for the public TCP proxy connection in seconds. Default: 3600 (1 hour)." canGate="update" :canResource="$database" />
|
||||
</div>
|
||||
<x-forms.textarea placeholder="# maxmemory 256mb
|
||||
# maxmemory-policy allkeys-lru
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
59
tests/Feature/ApplicationSourceLocalhostKeyTest.php
Normal file
59
tests/Feature/ApplicationSourceLocalhostKeyTest.php
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
use App\Livewire\Project\Application\Source;
|
||||
use App\Models\Application;
|
||||
use App\Models\Environment;
|
||||
use App\Models\PrivateKey;
|
||||
use App\Models\Project;
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Livewire\Livewire;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
$this->team = Team::factory()->create();
|
||||
$this->user = User::factory()->create();
|
||||
$this->team->members()->attach($this->user->id, ['role' => 'owner']);
|
||||
|
||||
$this->actingAs($this->user);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
$this->project = Project::factory()->create(['team_id' => $this->team->id]);
|
||||
$this->environment = Environment::factory()->create(['project_id' => $this->project->id]);
|
||||
});
|
||||
|
||||
describe('Application Source with localhost key (id=0)', function () {
|
||||
test('renders deploy key section when private_key_id is 0', function () {
|
||||
$privateKey = PrivateKey::create([
|
||||
'id' => 0,
|
||||
'name' => 'localhost',
|
||||
'private_key' => 'test-key-content',
|
||||
'team_id' => $this->team->id,
|
||||
]);
|
||||
|
||||
$application = Application::factory()->create([
|
||||
'environment_id' => $this->environment->id,
|
||||
'private_key_id' => 0,
|
||||
]);
|
||||
|
||||
Livewire::test(Source::class, ['application' => $application])
|
||||
->assertSuccessful()
|
||||
->assertSet('privateKeyId', 0)
|
||||
->assertSee('Deploy Key');
|
||||
});
|
||||
|
||||
test('shows no source connected section when private_key_id is null', function () {
|
||||
$application = Application::factory()->create([
|
||||
'environment_id' => $this->environment->id,
|
||||
'private_key_id' => null,
|
||||
]);
|
||||
|
||||
Livewire::test(Source::class, ['application' => $application])
|
||||
->assertSuccessful()
|
||||
->assertSet('privateKeyId', null)
|
||||
->assertDontSee('Deploy Key')
|
||||
->assertSee('No source connected');
|
||||
});
|
||||
});
|
||||
|
|
@ -43,3 +43,15 @@
|
|||
->and($method->invoke($action, 'network timeout'))->toBeFalse()
|
||||
->and($method->invoke($action, 'connection refused'))->toBeFalse();
|
||||
});
|
||||
|
||||
test('buildProxyTimeoutConfig normalizes invalid values to default', function (?int $input, string $expected) {
|
||||
$action = new StartDatabaseProxy;
|
||||
$method = new ReflectionMethod($action, 'buildProxyTimeoutConfig');
|
||||
|
||||
expect($method->invoke($action, $input))->toBe($expected);
|
||||
})->with([
|
||||
[null, 'proxy_timeout 3600s;'],
|
||||
[0, 'proxy_timeout 3600s;'],
|
||||
[-10, 'proxy_timeout 3600s;'],
|
||||
[120, 'proxy_timeout 120s;'],
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Test to verify that docker-compose custom start commands use the correct
|
||||
* execution context based on the preserveRepository setting.
|
||||
*
|
||||
* When preserveRepository is enabled, the compose file and .env file are
|
||||
* written to the host at /data/coolify/applications/{uuid}/. The start
|
||||
* command must run on the host (not inside the helper container) so it
|
||||
* can access these files.
|
||||
*
|
||||
* When preserveRepository is disabled, the files are inside the helper
|
||||
* container at /artifacts/{uuid}/, so the command must run inside the
|
||||
* container via executeInDocker().
|
||||
*
|
||||
* @see https://github.com/coollabsio/coolify/issues/8417
|
||||
*/
|
||||
it('generates host command (not executeInDocker) when preserveRepository is true', function () {
|
||||
$deploymentUuid = 'test-deployment-uuid';
|
||||
$serverWorkdir = '/data/coolify/applications/app-uuid';
|
||||
$basedir = '/artifacts/test-deployment-uuid';
|
||||
$preserveRepository = true;
|
||||
|
||||
$startCommand = 'docker compose -f /data/coolify/applications/app-uuid/compose.yml --env-file /data/coolify/applications/app-uuid/.env --profile all up -d';
|
||||
|
||||
// Simulate the logic from ApplicationDeploymentJob::deploy_docker_compose_buildpack()
|
||||
if ($preserveRepository) {
|
||||
$command = "cd {$serverWorkdir} && {$startCommand}";
|
||||
} else {
|
||||
$command = executeInDocker($deploymentUuid, "cd {$basedir} && {$startCommand}");
|
||||
}
|
||||
|
||||
// When preserveRepository is true, the command should NOT be wrapped in executeInDocker
|
||||
expect($command)->not->toContain('docker exec');
|
||||
expect($command)->toStartWith("cd {$serverWorkdir}");
|
||||
expect($command)->toContain($startCommand);
|
||||
});
|
||||
|
||||
it('generates executeInDocker command when preserveRepository is false', function () {
|
||||
$deploymentUuid = 'test-deployment-uuid';
|
||||
$serverWorkdir = '/data/coolify/applications/app-uuid';
|
||||
$basedir = '/artifacts/test-deployment-uuid';
|
||||
$workdir = '/artifacts/test-deployment-uuid/backend';
|
||||
$preserveRepository = false;
|
||||
|
||||
$startCommand = 'docker compose -f /artifacts/test-deployment-uuid/backend/compose.yml --env-file /artifacts/test-deployment-uuid/backend/.env --profile all up -d';
|
||||
|
||||
// Simulate the logic from ApplicationDeploymentJob::deploy_docker_compose_buildpack()
|
||||
if ($preserveRepository) {
|
||||
$command = "cd {$serverWorkdir} && {$startCommand}";
|
||||
} else {
|
||||
$command = executeInDocker($deploymentUuid, "cd {$basedir} && {$startCommand}");
|
||||
}
|
||||
|
||||
// When preserveRepository is false, the command SHOULD be wrapped in executeInDocker
|
||||
expect($command)->toContain('docker exec');
|
||||
expect($command)->toContain($deploymentUuid);
|
||||
expect($command)->toContain("cd {$basedir}");
|
||||
});
|
||||
|
||||
it('uses host paths for env-file when preserveRepository is true', function () {
|
||||
$serverWorkdir = '/data/coolify/applications/app-uuid';
|
||||
$composeLocation = '/compose.yml';
|
||||
$preserveRepository = true;
|
||||
|
||||
$workdirPath = $preserveRepository ? $serverWorkdir : '/artifacts/deployment-uuid/backend';
|
||||
$startCommand = injectDockerComposeFlags(
|
||||
'docker compose --profile all up -d',
|
||||
"{$workdirPath}{$composeLocation}",
|
||||
"{$workdirPath}/.env"
|
||||
);
|
||||
|
||||
// Verify the injected paths point to the host filesystem
|
||||
expect($startCommand)->toContain("--env-file {$serverWorkdir}/.env");
|
||||
expect($startCommand)->toContain("-f {$serverWorkdir}{$composeLocation}");
|
||||
});
|
||||
|
||||
it('uses container paths for env-file when preserveRepository is false', function () {
|
||||
$workdir = '/artifacts/deployment-uuid/backend';
|
||||
$composeLocation = '/compose.yml';
|
||||
$preserveRepository = false;
|
||||
$serverWorkdir = '/data/coolify/applications/app-uuid';
|
||||
|
||||
$workdirPath = $preserveRepository ? $serverWorkdir : $workdir;
|
||||
$startCommand = injectDockerComposeFlags(
|
||||
'docker compose --profile all up -d',
|
||||
"{$workdirPath}{$composeLocation}",
|
||||
"{$workdirPath}/.env"
|
||||
);
|
||||
|
||||
// Verify the injected paths point to the container filesystem
|
||||
expect($startCommand)->toContain("--env-file {$workdir}/.env");
|
||||
expect($startCommand)->toContain("-f {$workdir}{$composeLocation}");
|
||||
expect($startCommand)->not->toContain('/data/coolify/applications/');
|
||||
});
|
||||
11
tests/Unit/ServiceIndexValidationTest.php
Normal file
11
tests/Unit/ServiceIndexValidationTest.php
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
use App\Livewire\Project\Service\Index;
|
||||
|
||||
test('service database proxy timeout requires a minimum of one second', function () {
|
||||
$component = new Index;
|
||||
$rules = (fn (): array => $this->rules)->call($component);
|
||||
|
||||
expect($rules['publicPortTimeout'])
|
||||
->toContain('min:1');
|
||||
});
|
||||
Loading…
Reference in a new issue