From 19d19112d9708317e2c6c0751ff9538733d97640 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 18 Mar 2024 15:40:25 +0100 Subject: [PATCH 1/9] Add healthcheck for Umami service and update service-templates.json --- templates/compose/umami.yaml | 5 +++++ templates/service-templates.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/templates/compose/umami.yaml b/templates/compose/umami.yaml index 1f70ad64c..d6e7366b5 100644 --- a/templates/compose/umami.yaml +++ b/templates/compose/umami.yaml @@ -15,6 +15,11 @@ services: depends_on: postgresql: condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000/api/heartbeat"] + interval: 5s + timeout: 20s + retries: 10 postgresql: image: postgres:16-alpine volumes: diff --git a/templates/service-templates.json b/templates/service-templates.json index d65fb4aac..04f7d6e48 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -760,7 +760,7 @@ "umami": { "documentation": "https:\/\/umami.is", "slogan": "Umami is web analytics platform which provides insights into visitor behavior without compromising user privacy.", - "compose": "c2VydmljZXM6CiAgdW1hbWk6CiAgICBpbWFnZTogJ2doY3IuaW8vdW1hbWktc29mdHdhcmUvdW1hbWk6cG9zdGdyZXNxbC1sYXRlc3QnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fVU1BTUlfMzAwMAogICAgICAtICdEQVRBQkFTRV9VUkw9cG9zdGdyZXM6Ly8kU0VSVklDRV9VU0VSX1BPU1RHUkVTOiRTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTQHBvc3RncmVzcWw6NTQzMi8kUE9TVEdSRVNfREInCiAgICAgIC0gREFUQUJBU0VfVFlQRT1wb3N0Z3JlcwogICAgICAtIEFQUF9TRUNSRVQ9JFNFUlZJQ0VfUEFTU1dPUkRfNjRfVU1BTUkKICAgIGRlcGVuZHNfb246CiAgICAgIHBvc3RncmVzcWw6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICBwb3N0Z3Jlc3FsOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNi1hbHBpbmUnCiAgICB2b2x1bWVzOgogICAgICAtICdwb3N0Z3Jlc3FsLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0kU0VSVklDRV9VU0VSX1BPU1RHUkVTCiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JFNFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVMKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotdW1hbWl9JwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICQke1BPU1RHUkVTX1VTRVJ9IC1kICQke1BPU1RHUkVTX0RCfScKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAo=", + "compose": "c2VydmljZXM6CiAgdW1hbWk6CiAgICBpbWFnZTogJ2doY3IuaW8vdW1hbWktc29mdHdhcmUvdW1hbWk6cG9zdGdyZXNxbC1sYXRlc3QnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fVU1BTUlfMzAwMAogICAgICAtICdEQVRBQkFTRV9VUkw9cG9zdGdyZXM6Ly8kU0VSVklDRV9VU0VSX1BPU1RHUkVTOiRTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTQHBvc3RncmVzcWw6NTQzMi8kUE9TVEdSRVNfREInCiAgICAgIC0gREFUQUJBU0VfVFlQRT1wb3N0Z3JlcwogICAgICAtIEFQUF9TRUNSRVQ9JFNFUlZJQ0VfUEFTU1dPUkRfNjRfVU1BTUkKICAgIGRlcGVuZHNfb246CiAgICAgIHBvc3RncmVzcWw6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLWYnCiAgICAgICAgLSAnaHR0cDovL2xvY2FsaG9zdDozMDAwL2FwaS9oZWFydGJlYXQnCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiAyMHMKICAgICAgcmV0cmllczogMTAKICBwb3N0Z3Jlc3FsOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNi1hbHBpbmUnCiAgICB2b2x1bWVzOgogICAgICAtICdwb3N0Z3Jlc3FsLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0kU0VSVklDRV9VU0VSX1BPU1RHUkVTCiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JFNFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVMKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotdW1hbWl9JwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICQke1BPU1RHUkVTX1VTRVJ9IC1kICQke1BPU1RHUkVTX0RCfScKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAo=", "tags": [ "analytics", "insights", From ec16c0f0f417263fa07c331f7f2479b4a4eaae14 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 19 Mar 2024 10:21:40 +0100 Subject: [PATCH 2/9] update cloudflared version --- docker/dev-ssu/Dockerfile | 4 ++-- docker/prod-ssu/Dockerfile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/dev-ssu/Dockerfile b/docker/dev-ssu/Dockerfile index cf79afe4d..a9e6c4a44 100644 --- a/docker/dev-ssu/Dockerfile +++ b/docker/dev-ssu/Dockerfile @@ -2,7 +2,7 @@ FROM serversideup/php:8.2-fpm-nginx ARG TARGETPLATFORM # https://github.com/cloudflare/cloudflared/releases -ARG CLOUDFLARED_VERSION=2023.10.0 +ARG CLOUDFLARED_VERSION=2024.2.1 ARG POSTGRES_VERSION=15 RUN apt-get update @@ -40,4 +40,4 @@ RUN /bin/bash -c "if [[ ${TARGETPLATFORM} == 'linux/arm64' ]]; then \ RUN { \ echo 'upload_max_filesize=256M'; \ echo 'post_max_size=256M'; \ - } > /etc/php/current_version/cli/conf.d/upload-limits.ini \ No newline at end of file + } > /etc/php/current_version/cli/conf.d/upload-limits.ini diff --git a/docker/prod-ssu/Dockerfile b/docker/prod-ssu/Dockerfile index d5ba465b7..f6d368a9f 100644 --- a/docker/prod-ssu/Dockerfile +++ b/docker/prod-ssu/Dockerfile @@ -15,7 +15,7 @@ FROM serversideup/php:8.2-fpm-nginx ARG TARGETPLATFORM # https://github.com/cloudflare/cloudflared/releases -ARG CLOUDFLARED_VERSION=2023.10.0 +ARG CLOUDFLARED_VERSION=2024.2.1 ARG POSTGRES_VERSION=15 WORKDIR /var/www/html @@ -66,4 +66,4 @@ RUN /bin/bash -c "if [[ ${TARGETPLATFORM} == 'linux/arm64' ]]; then \ RUN { \ echo 'upload_max_filesize=256M'; \ echo 'post_max_size=256M'; \ - } > /etc/php/current_version/cli/conf.d/upload-limits.ini \ No newline at end of file + } > /etc/php/current_version/cli/conf.d/upload-limits.ini From 8d48051a8d0150c7ad1c93565fabcb8c29ed8368 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 19 Mar 2024 10:22:35 +0100 Subject: [PATCH 3/9] Update Node.js version in Dockerfile --- docker/prod-ssu/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/prod-ssu/Dockerfile b/docker/prod-ssu/Dockerfile index f6d368a9f..7d0a4d373 100644 --- a/docker/prod-ssu/Dockerfile +++ b/docker/prod-ssu/Dockerfile @@ -4,7 +4,7 @@ WORKDIR /var/www/html COPY composer.json composer.lock ./ RUN composer install --no-dev --no-interaction --no-plugins --no-scripts --prefer-dist -FROM node:19 as static-assets +FROM node:20 as static-assets WORKDIR /app COPY . . COPY --from=base --chown=9999:9999 /var/www/html . From 3da7746629161d44600b5e3ccfb3ff21e134d87d Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 19 Mar 2024 10:24:09 +0100 Subject: [PATCH 4/9] update packages in helper container --- docker/coolify-helper/Dockerfile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docker/coolify-helper/Dockerfile b/docker/coolify-helper/Dockerfile index 4cf996904..5798c92bd 100644 --- a/docker/coolify-helper/Dockerfile +++ b/docker/coolify-helper/Dockerfile @@ -2,15 +2,15 @@ FROM alpine:3.17 ARG TARGETPLATFORM # https://download.docker.com/linux/static/stable/ -ARG DOCKER_VERSION=24.0.5 +ARG DOCKER_VERSION=24.0.9 # https://github.com/docker/compose/releases -ARG DOCKER_COMPOSE_VERSION=2.21.0 +ARG DOCKER_COMPOSE_VERSION=2.25.0 # https://github.com/docker/buildx/releases -ARG DOCKER_BUILDX_VERSION=0.11.2 +ARG DOCKER_BUILDX_VERSION=0.13.1 # https://github.com/buildpacks/pack/releases -ARG PACK_VERSION=0.32.1 +ARG PACK_VERSION=0.33.2 # https://github.com/railwayapp/nixpacks/releases -ARG NIXPACKS_VERSION=1.20.0 +ARG NIXPACKS_VERSION=1.21.2 USER root WORKDIR /artifacts @@ -34,7 +34,7 @@ RUN if [[ ${TARGETPLATFORM} == 'linux/arm64' ]]; then \ chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack /root/.docker/cli-plugins/docker-buildx \ ;fi -COPY --from=minio/mc /usr/bin/mc /usr/bin/mc +COPY --from=minio/mc:RELEASE.2024-03-13T23-51-57Z /usr/bin/mc /usr/bin/mc RUN chmod +x /usr/bin/mc ENTRYPOINT ["/sbin/tini", "--"] From 289480c95478a28408159e5b50b82e08ddf9af0b Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 19 Mar 2024 10:24:23 +0100 Subject: [PATCH 5/9] feat: able to run scheduler/horizon programatically --- app/Console/Commands/Horizon.php | 21 +++++++++++++++++++ app/Console/Commands/Scheduler.php | 21 +++++++++++++++++++ config/coolify.php | 2 ++ config/sentry.php | 2 +- config/version.php | 2 +- .../etc/s6-overlay/s6-rc.d/horizon/run | 2 +- .../s6-overlay/s6-rc.d/scheduler-worker/run | 2 +- versions.json | 2 +- 8 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 app/Console/Commands/Horizon.php create mode 100644 app/Console/Commands/Scheduler.php diff --git a/app/Console/Commands/Horizon.php b/app/Console/Commands/Horizon.php new file mode 100644 index 000000000..8dd64a246 --- /dev/null +++ b/app/Console/Commands/Horizon.php @@ -0,0 +1,21 @@ +info('Horizon is enabled. Starting.'); + $this->call('horizon'); + exit(0); + } else { + exit(0); + } + } +} diff --git a/app/Console/Commands/Scheduler.php b/app/Console/Commands/Scheduler.php new file mode 100644 index 000000000..eab623802 --- /dev/null +++ b/app/Console/Commands/Scheduler.php @@ -0,0 +1,21 @@ +info('Scheduler is enabled. Starting.'); + $this->call('schedule:work'); + exit(0); + } else { + exit(0); + } + } +} diff --git a/config/coolify.php b/config/coolify.php index 69ec23146..a6d6d8581 100644 --- a/config/coolify.php +++ b/config/coolify.php @@ -12,4 +12,6 @@ return [ 'is_windows_docker_desktop' => env('IS_WINDOWS_DOCKER_DESKTOP', false), 'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'), 'helper_image' => env('HELPER_IMAGE', 'ghcr.io/coollabsio/coolify-helper:latest'), + 'is_horizon_enabled' => env('HORIZON_ENABLED', true), + 'is_scheduler_enabled' => env('SCHEDULER_ENABLED', true), ]; diff --git a/config/sentry.php b/config/sentry.php index 5d46ba7f3..b4c1aa5f4 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ return [ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => '4.0.0-beta.240', + 'release' => '4.0.0-beta.241', // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/config/version.php b/config/version.php index c7e1008fc..f00cd2d57 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ Date: Tue, 19 Mar 2024 11:05:02 +0100 Subject: [PATCH 6/9] Refactor previews.blade.php to improve code readability --- .../views/livewire/project/application/previews.blade.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/views/livewire/project/application/previews.blade.php b/resources/views/livewire/project/application/previews.blade.php index 6aa9f1d28..91e9c0504 100644 --- a/resources/views/livewire/project/application/previews.blade.php +++ b/resources/views/livewire/project/application/previews.blade.php @@ -15,8 +15,8 @@ @isset($rate_limit_remaining)
Requests remaining till rate limited by Git: {{ $rate_limit_remaining }}
@endisset - @if (count($pull_requests) > 0) -
+
+ @if ($pull_requests->count() > 0)
@@ -50,8 +50,8 @@
-
- @endif + @endif +
@if ($application->previews->count() > 0)
Previews
From 42715bba501872cb5f753e93225352a937f16773 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 19 Mar 2024 11:48:25 +0100 Subject: [PATCH 7/9] fix: volumes for prs --- app/Jobs/ApplicationDeploymentJob.php | 14 ++- bootstrap/helpers/shared.php | 141 +++++++++++++++----------- 2 files changed, 91 insertions(+), 64 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 1346a6ded..98c189275 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -298,6 +298,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted "ignore_errors" => true, ] ); + + // $this->execute_remote_command( // [ // "docker image prune -f >/dev/null 2>&1", @@ -305,6 +307,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted // "ignore_errors" => true, // ] // ); + + ApplicationStatusChanged::dispatch(data_get($this->application, 'environment.project.team.id')); } } @@ -417,7 +421,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted "docker network connect {$networkId} coolify-proxy || true", "hidden" => true, "ignore_errors" => true ]); } - $this->write_deployment_configurations(); // Start compose file if ($this->application->settings->is_raw_compose_deployment_enabled) { @@ -425,7 +428,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $this->execute_remote_command( [executeInDocker($this->deployment_uuid, "cd {$this->workdir} && {$this->docker_compose_custom_start_command}"), "hidden" => true], ); + $this->write_deployment_configurations(); } else { + $this->write_deployment_configurations(); $server_workdir = $this->application->workdir(); ray("SOURCE_COMMIT={$this->commit} docker compose --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d"); $this->execute_remote_command( @@ -437,14 +442,15 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $this->execute_remote_command( [executeInDocker($this->deployment_uuid, "cd {$this->basedir} && {$this->docker_compose_custom_start_command}"), "hidden" => true], ); + $this->write_deployment_configurations(); } else { $this->execute_remote_command( [executeInDocker($this->deployment_uuid, "SOURCE_COMMIT={$this->commit} docker compose --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d"), "hidden" => true], ); + $this->write_deployment_configurations(); } } - $this->application_deployment_queue->addLogEntry("New container started."); } private function deploy_dockerfile_buildpack() @@ -822,6 +828,10 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted } private function deploy_pull_request() { + if ($this->application->build_pack === 'dockercompose') { + $this->deploy_docker_compose_buildpack(); + return; + } if ($this->use_build_server) { $this->server = $this->build_server; } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index c9f98e48a..7810e0155 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1240,84 +1240,95 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } $baseName = generateApplicationContainerName($resource, $pull_request_id); $containerName = "$serviceName-$baseName"; - if ($pull_request_id !== 0) { - if (count($serviceVolumes) > 0) { - $serviceVolumes = $serviceVolumes->map(function ($volume) use ($resource, $pull_request_id, $topLevelVolumes) { - if (is_string($volume)) { - $volume = str($volume); - if ($volume->contains(':') && !$volume->startsWith('/')) { - $name = $volume->before(':'); - $mount = $volume->after(':'); - $newName = $resource->uuid . "-{$name}-pr-$pull_request_id"; - $volume = str("$newName:$mount"); - $topLevelVolumes->put($newName, [ - 'name' => $newName, - ]); - } - } else if (is_array($volume)) { - $source = data_get($volume, 'source'); - if ($source) { - $newSource = $resource->uuid . "-{$source}-pr-$pull_request_id"; - data_set($volume, 'source', $newSource); - if (!str($source)->startsWith('/')) { - $topLevelVolumes->put($newSource, [ - 'name' => $newSource, - ]); + if (count($serviceVolumes) > 0) { + $serviceVolumes = $serviceVolumes->map(function ($volume) use ($resource, $topLevelVolumes, $pull_request_id) { + if (is_string($volume)) { + $volume = str($volume); + if ($volume->contains(':') && !$volume->startsWith('/')) { + $name = $volume->before(':'); + $mount = $volume->after(':'); + if ($name->startsWith('.') || $name->startsWith('~')) { + $dir = base_configuration_dir() . '/applications/' . $resource->uuid; + if ($name->startsWith('.')) { + $name = $name->replaceFirst('.', $dir); } - } - } - return $volume->value(); - }); - data_set($service, 'volumes', $serviceVolumes->toArray()); - } - } else { - if (count($serviceVolumes) > 0) { - $serviceVolumes = $serviceVolumes->map(function ($volume) use ($resource, $topLevelVolumes) { - if (is_string($volume)) { - $volume = str($volume); - if ($volume->contains(':') && !$volume->startsWith('/')) { - $name = $volume->before(':'); - $mount = $volume->after(':'); - if ($name->startsWith('.') || $name->startsWith('~')) { - $dir = base_configuration_dir() . '/applications/' . $resource->uuid; - if ($name->startsWith('.')) { - $name = $name->replaceFirst('.', $dir); - } - if ($name->startsWith('~')) { - $name = $name->replaceFirst('~', $dir); - } + if ($name->startsWith('~')) { + $name = $name->replaceFirst('~', $dir); + } + if ($pull_request_id !== 0) { + $name = $name . "-pr-$pull_request_id"; + } + $volume = str("$name:$mount"); + } else { + if ($pull_request_id !== 0) { + $name = $name . "-pr-$pull_request_id"; $volume = str("$name:$mount"); + $topLevelVolumes->put($name, [ + 'name' => $name, + ]); } else { $topLevelVolumes->put($name->value(), [ 'name' => $name->value(), ]); } } - } else if (is_array($volume)) { - $source = data_get($volume, 'source'); - if ($source) { - if ((str($source)->startsWith('.') || str($source)->startsWith('~')) && !str($source)->startsWith('/')) { - $dir = base_configuration_dir() . '/applications/' . $resource->uuid; - if (str($source, '.')) { - $source = str('.', $dir, $source); - } - if (str($source, '~')) { - $source = str('~', $dir, $source); - } - data_set($volume, 'source', $source); + } else { + if ($volume->startsWith('/')) { + $name = $volume->before(':'); + $mount = $volume->after(':'); + if ($pull_request_id !== 0) { + $name = $name . "-pr-$pull_request_id"; + } + $volume = str("$name:$mount"); + } + } + + } else if (is_array($volume)) { + $source = data_get($volume, 'source'); + $target = data_get($volume, 'target'); + $read_only = data_get($volume, 'read_only'); + if ($source && $target) { + if ((str($source)->startsWith('.') || str($source)->startsWith('~'))) { + $dir = base_configuration_dir() . '/applications/' . $resource->uuid; + if (str($source, '.')) { + $source = str($source)->replaceFirst('.', $dir); + } + if (str($source, '~')) { + $source = str($source)->replaceFirst('~', $dir); + } + if ($pull_request_id !== 0) { + $source = $source . "-pr-$pull_request_id"; + } + if ($read_only) { + data_set($volume, 'source', $source . ':' . $target . ':ro'); } else { - data_set($volume, 'source', $source); + data_set($volume, 'source', $source . ':' . $target); + } + } else { + if ($pull_request_id !== 0) { + $source = $source . "-pr-$pull_request_id"; + } + if ($read_only) { + data_set($volume, 'source', $source . ':' . $target . ':ro'); + } else { + data_set($volume, 'source', $source . ':' . $target); + } + if (!str($source)->startsWith('/')) { $topLevelVolumes->put($source, [ 'name' => $source, ]); } } } - return $volume->value(); - }); - data_set($service, 'volumes', $serviceVolumes->toArray()); - } + } + if (is_array($volume)) { + return data_get($volume, 'source'); + } + return $volume->value(); + }); + data_set($service, 'volumes', $serviceVolumes->toArray()); } + // Decide if the service is a database $isDatabase = isDatabaseImage(data_get_str($service, 'image')); data_set($service, 'is_database', $isDatabase); @@ -1602,6 +1613,12 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal return $service; }); + if ($pull_request_id !== 0) { + $services->each(function ($service, $serviceName) use ($pull_request_id, $services) { + $services[$serviceName . "-pr-$pull_request_id"] = $service; + data_forget($services, $serviceName); + }); + } $finalServices = [ 'version' => $dockerComposeVersion, 'services' => $services->toArray(), From 91950e189182f0f9e1a3a8e01ef4caad636be282 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 19 Mar 2024 15:37:16 +0100 Subject: [PATCH 8/9] ui: redesign --- .../Project/Shared/ScheduledTask/Add.php | 28 +- app/View/Components/Forms/Button.php | 2 +- app/View/Components/Forms/Checkbox.php | 14 +- app/View/Components/Forms/Input.php | 2 +- app/View/Components/Forms/Select.php | 2 +- app/View/Components/Forms/Textarea.php | 4 +- package-lock.json | 20 + package.json | 1 + resources/css/app.css | 163 +++++--- resources/js/components/MagicBar.vue | 1 + .../views/components/forms/checkbox.blade.php | 5 +- .../views/components/forms/input.blade.php | 4 +- resources/views/components/loading.blade.php | 15 +- resources/views/components/navbar.blade.php | 383 ++++++++---------- .../resources/breadcrumbs.blade.php | 2 +- .../views/components/slide-over.blade.php | 2 +- .../components/status/degraded.blade.php | 2 +- .../components/status/restarting.blade.php | 2 +- .../views/components/status/running.blade.php | 2 +- .../views/components/status/stopped.blade.php | 2 +- resources/views/layouts/app.blade.php | 14 +- resources/views/layouts/base.blade.php | 19 +- resources/views/livewire/dashboard.blade.php | 2 +- .../project/application/advanced.blade.php | 6 +- .../application/configuration.blade.php | 32 +- .../project/application/general.blade.php | 1 + .../views/livewire/project/edit.blade.php | 2 +- .../project/environment-edit.blade.php | 2 +- .../views/livewire/project/index.blade.php | 9 +- .../livewire/project/resource/index.blade.php | 56 +-- .../project/shared/destination.blade.php | 8 +- .../shared/environment-variable/all.blade.php | 3 +- .../shared/scheduled-task/add.blade.php | 25 +- .../shared/scheduled-task/all.blade.php | 14 +- .../views/livewire/server/index.blade.php | 1 - .../dynamic-configuration-navbar.blade.php | 2 +- .../proxy/dynamic-configurations.blade.php | 2 +- .../team-shared-variables-index.blade.php | 6 +- resources/views/livewire/upgrade.blade.php | 12 +- tailwind.config.js | 45 +- 40 files changed, 481 insertions(+), 436 deletions(-) diff --git a/app/Livewire/Project/Shared/ScheduledTask/Add.php b/app/Livewire/Project/Shared/ScheduledTask/Add.php index 3cc5428b8..3a7a3fa23 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/Add.php +++ b/app/Livewire/Project/Shared/ScheduledTask/Add.php @@ -33,19 +33,23 @@ class Add extends Component public function submit() { - $this->validate(); - $isValid = validate_cron_expression($this->frequency); - if (!$isValid) { - $this->dispatch('error', 'Invalid Cron / Human expression.'); - return; + try { + $this->validate(); + $isValid = validate_cron_expression($this->frequency); + if (!$isValid) { + $this->dispatch('error', 'Invalid Cron / Human expression.'); + return; + } + $this->dispatch('saveScheduledTask', [ + 'name' => $this->name, + 'command' => $this->command, + 'frequency' => $this->frequency, + 'container' => $this->container, + ]); + $this->clear(); + } catch (\Exception $e) { + return handleError($e, $this); } - $this->dispatch('saveScheduledTask', [ - 'name' => $this->name, - 'command' => $this->command, - 'frequency' => $this->frequency, - 'container' => $this->container, - ]); - $this->clear(); } public function clear() diff --git a/app/View/Components/Forms/Button.php b/app/View/Components/Forms/Button.php index c9f4ebdc0..350039fce 100644 --- a/app/View/Components/Forms/Button.php +++ b/app/View/Components/Forms/Button.php @@ -16,7 +16,7 @@ class Button extends Component public bool $isModal = false, public bool $noStyle = false, public ?string $modalId = null, - public string $defaultClass = "btn btn-primary btn-sm font-normal text-white normal-case no-animation rounded border-none" + public string $defaultClass = "button" ) { if ($this->noStyle) { $this->defaultClass = ""; diff --git a/app/View/Components/Forms/Checkbox.php b/app/View/Components/Forms/Checkbox.php index 0bbbc1e04..5361be4e7 100644 --- a/app/View/Components/Forms/Checkbox.php +++ b/app/View/Components/Forms/Checkbox.php @@ -12,14 +12,14 @@ class Checkbox extends Component * Create a new component instance. */ public function __construct( - public string|null $id = null, - public string|null $name = null, - public string|null $value = null, - public string|null $label = null, - public string|null $helper = null, - public string|bool $instantSave = false, + public ?string $id = null, + public ?string $name = null, + public ?string $value = null, + public ?string $label = null, + public ?string $helper = null, + public string|bool $instantSave = false, public bool $disabled = false, - public string $defaultClass = "toggle toggle-xs toggle-warning rounded disabled:bg-coolgray-200 disabled:opacity-50 placeholder:text-neutral-700", + public string $defaultClass = "border-coolgray-500 text-warning focus:ring-warning bg-coolgray-100 rounded cursor-pointer", ) { // } diff --git a/app/View/Components/Forms/Input.php b/app/View/Components/Forms/Input.php index a55f9b9d2..c1c60e8a0 100644 --- a/app/View/Components/Forms/Input.php +++ b/app/View/Components/Forms/Input.php @@ -21,7 +21,7 @@ class Input extends Component public ?string $helper = null, public bool $allowToPeak = true, 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" + public string $defaultClass = "block w-full py-1.5 rounded border-0 text-sm ring-inset ring-1 dark:ring-coolgray-300 dark:placeholder:text-neutral-700 focus:ring-2 focus:ring-inset dark:focus:ring-coolgray-500 dark:bg-coolgray-100 dark:text-white text-black dark:read-only:text-neutral-500 dark:read-only:bg-coolgray-100/20" ) { } diff --git a/app/View/Components/Forms/Select.php b/app/View/Components/Forms/Select.php index e1f2fc759..eadb8dcac 100644 --- a/app/View/Components/Forms/Select.php +++ b/app/View/Components/Forms/Select.php @@ -19,7 +19,7 @@ class Select extends Component public string|null $label = null, public string|null $helper = null, public bool $required = false, - public string $defaultClass = "select select-sm w-full rounded text-sm bg-coolgray-100 font-normal disabled:bg-coolgray-200/50 disabled:border-none" + public string $defaultClass = "block w-full py-1.5 rounded border-0 text-sm ring-inset ring-1 dark:ring-coolgray-300 dark:placeholder:text-neutral-700 focus:ring-2 focus:ring-inset dark:focus:ring-coolgray-500 dark:bg-coolgray-100 dark:text-white text-black " ) { // } diff --git a/app/View/Components/Forms/Textarea.php b/app/View/Components/Forms/Textarea.php index 8c50af533..58a1af67a 100644 --- a/app/View/Components/Forms/Textarea.php +++ b/app/View/Components/Forms/Textarea.php @@ -25,8 +25,8 @@ class Textarea extends Component public ?string $helper = null, public bool $realtimeValidation = false, 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" + public string $defaultClass = "block w-full py-1.5 rounded border-0 text-sm ring-inset ring-1 dark:ring-coolgray-300 dark:placeholder:text-neutral-700 focus:ring-2 focus:ring-inset dark:focus:ring-coolgray-500 dark:bg-coolgray-100 dark:text-white text-black dark:read-only:text-neutral-500 dark:read-only:bg-coolgray-100/20 scrollbar", + public string $defaultClassInput = "block w-full py-1.5 rounded border-0 text-sm ring-inset ring-1 dark:ring-coolgray-300 dark:placeholder:text-neutral-700 focus:ring-2 focus:ring-inset dark:focus:ring-coolgray-500 dark:bg-coolgray-100 dark:text-white text-black dark:read-only:text-neutral-500 dark:read-only:bg-coolgray-100/20" ) { // } diff --git a/package-lock.json b/package-lock.json index b2124e9df..cc9889a18 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "dependencies": { + "@tailwindcss/forms": "^0.5.7", "@tailwindcss/typography": "0.5.10", "alpinejs": "3.13.5", "daisyui": "4.7.2", @@ -484,6 +485,17 @@ "node": ">= 8" } }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz", + "integrity": "sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==", + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" + } + }, "node_modules/@tailwindcss/typography": { "version": "0.5.10", "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.10.tgz", @@ -1462,6 +1474,14 @@ "node": ">= 0.6" } }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", diff --git a/package.json b/package.json index 8568525e6..69c5c560a 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "vue": "3.4.21" }, "dependencies": { + "@tailwindcss/forms": "^0.5.7", "@tailwindcss/typography": "0.5.10", "alpinejs": "3.13.5", "daisyui": "4.7.2", diff --git a/resources/css/app.css b/resources/css/app.css index 1080a84f4..b7eec46fb 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -2,8 +2,9 @@ @tailwind components; @tailwind utilities; -html { - @apply text-neutral-400; +html, +body { + @apply text-black bg-white dark:bg-base dark:text-neutral-400; } body { @@ -18,6 +19,101 @@ button[isHighlighted] { @apply bg-coollabs hover:bg-coollabs-100; } +h1 { + @apply pb-6 text-2xl font-bold dark:text-white text-neutral-800; +} + +h2 { + @apply text-xl font-bold dark:text-white text-neutral-800; +} + +h3 { + @apply text-lg font-bold dark:text-white text-neutral-800; +} + +h4 { + @apply text-base font-bold dark:text-white text-neutral-800; +} + +a { + @apply dark:text-neutral-400 text-neutral-600; +} + +label { + @apply dark:text-neutral-400 text-neutral-600; +} + +table { + @apply min-w-full divide-y divide-coolgray-200; +} + +thead { + @apply uppercase; +} + +tbody { + @apply divide-y divide-coolgray-200; +} + +tr { + @apply text-neutral-400; +} + +tr th { + @apply px-3 py-3.5 text-left text-white; +} + +tr th:first-child { + @apply py-3.5 pl-4 pr-3 sm:pl-6; +} + +tr td { + @apply px-3 py-4 whitespace-nowrap; +} + +tr td:first-child { + @apply pl-4 pr-3 font-bold sm:pl-6; +} + +input.input-sm { + @apply pr-10; +} + +option { + @apply text-white; +} +.badge { + @apply inline-block w-3 h-3 text-xs font-bold leading-none border border-black rounded-full ; +} +.badge-success { + @apply bg-success; +} +.badge-warning { + @apply bg-warning; +} +.badge-error { + @apply bg-error; +} +.button { + @apply px-3 py-1 text-sm font-normal normal-case rounded dark:bg-coolgray-200 dark:text-white dark:hover:bg-coolgray-100; +} +[type='checkbox']:checked { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='black' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e"); +} + +.menu { + @apply flex items-center gap-1; +} +.menu-item { + @apply flex items-center w-full gap-2 px-4 py-1 min-w-48 hover:bg-coolgray-100 dark:hover:text-white; +} +.menu-item-active { + @apply rounded-none bg-coolgray-200 text-warning; +} +.icon { + @apply w-4 h-4; +} + .scrollbar { @apply scrollbar-thumb-coollabs-100 scrollbar-track-coolgray-200 scrollbar-w-2; } @@ -27,13 +123,9 @@ button[isHighlighted] { } .custom-modal { - @apply flex flex-col gap-2 px-8 py-4 border bg-base-100 border-coolgray-200; + @apply flex flex-col gap-2 px-8 py-4 border bg-coolgray-100 border-coolgray-200; } -.label-text, -label { - @apply text-neutral-400; -} .navbar-main { @apply flex items-end gap-6 py-2 border-b-2 border-solid border-coolgray-200; @@ -43,26 +135,6 @@ label { @apply w-4 text-warning; } -h1 { - @apply text-3xl font-bold text-white; -} - -h2 { - @apply text-2xl font-bold text-white; -} - -h3 { - @apply text-xl font-bold text-white; -} - -h4 { - @apply text-base font-bold text-white; -} - -a { - @apply text-neutral-400 hover:text-white link link-hover hover:bg-transparent; -} - .kbd-custom { @apply px-2 text-xs border border-dashed rounded border-neutral-700 text-warning; } @@ -125,37 +197,7 @@ a { @apply inline-block font-bold text-warning; } -table { - @apply min-w-full divide-y divide-coolgray-200; -} -thead { - @apply uppercase; -} - -tbody { - @apply divide-y divide-coolgray-200; -} - -tr { - @apply text-neutral-400; -} - -tr th { - @apply px-3 py-3.5 text-left text-white; -} - -tr th:first-child { - @apply py-3.5 pl-4 pr-3 sm:pl-6; -} - -tr td { - @apply px-3 py-4 whitespace-nowrap; -} - -tr td:first-child { - @apply pl-4 pr-3 font-bold sm:pl-6; -} .buyme { @apply block px-3 py-2 mt-10 text-sm font-semibold leading-6 text-center text-white rounded-md shadow-sm bg-coolgray-200 hover:bg-coolgray-300 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-coolgray-200 hover:no-underline; @@ -168,10 +210,3 @@ tr td:first-child { .fullscreen { @apply fixed top-0 left-0 w-full h-full z-[9999] bg-coolgray-100 overflow-y-auto scrollbar pb-4; } - -input.input-sm { - @apply pr-10; -} -option{ - @apply text-white; -} diff --git a/resources/js/components/MagicBar.vue b/resources/js/components/MagicBar.vue index 386a267b1..7fe770279 100644 --- a/resources/js/components/MagicBar.vue +++ b/resources/js/components/MagicBar.vue @@ -9,6 +9,7 @@ + /