Merge branch 'next' into main

This commit is contained in:
Muhammed Mustafa Akşam 2024-06-13 15:18:17 +03:00 committed by GitHub
commit 6f23f6352d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 232 additions and 87 deletions

View File

@ -5,13 +5,13 @@ # About the Project
Coolify is an open-source & self-hostable alternative to Heroku / Netlify / Vercel / etc.
It helps you to manage your servers, applications, databases on your own hardware, all you need is SSH connection. You can manage VPS, Bare Metal, Raspberry PI's anything.
It helps you manage your servers, applications, and databases on your own hardware; you only need an SSH connection. You can manage VPS, Bare Metal, Raspberry PIs, and anything else.
Imagine if you could have the ease of a cloud but with your own servers. That is **Coolify**.
Imagine having the ease of a cloud but with your own servers. That is **Coolify**.
No vendor lock-in, which means that all the configuration for your applications/databases/etc are saved to your server. So if you decide to stop using Coolify (oh nooo), you could still manage your running resources. You just lose the automations and all the magic. 🪄️
No vendor lock-in, which means that all the configurations for your applications/databases/etc are saved to your server. So, if you decide to stop using Coolify (oh nooo), you could still manage your running resources. You lose the automations and all the magic. 🪄️
For more information, take a look at our landing page [here](https://coolify.io).
For more information, take a look at our landing page at [coolify.io](https://coolify.io).
# Installation
@ -22,12 +22,12 @@ # Installation
# Support
Contact us [here](https://coolify.io/docs/contact).
Contact us at [coolify.io/docs/contact](https://coolify.io/docs/contact).
# Donations
To stay completely free, open-source, no feature behind paywall and evolve the project, we need your help. If you like Coolify, please consider donating to help us fund the future development of the project.
To stay completely free and open-source, with no feature behind the paywall and evolve the project, we need your help. If you like Coolify, please consider donating to help us fund the project's future development.
https://coolify.io/sponsorships
[coolify.io/sponsorships](https://coolify.io/sponsorships)
Thank you so much!
@ -36,22 +36,23 @@ # Donations
<a href="https://cccareers.org/" target="_blank"><img src="./other/logos/ccc-logo.webp" alt="cccareers logo" width="200"/></a>
<a href="http://htznr.li/CoolifyXHetzner" target="_blank"><img src="./other/logos/hetzner.jpg" alt="hetzner logo" width="200"/></a>
<a href="https://logto.io/?ref=coolify" target="_blank"><img src="./other/logos/logto.webp" alt="logto logo" width="200"/></a>
<a href="https://bc.direct/?utm_source=coolify.io" target="_blank"><img src="./other/logos/bc.png" alt="bc direct logo" width="200"/></a>
<a href="https://www.quantcdn.io/?utm_source=coolify.io" target="_blank"><img src="./other/logos/quant.svg" alt="quantcdn logo" width="200"/></a>
<a href="https://arcjet.com/?utm_source=coolify.io" target="_blank"><img src="./other/logos/arcjet.svg" alt="arcjet logo" width="200"/></a>
<a href="https://bc.direct/?ref=coolify.io" target="_blank"><img src="./other/logos/bc.png" alt="bc direct logo" width="200"/></a>
<a href="https://www.quantcdn.io/?ref=coolify.io" target="_blank"><img src="./other/logos/quant.svg" alt="quantcdn logo" width="200"/></a>
<a href="https://arcjet.com/?ref=coolify.io" target="_blank"><img src="./other/logos/arcjet.svg" alt="arcjet logo" width="200"/></a>
<a href="https://supa.guide/?ref=coolify.io" target="_blank"><img src="./other/logos/supaguide.png" alt="supaguide logo" width="200"/></a>
<a href="https://tigrisdata.com/?ref=coolify.io" target="_blank"><img src="./other/logos/tigris.svg" alt="tigris logo" width="200"/></a>
## Github Sponsors ($40+)
<a href="https://serpapi.com/?utm_source=coolify.io"><img width="60px" alt="SerpAPI" src="https://github.com/serpapi.png"/></a>
<a href="https://typebot.io/?utm_source=coolify.io"><img src="https://pbs.twimg.com/profile_images/1509194008366657543/9I-C7uWT_400x400.jpg" width="60px" alt="typebot"/></a>
<a href="https://www.runpod.io/?utm_source=coolify.io">
<a href="https://serpapi.com/?ref=coolify.io"><img width="60px" alt="SerpAPI" src="https://github.com/serpapi.png"/></a>
<a href="https://typebot.io/?ref=coolify.io"><img src="https://pbs.twimg.com/profile_images/1509194008366657543/9I-C7uWT_400x400.jpg" width="60px" alt="typebot"/></a>
<a href="https://www.runpod.io/?ref=coolify.io">
<svg style="width:60px;height:60px;background:#fff;" xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 200 200"><g><path d="M74.5 51.1c-25.4 14.9-27 16-29.6 20.2-1.8 3-1.9 5.3-1.9 32.3 0 21.7.3 29.4 1.3 30.6 1.9 2.5 46.7 27.9 48.5 27.6 1.5-.3 1.7-3.1 2-27.7.2-21.9 0-27.8-1.1-29.5-.8-1.2-9.9-6.8-20.2-12.6-10.3-5.8-19.4-11.5-20.2-12.7-1.8-2.6-.9-5.9 1.8-7.4 1.6-.8 6.3 0 21.8 4C87.8 78.7 98 81 99.6 81c4.4 0 49.9-25.9 49.9-28.4 0-1.6-3.4-2.8-24-8.2-13.2-3.5-25.1-6.3-26.5-6.3-1.4.1-12.4 5.9-24.5 13z"></path><path d="m137.2 68.1-3.3 2.1 6.3 3.7c3.5 2 6.3 4.3 6.3 5.1 0 .9-8 6.1-19.4 12.6-10.6 6-20 11.9-20.7 12.9-1.2 1.6-1.4 7.2-1.2 29.4.3 24.8.5 27.6 2 27.9 1.8.3 46.6-25.1 48.6-27.6.9-1.2 1.2-8.8 1.2-30.2s-.3-29-1.2-30.2c-1.6-1.9-12.1-7.8-13.9-7.8-.8 0-2.9 1-4.7 2.1z"></path></g></svg></a>
<a href="https://lightspeed.run/?utm_source=coolify.io"><img src="https://github.com/lightspeedrun.png" width="60px" alt="Lightspeed.run"/></a>
<a href="https://www.flint.sh/en/home?utm_source=coolify.io"> <img src="https://github.com/Flint-company.png" width="60px" alt="FlintCompany"/></a>
<a href="https://americancloud.com/?utm_source=coolify.io"><img src="https://github.com/American-Cloud.png" width="60px" alt="American Cloud"/></a>
<a href="https://cryptojobslist.com/?utm_source=coolify.io"><img src="https://github.com/cryptojobslist.png" width="60px" alt="CryptoJobsList" /></a>
<a href="https://x.com/mrsmith9ja?utm_source=coolify.io"><img width="60px" alt="Thompson Edolo" src="https://github.com/verygreenboi.png"/></a>
<a href="https://www.uxwizz.com/?utm_source=coolify.io"><img width="60px" alt="UXWizz" src="https://github.com/UXWizz.png"/></a>
<a href="https://lightspeed.run/?ref=coolify.io"><img src="https://github.com/lightspeedrun.png" width="60px" alt="Lightspeed.run"/></a>
<a href="https://www.flint.sh/en/home?ref=coolify.io"> <img src="https://github.com/Flint-company.png" width="60px" alt="FlintCompany"/></a>
<a href="https://americancloud.com/?ref=coolify.io"><img src="https://github.com/American-Cloud.png" width="60px" alt="American Cloud"/></a>
<a href="https://cryptojobslist.com/?ref=coolify.io"><img src="https://github.com/cryptojobslist.png" width="60px" alt="CryptoJobsList" /></a>
<a href="https://x.com/mrsmith9ja?ref=coolify.io"><img width="60px" alt="Thompson Edolo" src="https://github.com/verygreenboi.png"/></a>
<a href="https://www.uxwizz.com/?ref=coolify.io"><img width="60px" alt="UXWizz" src="https://github.com/UXWizz.png"/></a>
<a href="https://github.com/Flowko"><img src="https://barrad.me/_ipx/f_webp&s_300x300/younes.jpg" width="60px" alt="Younes Barrad" /></a>
<a href="https://github.com/automazeio"><img src="https://github.com/automazeio.png" width="60px" alt="Automaze" /></a>
<a href="https://github.com/corentinclichy"><img src="https://github.com/corentinclichy.png" width="60px" alt="Corentin Clichy" /></a>
@ -83,9 +84,9 @@ ## Individuals
# Cloud
If you do not want to self-host Coolify, there is a paid cloud version available: https://app.coolify.io
If you do not want to self-host Coolify, there is a paid cloud version available: [app.coolify.io](https://app.coolify.io)
For more information & pricing, take a look at our landing page [here](https://coolify.io).
For more information & pricing, take a look at our landing page [coolify.io](https://coolify.io).
## Why should I use the Cloud version?
The recommended way to use Coolify is to have one server for Coolify and one (or more) for the resources you are deploying. A server is around 4-5$/month.
@ -109,7 +110,7 @@ # Recognitions
</a>
</p>
<a href="https://www.producthunt.com/posts/coolify?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-coolify" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=338273&theme=light" alt="Coolify - An&#0032;open&#0045;source&#0032;&#0038;&#0032;self&#0045;hostable&#0032;Heroku&#0044;&#0032;Netlify&#0032;alternative | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
<a href="https://www.producthunt.com/posts/coolify?ref=badge-featured&utm_medium=badge&utm_souce=badge-coolify" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=338273&theme=light" alt="Coolify - An&#0032;open&#0045;source&#0032;&#0038;&#0032;self&#0045;hostable&#0032;Heroku&#0044;&#0032;Netlify&#0032;alternative | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
<a href="https://trendshift.io/repositories/634" target="_blank"><img src="https://trendshift.io/api/badge/repositories/634" alt="coollabsio%2Fcoolify | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>

View File

@ -130,6 +130,16 @@ public function manual(Request $request)
$deployment_uuid = new Cuid2(7);
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
if (! $found) {
if ($application->build_pack === 'dockercompose') {
$pr_app = ApplicationPreview::create([
'git_type' => 'bitbucket',
'application_id' => $application->id,
'pull_request_id' => $pull_request_id,
'pull_request_html_url' => $pull_request_html_url,
'docker_compose_domains' => $application->docker_compose_domains,
]);
$pr_app->generate_preview_fqdn_compose();
} else {
ApplicationPreview::create([
'git_type' => 'bitbucket',
'application_id' => $application->id,
@ -137,6 +147,7 @@ public function manual(Request $request)
'pull_request_html_url' => $pull_request_html_url,
]);
}
}
queue_application_deployment(
application: $application,
pull_request_id: $pull_request_id,

View File

@ -165,6 +165,16 @@ public function manual(Request $request)
$deployment_uuid = new Cuid2(7);
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
if (! $found) {
if ($application->build_pack === 'dockercompose') {
$pr_app = ApplicationPreview::create([
'git_type' => 'gitea',
'application_id' => $application->id,
'pull_request_id' => $pull_request_id,
'pull_request_html_url' => $pull_request_html_url,
'docker_compose_domains' => $application->docker_compose_domains,
]);
$pr_app->generate_preview_fqdn_compose();
} else {
ApplicationPreview::create([
'git_type' => 'gitea',
'application_id' => $application->id,
@ -172,6 +182,8 @@ public function manual(Request $request)
'pull_request_html_url' => $pull_request_html_url,
]);
}
}
queue_application_deployment(
application: $application,
pull_request_id: $pull_request_id,

View File

@ -170,6 +170,16 @@ public function manual(Request $request)
$deployment_uuid = new Cuid2(7);
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
if (! $found) {
if ($application->build_pack === 'dockercompose') {
$pr_app = ApplicationPreview::create([
'git_type' => 'github',
'application_id' => $application->id,
'pull_request_id' => $pull_request_id,
'pull_request_html_url' => $pull_request_html_url,
'docker_compose_domains' => $application->docker_compose_domains,
]);
$pr_app->generate_preview_fqdn_compose();
} else {
ApplicationPreview::create([
'git_type' => 'github',
'application_id' => $application->id,
@ -177,6 +187,7 @@ public function manual(Request $request)
'pull_request_html_url' => $pull_request_html_url,
]);
}
}
queue_application_deployment(
application: $application,
pull_request_id: $pull_request_id,

View File

@ -180,6 +180,16 @@ public function manual(Request $request)
$deployment_uuid = new Cuid2(7);
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
if (! $found) {
if ($application->build_pack === 'dockercompose') {
$pr_app = ApplicationPreview::create([
'git_type' => 'gitlab',
'application_id' => $application->id,
'pull_request_id' => $pull_request_id,
'pull_request_html_url' => $pull_request_html_url,
'docker_compose_domains' => $application->docker_compose_domains,
]);
$pr_app->generate_preview_fqdn_compose();
} else {
ApplicationPreview::create([
'git_type' => 'gitlab',
'application_id' => $application->id,
@ -187,6 +197,7 @@ public function manual(Request $request)
'pull_request_html_url' => $pull_request_html_url,
]);
}
}
queue_application_deployment(
application: $application,
pull_request_id: $pull_request_id,

View File

@ -9,6 +9,7 @@
use App\Models\Application;
use App\Models\ApplicationDeploymentQueue;
use App\Models\ApplicationPreview;
use App\Models\EnvironmentVariable;
use App\Models\GithubApp;
use App\Models\GitlabApp;
use App\Models\Server;
@ -877,7 +878,6 @@ private function save_environment_variables()
$real_value = '\''.$real_value.'\'';
} else {
$real_value = escapeEnvVariables($env->real_value);
ray($real_value);
}
}
$envs->push($env->key.'='.$real_value);
@ -946,9 +946,8 @@ private function save_environment_variables()
}
}
private function framework_based_notification()
private function laravel_finetunes()
{
// Laravel old env variables
if ($this->pull_request_id === 0) {
$nixpacks_php_fallback_path = $this->application->environment_variables->where('key', 'NIXPACKS_PHP_FALLBACK_PATH')->first();
$nixpacks_php_root_dir = $this->application->environment_variables->where('key', 'NIXPACKS_PHP_ROOT_DIR')->first();
@ -956,9 +955,22 @@ private function framework_based_notification()
$nixpacks_php_fallback_path = $this->application->environment_variables_preview->where('key', 'NIXPACKS_PHP_FALLBACK_PATH')->first();
$nixpacks_php_root_dir = $this->application->environment_variables_preview->where('key', 'NIXPACKS_PHP_ROOT_DIR')->first();
}
if ($nixpacks_php_fallback_path?->value === '/index.php' && $nixpacks_php_root_dir?->value === '/app/public' && $this->newVersionIsHealthy === false) {
$this->application_deployment_queue->addLogEntry('There was a change in how Laravel is deployed. Please update your environment variables to match the new deployment method. More details here: https://coolify.io/docs/resources/laravel', 'stderr');
if (! $nixpacks_php_fallback_path) {
$nixpacks_php_fallback_path = new EnvironmentVariable();
$nixpacks_php_fallback_path->key = 'NIXPACKS_PHP_FALLBACK_PATH';
$nixpacks_php_fallback_path->value = '/index.php';
$nixpacks_php_fallback_path->application_id = $this->application->id;
$nixpacks_php_fallback_path->save();
}
if (! $nixpacks_php_root_dir) {
$nixpacks_php_root_dir = new EnvironmentVariable();
$nixpacks_php_root_dir->key = 'NIXPACKS_PHP_ROOT_DIR';
$nixpacks_php_root_dir->value = '/app/public';
$nixpacks_php_root_dir->application_id = $this->application->id;
$nixpacks_php_root_dir->save();
}
return [$nixpacks_php_fallback_path, $nixpacks_php_root_dir];
}
private function rolling_update()
@ -1005,7 +1017,6 @@ private function rolling_update()
$this->application_deployment_queue->addLogEntry('Rolling update completed.');
}
}
$this->framework_based_notification();
}
private function health_check()
@ -1366,12 +1377,14 @@ private function generate_nixpacks_confs()
throw new RuntimeException('Nixpacks failed to detect the application type. Please check the documentation of Nixpacks: https://nixpacks.com/docs/providers');
}
}
if ($this->saved_outputs->get('nixpacks_plan')) {
$this->nixpacks_plan = $this->saved_outputs->get('nixpacks_plan');
if ($this->nixpacks_plan) {
$this->application_deployment_queue->addLogEntry("Found application type: {$this->nixpacks_type}.");
$this->application_deployment_queue->addLogEntry("If you need further customization, please check the documentation of Nixpacks: https://nixpacks.com/docs/providers/{$this->nixpacks_type}");
$parsed = Toml::Parse($this->nixpacks_plan);
// Do any modifications here
$this->generate_env_variables();
$merged_envs = $this->env_args->merge(collect(data_get($parsed, 'variables', [])));
@ -1388,6 +1401,12 @@ private function generate_nixpacks_confs()
data_set($parsed, 'phases.setup.aptPkgs', $aptPkgs);
}
data_set($parsed, 'variables', $merged_envs->toArray());
$is_laravel = data_get($parsed, 'variables.IS_LARAVEL', false);
if ($is_laravel) {
$variables = $this->laravel_finetunes();
data_set($parsed, 'variables.NIXPACKS_PHP_FALLBACK_PATH', $variables[0]->value);
data_set($parsed, 'variables.NIXPACKS_PHP_ROOT_DIR', $variables[1]->value);
}
$this->nixpacks_plan = json_encode($parsed, JSON_PRETTY_PRINT);
$this->application_deployment_queue->addLogEntry("Final Nixpacks plan: {$this->nixpacks_plan}", hidden: true);
}
@ -1841,13 +1860,23 @@ private function build_image()
$this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->nixpacks_plan}' | base64 -d | tee /artifacts/thegameplan.json > /dev/null"), 'hidden' => true]);
if ($this->force_rebuild) {
$this->execute_remote_command([
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --no-cache --no-error-without-start -n {$this->build_image_name} {$this->workdir}"), 'hidden' => true,
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --no-cache --no-error-without-start -n {$this->build_image_name} {$this->workdir} -o {$this->workdir}"), 'hidden' => true,
]);
} else {
$this->execute_remote_command([
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --cache-key '{$this->application->uuid}' --no-error-without-start -n {$this->build_image_name} {$this->workdir}"), 'hidden' => true,
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --cache-key '{$this->application->uuid}' --no-error-without-start -n {$this->build_image_name} {$this->workdir} -o {$this->workdir}"), 'hidden' => true,
]);
}
$build_command = "docker build {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile {$this->build_args} --progress plain -t {$this->production_image_name} {$this->workdir}";
$base64_build_command = base64_encode($build_command);
$this->execute_remote_command(
[
executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee /artifacts/build.sh > /dev/null"), 'hidden' => true,
],
[
executeInDocker($this->deployment_uuid, 'bash /artifacts/build.sh'), 'hidden' => true,
]
);
$this->execute_remote_command([executeInDocker($this->deployment_uuid, 'rm /artifacts/thegameplan.json'), 'hidden' => true]);
} else {
if ($this->force_rebuild) {
@ -1929,13 +1958,23 @@ private function build_image()
$this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->nixpacks_plan}' | base64 -d | tee /artifacts/thegameplan.json > /dev/null"), 'hidden' => true]);
if ($this->force_rebuild) {
$this->execute_remote_command([
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --no-cache --no-error-without-start -n {$this->production_image_name} {$this->workdir}"), 'hidden' => true,
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --no-cache --no-error-without-start -n {$this->production_image_name} {$this->workdir} -o {$this->workdir}"), 'hidden' => true,
]);
} else {
$this->execute_remote_command([
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --cache-key '{$this->application->uuid}' --no-error-without-start -n {$this->production_image_name} {$this->workdir}"), 'hidden' => true,
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --cache-key '{$this->application->uuid}' --no-error-without-start -n {$this->production_image_name} {$this->workdir} -o {$this->workdir}"), 'hidden' => true,
]);
}
$build_command = "docker build {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile {$this->build_args} --progress plain -t {$this->production_image_name} {$this->workdir}";
$base64_build_command = base64_encode($build_command);
$this->execute_remote_command(
[
executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee /artifacts/build.sh > /dev/null"), 'hidden' => true,
],
[
executeInDocker($this->deployment_uuid, 'bash /artifacts/build.sh'), 'hidden' => true,
]
);
$this->execute_remote_command([executeInDocker($this->deployment_uuid, 'rm /artifacts/thegameplan.json'), 'hidden' => true]);
} else {
if ($this->force_rebuild) {

View File

@ -54,9 +54,9 @@ public function force_start()
public function cancel()
{
try {
$kill_command = "docker rm -f {$this->application_deployment_queue->deployment_uuid}";
$server_id = $this->application_deployment_queue->server_id ?? $this->application->destination->server_id;
try {
$server = Server::find($server_id);
if ($this->application_deployment_queue->logs) {
$previous_logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR);
@ -84,6 +84,7 @@ public function cancel()
'current_process_id' => null,
'status' => ApplicationDeploymentStatus::CANCELLED_BY_USER->value,
]);
next_after_cancel($server);
}
}
}

View File

@ -131,6 +131,12 @@ public function add(int $pull_request_id, ?string $pull_request_html_url = null)
}
}
public function add_and_deploy(int $pull_request_id, ?string $pull_request_html_url = null)
{
$this->add($pull_request_id, $pull_request_html_url);
$this->deploy($pull_request_id, $pull_request_html_url);
}
public function deploy(int $pull_request_id, ?string $pull_request_html_url = null)
{
try {

View File

@ -128,8 +128,8 @@ public function load_branch()
) {
$this->repository_url = $this->repository_url.'.git';
}
if (str($this->repository_url)->contains('github.com')) {
$this->repository_url = str($this->repository_url)->before('.git')->value();
if (str($this->repository_url)->contains('github.com') && str($this->repository_url)->endsWith('.git')) {
$this->repository_url = str($this->repository_url)->beforeLast('.git')->value();
}
} catch (\Throwable $e) {
return handleError($e, $this);
@ -140,7 +140,6 @@ public function load_branch()
$this->get_branch();
$this->selected_branch = $this->git_branch;
} catch (\Throwable $e) {
ray($e->getMessage());
if (! $this->branch_found && $this->git_branch == 'main') {
try {
$this->git_branch = 'master';

View File

@ -235,11 +235,6 @@ public function gitCommitLink($link): string
return "{$this->source->html_url}/{$this->git_repository}/commit/{$link}";
}
if (strpos($this->git_repository, 'git@') === 0) {
$git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository);
return "https://{$git_repository}/commit/{$link}";
}
if (str($this->git_repository)->contains('bitbucket')) {
$git_repository = str_replace('.git', '', $this->git_repository);
$url = Url::fromString($git_repository);
@ -248,6 +243,11 @@ public function gitCommitLink($link): string
return $url->__toString();
}
if (strpos($this->git_repository, 'git@') === 0) {
$git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository);
return "https://{$git_repository}/commit/{$link}";
}
return $this->git_repository;
}
@ -532,7 +532,7 @@ public function isDeploymentInprogress()
public function get_last_successful_deployment()
{
return ApplicationDeploymentQueue::where('application_id', $this->id)->where('status', 'finished')->where('pull_request_id', 0)->orderBy('created_at', 'desc')->first();
return ApplicationDeploymentQueue::where('application_id', $this->id)->where('status', ApplicationDeploymentStatus::FINISHED)->where('pull_request_id', 0)->orderBy('created_at', 'desc')->first();
}
public function get_last_days_deployments()

View File

@ -65,7 +65,7 @@ function force_start_deployment(ApplicationDeploymentQueue $deployment)
function queue_next_deployment(Application $application)
{
$server_id = $application->destination->server_id;
$next_found = ApplicationDeploymentQueue::where('server_id', $server_id)->where('status', 'queued')->get()->sortBy('created_at')->first();
$next_found = ApplicationDeploymentQueue::where('server_id', $server_id)->where('status', ApplicationDeploymentStatus::QUEUED)->get()->sortBy('created_at')->first();
if ($next_found) {
$next_found->update([
'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
@ -79,7 +79,7 @@ function queue_next_deployment(Application $application)
function next_queuable(string $server_id, string $application_id): bool
{
$deployments = ApplicationDeploymentQueue::where('server_id', $server_id)->whereIn('status', ['in_progress', 'queued'])->get()->sortByDesc('created_at');
$deployments = ApplicationDeploymentQueue::where('server_id', $server_id)->whereIn('status', ['in_progress', ApplicationDeploymentStatus::QUEUED])->get()->sortByDesc('created_at');
$same_application_deployments = $deployments->where('application_id', $application_id);
$in_progress = $same_application_deployments->filter(function ($value, $key) {
return $value->status === 'in_progress';
@ -98,3 +98,26 @@ function next_queuable(string $server_id, string $application_id): bool
return true;
}
function next_after_cancel(?Server $server = null)
{
if ($server) {
$next_found = ApplicationDeploymentQueue::where('server_id', data_get($server, 'id'))->where('status', ApplicationDeploymentStatus::QUEUED)->get()->sortBy('created_at');
if ($next_found->count() > 0) {
foreach ($next_found as $next) {
$server = Server::find($next->server_id);
$concurrent_builds = $server->settings->concurrent_builds;
$inprogress_deployments = ApplicationDeploymentQueue::where('server_id', $next->server_id)->whereIn('status', [ApplicationDeploymentStatus::QUEUED])->get()->sortByDesc('created_at');
if ($inprogress_deployments->count() < $concurrent_builds) {
$next->update([
'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
]);
dispatch(new ApplicationDeploymentJob(
application_deployment_queue_id: $next->id,
));
}
break;
}
}
}
}

View File

@ -7,7 +7,7 @@
// The release version of your application
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
'release' => '4.0.0-beta.297',
'release' => '4.0.0-beta.298',
// When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'),

View File

@ -18,7 +18,7 @@
|
*/
'driver' => env('SESSION_DRIVER', 'redis'),
'driver' => env('SESSION_DRIVER', 'database'),
/*
|--------------------------------------------------------------------------

View File

@ -1,3 +1,3 @@
<?php
return '4.0.0-beta.297';
return '4.0.0-beta.298';

BIN
other/logos/supaguide.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

16
other/logos/tigris.svg Normal file
View File

@ -0,0 +1,16 @@
<svg width="59" height="24" viewBox="0 0 59 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1046_262)">
<path d="M27.1504 1.51153V0.285861H30.2514V12.3573C30.2671 13.4155 30.036 14.4637 29.575 15.4181C29.1341 16.3145 28.4319 17.0568 27.5601 17.5491C26.5655 18.0894 25.4436 18.3562 24.3106 18.3216C22.7757 18.3941 21.2609 17.951 20.0096 17.0624C18.9212 16.2185 18.2113 14.9806 18.0349 13.6176H21.0868C21.2442 14.2081 21.6103 14.7227 22.1194 15.0643C22.7076 15.4371 23.3975 15.6191 24.0941 15.5856C24.4993 15.6034 24.9034 15.5409 25.284 15.4025C25.6647 15.2641 26.0141 15.052 26.3121 14.7785C26.6157 14.4492 26.8479 14.0596 26.993 13.6366C27.1381 13.2135 27.194 12.7636 27.156 12.3182V9.92158C26.8546 10.7287 26.3032 11.4174 25.5809 11.8896C24.7884 12.3964 23.8608 12.6542 22.9197 12.6274C21.9385 12.6408 20.9718 12.3819 20.1301 11.8795C19.2829 11.3571 18.6087 10.5992 18.1889 9.69944C17.7268 8.64345 17.4879 7.50484 17.4879 6.35284C17.4879 5.20084 17.7268 4.06223 18.1889 3.00623C18.6075 2.10763 19.2829 1.35079 20.1301 0.830606C20.9718 0.326047 21.9385 0.0670711 22.9197 0.082699C23.9523 0.131815 26.3266 0.131814 27.1515 1.51042L27.1504 1.51153ZM21.5411 3.79991C20.9651 4.54558 20.6526 5.45981 20.6526 6.40084C20.6526 7.34186 20.9651 8.2561 21.5411 9.00177C22.1707 9.60791 23.0135 9.94502 23.8898 9.94056C24.7649 9.93609 25.6044 9.59005 26.2273 8.97721C26.8245 8.24828 27.1515 7.33516 27.1515 6.39414C27.1515 5.45312 26.8256 4.54 26.2273 3.81107C25.9281 3.49628 25.5653 3.24735 25.1623 3.08214C24.7605 2.91693 24.3262 2.83767 23.892 2.85107C23.4544 2.83209 23.0191 2.90688 22.6128 3.07098C22.2075 3.23507 21.8414 3.484 21.5411 3.80102V3.79991Z" fill="white"/>
<path d="M24.6813 23.9318C23.9389 23.9318 23.1988 23.8793 22.4643 23.7744C17.2692 23.022 13.2104 19.8038 12.1187 15.5765C11.8619 14.1342 11.7681 12.6686 11.8374 11.2062V5.40381H14.9484V11.2308C14.8948 12.4252 14.9562 13.6207 15.1315 14.8029C15.9062 17.8191 18.9637 20.1376 22.9086 20.708C25.936 21.1456 29.8217 20.5059 31.7183 17.4161L32.2117 16.4561C33.7667 13.297 37.1791 13.2669 39.0065 13.2479H40.1417C40.471 13.1999 40.7914 13.1006 41.0894 12.9532C41.6442 12.6831 42.112 12.2622 42.4401 11.7409C42.7683 11.2196 42.9436 10.6168 42.9458 10.0006V5.4239H46.0569V10.0006C46.0547 11.5545 45.4853 13.0548 44.455 14.2213C43.4247 15.3878 42.0037 16.1402 40.4565 16.3389H39.0344C36.5652 16.3634 35.5337 16.7329 35.0001 17.8146L34.432 18.9465C32.5108 22.1011 28.8963 23.9318 24.679 23.9318H24.6813Z" fill="white"/>
<path d="M35.8999 1.82169V0.227643H32.7743V11.866C32.7743 11.9117 32.7855 11.9564 32.8067 11.9966C32.8279 12.0368 32.8602 12.0702 32.8993 12.0948C32.9384 12.1194 32.9819 12.1328 33.0277 12.135C33.0735 12.1372 33.1192 12.1283 33.1594 12.1071C33.9642 11.732 34.8115 11.4529 35.6833 11.2755C35.7436 11.2632 35.7983 11.2308 35.8385 11.1828C35.8775 11.1359 35.8999 11.0756 35.901 11.0142V6.58485C35.901 4.46281 37.053 3.40123 39.3581 3.40123H40.2668V0.0702489C39.309 0.0501559 36.8052 0.227645 35.901 1.82169H35.8999Z" fill="white"/>
<path d="M13.4515 4.07001L13.13 3.36676C12.9458 2.96936 12.6232 2.65234 12.2213 2.47597L11.5103 2.17569L12.2113 1.85532C12.612 1.67336 12.9313 1.34853 13.1054 0.944434L13.4113 0.235596L13.7328 0.934386C13.9136 1.33513 14.2396 1.65327 14.6459 1.82518L15.3525 2.12992L14.6515 2.45029C14.2507 2.63225 13.9315 2.95708 13.7573 3.36118L13.4515 4.07001Z" fill="#50FFAB"/>
<path d="M5.92662 6.04346V2.82523H8.97853V0.19751H0.0895996V2.82523H2.75081V6.02895C2.75081 9.30635 4.14281 13.1296 8.97742 13.1296V10.5856C6.50821 10.6001 5.92551 8.70132 5.92551 6.04346H5.92662Z" fill="white"/>
<path d="M44.5019 4.07001L44.1805 3.36676C43.9963 2.96825 43.6714 2.65122 43.2673 2.47597L42.5563 2.17569L43.2618 1.85532C43.6614 1.67113 43.9795 1.34741 44.1559 0.944434L44.4618 0.235596L44.7777 0.934386C44.9585 1.33513 45.2856 1.65327 45.6908 1.82518L46.4019 2.12992L45.7008 2.45029C45.3001 2.63225 44.9808 2.95708 44.8067 3.36118L44.5008 4.07001H44.5019Z" fill="#50FFAB"/>
<path d="M58.038 7.20003C57.5792 6.71779 57.0054 6.36059 56.3691 6.16189C55.5609 5.92077 54.736 5.73993 53.8999 5.62049C53.1375 5.5111 52.3874 5.32468 51.6629 5.06458C51.453 4.99872 51.2688 4.86812 51.1394 4.69063C51.0099 4.51314 50.9407 4.29882 50.9418 4.08002C50.9462 3.86347 51.0121 3.65249 51.1304 3.47054C51.2487 3.28858 51.4162 3.14347 51.6127 3.05193C52.2277 2.75947 52.9075 2.62551 53.5874 2.66347C54.8588 2.64561 56.1124 2.97156 57.2119 3.60784L58.3483 1.36858C57.6841 0.993514 56.9641 0.725608 56.2151 0.576026C55.3611 0.380677 54.4882 0.282445 53.613 0.281329C52.1786 0.206538 50.7576 0.581608 49.5487 1.35407C49.0798 1.66998 48.6992 2.09863 48.4402 2.59984C48.1812 3.10105 48.0528 3.65919 48.0674 4.22291C48.0071 4.99314 48.2471 5.75668 48.7394 6.35389C49.2015 6.85621 49.7898 7.22682 50.4428 7.42663C51.2767 7.67221 52.1284 7.85305 52.9913 7.96803C53.728 8.06403 54.4536 8.22924 55.1591 8.46031C55.3578 8.51835 55.5308 8.64003 55.6525 8.80635C55.7741 8.97268 55.8367 9.17472 55.8311 9.38012C55.8311 10.3122 54.947 10.7766 53.1788 10.7732C51.5725 10.809 49.9751 10.5299 48.4781 9.95165V12.4119C49.9204 12.95 51.453 13.2056 52.9913 13.1643C54.7595 13.1643 56.157 12.8116 57.184 12.1061C57.6618 11.8036 58.0536 11.385 58.3226 10.8882C58.5916 10.3915 58.7278 9.83556 58.7189 9.27184C58.7702 8.51947 58.5258 7.77603 58.038 7.20003Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_1046_262">
<rect width="58.7163" height="24" fill="white" transform="translate(0.0494385)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -89,7 +89,7 @@ class="fixed top-4 right-16" x-on:click="toggleScroll"><svg class="icon" viewBox
@if (decode_remote_command_output($application_deployment_queue)->count() > 0)
@foreach (decode_remote_command_output($application_deployment_queue) as $line)
<span @class([
'dark:text-warning whitespace-pre-line' => $line['hidden'],
'text-coollabs dark:text-warning whitespace-pre-line' => $line['hidden'],
'text-red-500 font-bold whitespace-pre-line' => $line['type'] == 'stderr',
])>[{{ $line['timestamp'] }}] @if ($line['hidden'])
<br><br>[COMMAND] {{ $line['command'] }}<br>[OUTPUT]

View File

@ -45,7 +45,7 @@ class="dark:text-warning">{{ $application->destination->server->name }}</span>.<
Configure
</x-forms.button>
<x-forms.button
wire:click="deploy('{{ data_get($pull_request, 'number') }}', '{{ data_get($pull_request, 'html_url') }}')">
wire:click="add_and_deploy('{{ data_get($pull_request, 'number') }}', '{{ data_get($pull_request, 'html_url') }}')">
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 dark:text-warning"
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
fill="none" stroke-linecap="round" stroke-linejoin="round">

View File

@ -172,7 +172,8 @@ class="w-4 h-4 dark:text-warning text-coollabs"
<h2>Storages</h2>
</div>
<div class="pb-4">Persistent storage to preserve data between deployments.</div>
<span class="dark:text-warning">Please modify storage layout in your Docker Compose file.</span>
<div class="pb-4 dark:text-warning text-coollabs">If you would like to add a volume, you must add it to
your compose file (General tab).</div>
@foreach ($applications as $application)
<livewire:project.service.storage wire:key="application-{{ $application->id }}"
:resource="$application" />

View File

@ -6,19 +6,21 @@
<x-modal-input buttonTitle="+ Add" title="New Environment Variable">
<livewire:project.shared.environment-variable.add />
</x-modal-input>
@endif
<x-forms.button
wire:click='switch'>{{ $view === 'normal' ? 'Developer view' : 'Normal view' }}</x-forms.button>
@endif
</div>
<div>Environment variables (secrets) for this resource.</div>
@if ($this->resourceClass === 'App\Models\Application' && data_get($this->resource, 'build_pack') !== 'dockercompose')
<div class="w-64 pt-2">
<x-forms.checkbox id="resource.settings.is_env_sorting_enabled" label="Sort alphabetically"
helper="Turn this off if one environment is dependent on an other. It will be sorted by creation order." instantSave></x-forms.checkbox>
helper="Turn this off if one environment is dependent on an other. It will be sorted by creation order."
instantSave></x-forms.checkbox>
</div>
@endif
@if ($resource->type() === 'service' || $resource?->build_pack === 'dockercompose')
<div class="pt-4 dark:text-warning text-coollabs">Hardcoded variables are not shown here.</div>
<div class="pb-4 dark:text-warning text-coollabs">If you would like to add a variable, you must add it to your compose file (General tab).</div>
@endif
</div>
@if ($view === 'normal')

View File

@ -19,7 +19,7 @@
@forelse (data_get($server,'containers',[]) as $container)
<livewire:project.shared.get-logs :server="$server" :resource="$resource" :container="data_get($container, 'Names')" />
@empty
<div class="pt-2">No containers are not running on server: {{ $server->name }}</div>
<div class="pt-2">No containers are running on server: {{ $server->name }}</div>
@endforelse
</div>
</div>
@ -41,7 +41,7 @@
<div> No functional server found for the database.</div>
@endif
@empty
<div class="pt-2">No containers are not running.</div>
<div class="pt-2">No containers are running.</div>
@endforelse
</div>
@elseif ($type === 'service')
@ -56,7 +56,7 @@
<div> No functional server found for the service.</div>
@endif
@empty
<div class="pt-2">No containers are not running.</div>
<div class="pt-2">No containers are running.</div>
@endforelse
</div>
@endif

View File

@ -2,8 +2,15 @@
<form wire:submit='submit' class="flex flex-col gap-2 xl:items-end xl:flex-row">
@if ($isReadOnly)
@if ($isFirst)
@if (
$storage->resource_type === 'App\Models\ServiceApplication' ||
$storage->resource_type === 'App\Models\ServiceDatabase')
<x-forms.input id="storage.name" label="Volume Name" required readonly
helper="Warning: Changing the volume name after the initial start could cause problems. Only use it when you know what are you doing." />
@else
<x-forms.input id="storage.name" label="Volume Name" required
helper="Warning: Changing the volume name after the initial start could cause problems. Only use it when you know what are you doing." />
@endif
@if ($isService || $startedAt)
<x-forms.input id="storage.host_path" readonly helper="Directory on the host system."
label="Source Path"

View File

@ -1,9 +1,9 @@
set -e
export IMAGE=$1
docker exec coolify sh -c "php artisan tinker --execute='isAnyDeploymentInprogress()'"
docker system prune -af
docker compose pull
read -p "Press Enter to update Coolify to $IMAGE..." </dev/tty
docker exec coolify sh -c "php artisan tinker --execute='isAnyDeploymentInprogress()'"
docker compose up --remove-orphans --force-recreate -d --wait
echo $IMAGE > last_version
docker compose logs -f

5
scripts/install.sh Normal file → Executable file
View File

@ -27,6 +27,11 @@ if [ "$OS_TYPE" = "linuxmint" ]; then
OS_TYPE="ubuntu"
fi
#Check if the OS is zorin, if so, change it to ubuntu
if [ "$OS_TYPE" = "zorin" ]; then
OS_TYPE="ubuntu"
fi
if [ "$OS_TYPE" = "arch" ] || [ "$OS_TYPE" = "archarm" ]; then
OS_VERSION="rolling"
else

View File

@ -1,7 +1,7 @@
{
"coolify": {
"v4": {
"version": "4.0.0-beta.297"
"version": "4.0.0-beta.298"
},
"sentinel": {
"version": "0.0.4"