From e86e96a29a261b6b52e08460274137fd0c146ec8 Mon Sep 17 00:00:00 2001 From: bopad Date: Wed, 12 Feb 2025 14:43:50 +0100 Subject: [PATCH 01/99] add yaml + svg --- public/svgs/denoKV.svg | 1 + templates/compose/denoKV.yaml | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 public/svgs/denoKV.svg create mode 100644 templates/compose/denoKV.yaml diff --git a/public/svgs/denoKV.svg b/public/svgs/denoKV.svg new file mode 100644 index 000000000..799fcf865 --- /dev/null +++ b/public/svgs/denoKV.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/compose/denoKV.yaml b/templates/compose/denoKV.yaml new file mode 100644 index 000000000..8709fc657 --- /dev/null +++ b/templates/compose/denoKV.yaml @@ -0,0 +1,25 @@ +# documentation: https://docs.deno.com/deploy/kv/manual/ +# slogan: The Denoland key-value database +# tags: deno, kv, key-value, database +# logo: svgs/deno.svg +# port: 4512 + +services: + denokv: + image: ghcr.io/denoland/denokv:latest + environment: + - 'ACCESS_TOKEN=${SERVICE_PASSWORD_DENOKV}' + - SERVICE_FQDN_DENOKV_4512 + volumes: + - '${COOLIFY_VOLUME_APP}:/data' + command: '--sqlite-path /data/denokv.sqlite serve --access-token ${SERVICE_PASSWORD_DENOKV}' + healthcheck: + test: + - CMD + - nc + - '-zv' + - 127.0.0.1 + - '4512' + interval: 5s + timeout: 5s + retries: 3 From 9aa945824b76a2da57ad285eed9d5dd45e2726d2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 13 Feb 2025 09:42:06 +0000 Subject: [PATCH 02/99] docs: update changelog --- CHANGELOG.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b545cfe0..eefb511d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ All notable changes to this project will be documented in this file. +## [unreleased] + +### 🚀 Features + +- *(ui)* Add top padding to pricing plans view + +### 🐛 Bug Fixes + +- Pull latest image from registry when using build server +- *(deployment)* Improve server selection for deployment cancellation +- *(deployment)* Improve log line rendering and formatting +- *(s3-storage)* Optimize team admin notification query +- *(core)* Improve connection testing with dynamic disk configuration for s3 backups + +### 🚜 Refactor + +- Use pull flag on docker compose up + +### 📚 Documentation + +- Update changelog + ## [4.0.0-beta.391] - 2025-02-04 ### 🚀 Features @@ -13,6 +35,11 @@ All notable changes to this project will be documented in this file. - *(changelog)* Add git cliff for automatic changelog generation - *(workflows)* Improve changelog generation and workflows - *(ui)* Add periodic status checking for services +- *(deployment)* Ensure private key is stored in filesystem before deployment +- *(slack)* Show message title in notification previews (#5063) +- *(i18n)* Add Arabic translations (#4991) +- *(i18n)* Add French translations (#4992) +- *(services)* Update `service-templates.json` ### 🐛 Bug Fixes @@ -22,6 +49,17 @@ All notable changes to this project will be documented in this file. - *(ui)* Simplify service templates loading logic - *(ui)* Align title and add button vertically in various views - Handle pullrequest:updated for reliable preview deployments +- *(ui)* Fix typo on team page (#5105) +- Cal.com documentation link give 404 (#5070) +- *(slack)* Notification settings URL in `HighDiskUsage` message (#5071) +- *(ui)* Correct typo in Storage delete dialog (#5061) +- *(lang)* Add missing italian translations (#5057) +- *(service)* Improve duplicati.yaml (#4971) +- *(service)* Links in homepage service (#5002) +- *(service)* Added SMTP credentials to getoutline yaml template file (#5011) +- *(service)* Added `KEY` Variable to Beszel Template (#5021) +- *(cloudflare-tunnels)* Dead links to docs (#5104) +- System-wide GitHub apps (#5114) ### 🚜 Refactor @@ -31,12 +69,16 @@ All notable changes to this project will be documented in this file. - *(services)* Reword nitropage url and slogan - *(readme)* Add Convex to special sponsors section +- Update changelog ### ⚙️ Miscellaneous Tasks - *(config)* Increase default PHP memory limit to 256M - Add openapi response - *(workflows)* Make naming more clear and remove unused code +- Bump Coolify version to 4.0.0-beta.392/393 +- *(ci)* Update changelog generation workflow to target 'next' branch +- *(ci)* Update changelog generation workflow to target main branch ## [4.0.0-beta.390] - 2025-01-28 From 67e013f52fc02dec7c11cae111faa118845fbd7a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 13 Feb 2025 12:33:46 +0000 Subject: [PATCH 03/99] docs: update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eefb511d9..9a1d56fa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,11 @@ All notable changes to this project will be documented in this file. ### 📚 Documentation - Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Rollback Coolify version to 4.0.0-beta.392 ## [4.0.0-beta.391] - 2025-02-04 From e6ddb66b2542bbf6793484a6019c5a25f8935439 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 15 Feb 2025 12:25:52 +0000 Subject: [PATCH 04/99] docs: update changelog --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a1d56fa0..bd4744596 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,20 @@ All notable changes to this project will be documented in this file. ### 🚀 Features +- *(core)* Add error logging and cron parsing to docker/server schedules + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Bump Coolify version to 4.0.0-beta.393 + +## [4.0.0-beta.392] - 2025-02-13 + +### 🚀 Features + - *(ui)* Add top padding to pricing plans view ### 🐛 Bug Fixes From e5bf2cc3900ee123f4943b346ebb67c863403053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Urs=20Kr=C3=B6ll?= <109229014+UrsKroell@users.noreply.github.com> Date: Sun, 16 Feb 2025 15:05:24 +0100 Subject: [PATCH 05/99] Add wakapi template Adds a template to create a wakapi instance --- templates/compose/wakapi.yaml | 60 +++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 templates/compose/wakapi.yaml diff --git a/templates/compose/wakapi.yaml b/templates/compose/wakapi.yaml new file mode 100644 index 000000000..45cc205ff --- /dev/null +++ b/templates/compose/wakapi.yaml @@ -0,0 +1,60 @@ +# documentation: https://wakapi.dev/ +# slogan: A minimalist, self-hosted WakaTime-compatible backend for coding statistics +# tags: productivity, self-hosted, developer-tools, time-tracker, wakatime, wakatime-api, coding-statistics, statistics, timetracking, analytics +# logo: svgs/wakapi.svg +# port: 3000 + +services: + wakapi: + image: ghcr.io/muety/wakapi:latest + environment: + - SERVICE_FQDN_WAKAPI_3000 + - TZ=${TIMEZONE:-Europe/Berlin} + + - WAKAPI_SERVER_LISTEN_IPV6="-" + - WAKAPI_ENV=${WAKAPI_ENVIRONMENT:-production} + - WAKAPI_SECURITY_PASSWORD_SALT=${SERVICE_BASE64_64_PASSWORDSALT} + - WAKAPI_SECURITY_EXPOSE_METRICS=${WAKAPI_SECURITY_EXPOSE_METRICS:-false} + + # Database configuration + - WAKAPI_DB_TYPE=postgres + - WAKAPI_DB_NAME=${WAKAPI_DB_NAME:-wakapi} + - WAKAPI_DB_USER=${SERVICE_USER_DATABASE} + - WAKAPI_DB_PASSWORD=${SERVICE_PASSWORD_DATABASE} + - WAKAPI_DB_HOST=${WAKAPI_DB_HOST:-postgres} + - WAKAPI_DB_PORT=${WAKAPI_DB_PORT:-5432} + + # SMTP configuration + - WAKAPI_MAIL_ENABLED=${WAKAPI_MAIL_ENABLED:-false} + - WAKAPI_MAIL_PROVIDER=smtp #only smtp supported + - WAKAPI_MAIL_SENDER=${WAKAPI_MAIL_SENDER} + - WAKAPI_MAIL_SMTP_HOST=${WAKAPI_MAIL_SMTP_HOST} + - WAKAPI_MAIL_SMTP_PORT=${WAKAPI_MAIL_SMTP_PORT:-587} + - WAKAPI_MAIL_SMTP_USERNAME=${WAKAPI_MAIL_SMTP_USERNAME} + - WAKAPI_MAIL_SMTP_PASSWORD=${WAKAPI_MAIL_SMTP_PASSWORD} + + volumes: + - wakapi-data:/data + depends_on: + postgres: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3000/"] + interval: 2s + timeout: 10s + retries: 15 + + postgres: + image: postgres:16-alpine + volumes: + - wakapi-postgres-data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=${SERVICE_USER_DATABASE} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_DATABASE} + - POSTGRES_DB=${WAKAPI_DB_NAME:-wakapi} + - POSTGRES_PORT=${WAKAPI_DB_PORT:-5432} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 20s + retries: 10 From cd51b94d733708db9fe359638e86545a3278ae2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Urs=20Kr=C3=B6ll?= <109229014+UrsKroell@users.noreply.github.com> Date: Sun, 16 Feb 2025 15:06:14 +0100 Subject: [PATCH 06/99] Add wakapi logo Add the svg logo for wakapi --- public/svgs/wakapi.svg | 150 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 public/svgs/wakapi.svg diff --git a/public/svgs/wakapi.svg b/public/svgs/wakapi.svg new file mode 100644 index 000000000..1f5dfb0c0 --- /dev/null +++ b/public/svgs/wakapi.svg @@ -0,0 +1,150 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 4a0cab8be3320e83a7f79defc8ab2e7b4b9c91bc Mon Sep 17 00:00:00 2001 From: Mike M Date: Sun, 16 Feb 2025 16:44:22 -0800 Subject: [PATCH 07/99] Added support for passing hd parameter to Google via existing tenant column in oauth_settings --- app/Providers/EventServiceProvider.php | 2 + bootstrap/helpers/socialite.php | 13 +++++- composer.json | 3 +- composer.lock | 43 ++++++++++++++++++- config/services.php | 8 ++++ .../views/livewire/settings-oauth.blade.php | 5 +++ 6 files changed, 71 insertions(+), 3 deletions(-) diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 428f78cb5..d76ec3037 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -11,6 +11,7 @@ use Illuminate\Foundation\Events\MaintenanceModeEnabled; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use SocialiteProviders\Authentik\AuthentikExtendSocialite; use SocialiteProviders\Azure\AzureExtendSocialite; +use SocialiteProviders\Google\GoogleExtendSocialite; use SocialiteProviders\Infomaniak\InfomaniakExtendSocialite; use SocialiteProviders\Manager\SocialiteWasCalled; @@ -26,6 +27,7 @@ class EventServiceProvider extends ServiceProvider SocialiteWasCalled::class => [ AzureExtendSocialite::class.'@handle', AuthentikExtendSocialite::class.'@handle', + GoogleExtendSocialite::class.'@handle', InfomaniakExtendSocialite::class.'@handle', ], ProxyStarted::class => [ diff --git a/bootstrap/helpers/socialite.php b/bootstrap/helpers/socialite.php index 09dffb78a..16870e33d 100644 --- a/bootstrap/helpers/socialite.php +++ b/bootstrap/helpers/socialite.php @@ -29,6 +29,18 @@ function get_socialite_provider(string $provider) return Socialite::driver('authentik')->setConfig($authentik_config); } + if ($provider == 'google') { + $google_config = new \SocialiteProviders\Manager\Config( + $oauth_setting->client_id, + $oauth_setting->client_secret, + $oauth_setting->redirect_uri + ); + + return Socialite::driver('google') + ->setConfig($google_config) + ->with(['hd' => $oauth_setting->tenant]); + } + $config = [ 'client_id' => $oauth_setting->client_id, 'client_secret' => $oauth_setting->client_secret, @@ -39,7 +51,6 @@ function get_socialite_provider(string $provider) 'bitbucket' => \Laravel\Socialite\Two\BitbucketProvider::class, 'github' => \Laravel\Socialite\Two\GithubProvider::class, 'gitlab' => \Laravel\Socialite\Two\GitlabProvider::class, - 'google' => \Laravel\Socialite\Two\GoogleProvider::class, 'infomaniak' => \SocialiteProviders\Infomaniak\Provider::class, ]; diff --git a/composer.json b/composer.json index f01913b5f..e5aeb6126 100644 --- a/composer.json +++ b/composer.json @@ -40,6 +40,7 @@ "resend/resend-laravel": "^0.15.0", "sentry/sentry-laravel": "^4.6", "socialiteproviders/authentik": "^5.2", + "socialiteproviders/google": "^4.1", "socialiteproviders/infomaniak": "^4.0", "socialiteproviders/microsoft-azure": "^5.1", "spatie/laravel-activitylog": "^4.7.3", @@ -125,4 +126,4 @@ "@php artisan key:generate --ansi" ] } -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index 97b40f7c7..5a7e04bbc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9c1a0833be38d1f058f216dcaa522077", + "content-hash": "dcf6b2f554372a570628d7f85184df7b", "packages": [ { "name": "3sidedcube/laravel-redoc", @@ -7474,6 +7474,47 @@ }, "time": "2023-11-07T22:21:16+00:00" }, + { + "name": "socialiteproviders/google", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/SocialiteProviders/Google-Plus.git", + "reference": "1cb8f6fb2c0dd0fc8b34e95f69865663fdf0b401" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SocialiteProviders/Google-Plus/zipball/1cb8f6fb2c0dd0fc8b34e95f69865663fdf0b401", + "reference": "1cb8f6fb2c0dd0fc8b34e95f69865663fdf0b401", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.2 || ^8.0", + "socialiteproviders/manager": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "SocialiteProviders\\Google\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "xstoop", + "email": "myenglishnameisx@gmail.com" + } + ], + "description": "Google OAuth2 Provider for Laravel Socialite", + "support": { + "source": "https://github.com/SocialiteProviders/Google-Plus/tree/4.1.0" + }, + "time": "2020-12-01T23:10:59+00:00" + }, { "name": "socialiteproviders/infomaniak", "version": "4.0.0", diff --git a/config/services.php b/config/services.php index 46fd12ec3..d1c4a3699 100644 --- a/config/services.php +++ b/config/services.php @@ -45,4 +45,12 @@ return [ 'client_secret' => env('AUTHENTIK_CLIENT_SECRET'), 'redirect' => env('AUTHENTIK_REDIRECT_URI'), ], + + 'google' => [ + 'client_id' => env('GOOGLE_CLIENT_ID'), + 'client_secret' => env('GOOGLE_CLIENT_SECRET'), + 'redirect' => env('GOOGLE_REDIRECT_URI'), + 'tenant' => env('GOOGLE_TENANT'), + ], + ]; diff --git a/resources/views/livewire/settings-oauth.blade.php b/resources/views/livewire/settings-oauth.blade.php index 2f0d28cfc..7062ef4d4 100644 --- a/resources/views/livewire/settings-oauth.blade.php +++ b/resources/views/livewire/settings-oauth.blade.php @@ -32,6 +32,11 @@ @endif + @if ($oauth_setting->provider == 'google') + + @endif @if ($oauth_setting->provider == 'authentik') From ee130da0ccd1b8ea9bf6ee1e9ab9b3df9ab13051 Mon Sep 17 00:00:00 2001 From: phenomen Date: Sun, 16 Feb 2025 20:36:04 -0600 Subject: [PATCH 08/99] Update Foundry VTT template --- templates/compose/foundryvtt.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/templates/compose/foundryvtt.yaml b/templates/compose/foundryvtt.yaml index 5cf961a37..75b86841f 100644 --- a/templates/compose/foundryvtt.yaml +++ b/templates/compose/foundryvtt.yaml @@ -39,12 +39,17 @@ services: - FOUNDRY_MINIFY_STATIC_FILES=${FOUNDRY_MINIFY_STATIC_FILES:-true} # The world ID to startup at system start. - FOUNDRY_WORLD=${FOUNDRY_WORLD} + # Optional telemetry. - FOUNDRY_TELEMETRY=${FOUNDRY_TELEMETRY:-false} + # The timezone to use for the server. - TIMEZONE=${TIMEZONE:-UTC} # Set a path to cache downloads of the Foundry distribution archive and speed up subsequent container startups. - CONTAINER_CACHE=/data/container_cache volumes: - - foundryvtt-data:/data + - type: bind + source: ${FOUNDRY_DATA:-/data/foundryvtt} + target: /data + is_directory: true healthcheck: test: ["CMD", "curl", "-f", "http://127.0.0.1:30000"] timeout: 5s From 49f159b38072efc6b2ff62b1cc7a5341b1cb1ab8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Feb 2025 09:17:13 +0000 Subject: [PATCH 09/99] docs: update changelog --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd4744596..bb6fb0a41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file. ## [unreleased] +### 🐛 Bug Fixes + +- *(core)* Update service status refresh event handling +- *(ui)* Adjust polling intervals for database and service status checks + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Bump Coolify version to 4.0.0-beta.394 + +## [4.0.0-beta.393] - 2025-02-15 + ### 🚀 Features - *(core)* Add error logging and cron parsing to docker/server schedules From ca380213d51499394f2dad2f29f142b7d53137dd Mon Sep 17 00:00:00 2001 From: Manish Gupta <59428681+mguptahub@users.noreply.github.com> Date: Mon, 17 Feb 2025 15:49:19 +0530 Subject: [PATCH 10/99] updated 'plane.yaml' to use APP_RELEASE environment variable --- templates/compose/plane.yaml | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/templates/compose/plane.yaml b/templates/compose/plane.yaml index fc62cb122..d1fcf78fa 100644 --- a/templates/compose/plane.yaml +++ b/templates/compose/plane.yaml @@ -5,6 +5,7 @@ x-app-env: &app-env environment: + - APP_RELEASE=${APP_RELEASE:-v0.24.1} - WEB_URL=${SERVICE_FQDN_PLANE} - DEBUG=${DEBUG:-0} - CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGIN:-http://localhost} @@ -54,7 +55,7 @@ services: - SERVICE_FQDN_PLANE - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880} - BUCKET_NAME=${BUCKET_NAME:-uploads} - image: makeplane/plane-proxy:stable + image: makeplane/plane-proxy:${APP_RELEASE:-v0.24.1} depends_on: - web - api @@ -66,8 +67,7 @@ services: retries: 15 web: - <<: *app-env - image: makeplane/plane-frontend:stable + image: makeplane/plane-frontend:${APP_RELEASE:-v0.24.1} command: node web/server.js web depends_on: - api @@ -78,8 +78,7 @@ services: timeout: 10s retries: 15 space: - <<: *app-env - image: makeplane/plane-space:stable + image: makeplane/plane-space:${APP_RELEASE:-v0.24.1} command: node space/server.js space depends_on: - api @@ -92,8 +91,7 @@ services: retries: 15 admin: - <<: *app-env - image: makeplane/plane-admin:stable + image: makeplane/plane-admin:${APP_RELEASE:-v0.24.1} command: node admin/server.js admin depends_on: - api @@ -106,7 +104,7 @@ services: live: <<: *app-env - image: makeplane/plane-live:stable + image: makeplane/plane-live:${APP_RELEASE:-v0.24.1} command: node live/dist/server.js live depends_on: - api @@ -119,7 +117,7 @@ services: api: <<: *app-env - image: makeplane/plane-backend:stable + image: makeplane/plane-backend:${APP_RELEASE:-v0.24.1} command: ./bin/docker-entrypoint-api.sh volumes: - logs_api:/code/plane/logs @@ -134,7 +132,7 @@ services: worker: <<: *app-env - image: makeplane/plane-backend:stable + image: makeplane/plane-backend:${APP_RELEASE:-v0.24.1} command: ./bin/docker-entrypoint-worker.sh volumes: - logs_worker:/code/plane/logs @@ -150,7 +148,7 @@ services: beat-worker: <<: *app-env - image: makeplane/plane-backend:stable + image: makeplane/plane-backend:${APP_RELEASE:-v0.24.1} command: ./bin/docker-entrypoint-beat.sh volumes: - logs_beat-worker:/code/plane/logs @@ -166,7 +164,7 @@ services: migrator: <<: *app-env - image: makeplane/plane-backend:stable + image: makeplane/plane-backend:${APP_RELEASE:-v0.24.1} restart: "no" command: ./bin/docker-entrypoint-migrator.sh volumes: From 0d12b8296e4d4f91517a4a7d4518df2b169787de Mon Sep 17 00:00:00 2001 From: "Gauthier A." Date: Mon, 17 Feb 2025 23:10:21 +0100 Subject: [PATCH 11/99] fix wrong database container name + code simplification --- app/Actions/Database/StartDatabaseProxy.php | 68 ++++----------------- 1 file changed, 11 insertions(+), 57 deletions(-) diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index d9272356c..14be9d2bc 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -22,74 +22,28 @@ class StartDatabaseProxy public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse|ServiceDatabase $database) { - $internalPort = null; - $type = $database->getMorphClass(); + $databaseType = $database->database_type; $network = data_get($database, 'destination.network'); $server = data_get($database, 'destination.server'); $containerName = data_get($database, 'uuid'); $proxyContainerName = "{$database->uuid}-proxy"; + if ($database->getMorphClass() === \App\Models\ServiceDatabase::class) { $databaseType = $database->databaseType(); // $connectPredefined = data_get($database, 'service.connect_to_docker_network'); $network = $database->service->uuid; $server = data_get($database, 'service.destination.server'); $proxyContainerName = "{$database->service->uuid}-proxy"; - switch ($databaseType) { - case 'standalone-mariadb': - $type = \App\Models\StandaloneMariadb::class; - $containerName = "mariadb-{$database->service->uuid}"; - break; - case 'standalone-mongodb': - $type = \App\Models\StandaloneMongodb::class; - $containerName = "mongodb-{$database->service->uuid}"; - break; - case 'standalone-mysql': - $type = \App\Models\StandaloneMysql::class; - $containerName = "mysql-{$database->service->uuid}"; - break; - case 'standalone-postgresql': - $type = \App\Models\StandalonePostgresql::class; - $containerName = "postgresql-{$database->service->uuid}"; - break; - case 'standalone-redis': - $type = \App\Models\StandaloneRedis::class; - $containerName = "redis-{$database->service->uuid}"; - break; - case 'standalone-keydb': - $type = \App\Models\StandaloneKeydb::class; - $containerName = "keydb-{$database->service->uuid}"; - break; - case 'standalone-dragonfly': - $type = \App\Models\StandaloneDragonfly::class; - $containerName = "dragonfly-{$database->service->uuid}"; - break; - case 'standalone-clickhouse': - $type = \App\Models\StandaloneClickhouse::class; - $containerName = "clickhouse-{$database->service->uuid}"; - break; - case 'standalone-supabase/postgres': - $type = \App\Models\StandalonePostgresql::class; - $containerName = "supabase-db-{$database->service->uuid}"; - break; - } - } - if ($type === \App\Models\StandaloneRedis::class) { - $internalPort = 6379; - } elseif ($type === \App\Models\StandalonePostgresql::class) { - $internalPort = 5432; - } elseif ($type === \App\Models\StandaloneMongodb::class) { - $internalPort = 27017; - } elseif ($type === \App\Models\StandaloneMysql::class) { - $internalPort = 3306; - } elseif ($type === \App\Models\StandaloneMariadb::class) { - $internalPort = 3306; - } elseif ($type === \App\Models\StandaloneKeydb::class) { - $internalPort = 6379; - } elseif ($type === \App\Models\StandaloneDragonfly::class) { - $internalPort = 6379; - } elseif ($type === \App\Models\StandaloneClickhouse::class) { - $internalPort = 9000; + $containerName = "{$database->name}-{$database->service->uuid}"; } + + $internalPort = match ($databaseType) { + 'standalone-mariadb', 'standalone-mysql' => 3306, + 'standalone-postgresql', 'standalone-supabase/postgres' => 5432, + 'standalone-redis', 'standalone-keydb', 'standalone-dragonfly' => 6379, + 'standalone-clickhouse' => 9000, + }; + $configuration_dir = database_proxy_dir($database->uuid); $nginxconf = << Date: Sat, 22 Feb 2025 12:50:56 +0100 Subject: [PATCH 12/99] chore: bump Coolify version to 4.0.0-beta.395 --- config/constants.php | 2 +- versions.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/constants.php b/config/constants.php index 4a10d22ef..eedb348f7 100644 --- a/config/constants.php +++ b/config/constants.php @@ -2,7 +2,7 @@ return [ 'coolify' => [ - 'version' => '4.0.0-beta.394', + 'version' => '4.0.0-beta.395', 'helper_version' => '1.0.6', 'realtime_version' => '1.0.5', 'self_hosted' => env('SELF_HOSTED', true), diff --git a/versions.json b/versions.json index 9d3522fbe..4070c932e 100644 --- a/versions.json +++ b/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.394" + "version": "4.0.0-beta.395" }, "nightly": { - "version": "4.0.0-beta.395" + "version": "4.0.0-beta.396" }, "helper": { "version": "1.0.6" From 40ad118492750f7158312e9680cbf8e8aac085ef Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 22 Feb 2025 12:51:22 +0100 Subject: [PATCH 13/99] fix(core): add server functionality check before dispatching container status --- app/Livewire/Project/Database/Heading.php | 6 ++++-- app/Livewire/Project/Service/Configuration.php | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/Livewire/Project/Database/Heading.php b/app/Livewire/Project/Database/Heading.php index fc0febd02..c3b57b9f4 100644 --- a/app/Livewire/Project/Database/Heading.php +++ b/app/Livewire/Project/Database/Heading.php @@ -43,8 +43,10 @@ class Heading extends Component public function check_status($showNotification = false) { - GetContainersStatus::run($this->database->destination->server); - $this->database->refresh(); + if ($this->database->destination->server->isFunctional()) { + GetContainersStatus::dispatch($this->database->destination->server); + } + if ($showNotification) { $this->dispatch('success', 'Database status updated.'); } diff --git a/app/Livewire/Project/Service/Configuration.php b/app/Livewire/Project/Service/Configuration.php index b36a860ce..da49dcae9 100644 --- a/app/Livewire/Project/Service/Configuration.php +++ b/app/Livewire/Project/Service/Configuration.php @@ -92,7 +92,9 @@ class Configuration extends Component public function check_status() { try { - GetContainersStatus::run($this->service->server); + if ($this->service->server->isFunctional()) { + GetContainersStatus::dispatch($this->service->server); + } $this->service->applications->each(function ($application) { $application->refresh(); }); From d9a7c78e6f4a9dd67c8c33bcd100ffea395a0aa3 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 22 Feb 2025 13:04:41 +0100 Subject: [PATCH 14/99] fix(ui): disable sticky scroll in Monaco editor --- resources/views/components/forms/monaco-editor.blade.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/views/components/forms/monaco-editor.blade.php b/resources/views/components/forms/monaco-editor.blade.php index 690e654d4..811953153 100644 --- a/resources/views/components/forms/monaco-editor.blade.php +++ b/resources/views/components/forms/monaco-editor.blade.php @@ -57,7 +57,8 @@ language: '{{ $language }}', domReadOnly: '{{ $readonly ?? false }}', contextmenu: '!{{ $readonly ?? false }}', - renderLineHighlight: '{{ $readonly ?? false }} ? none : all' + renderLineHighlight: '{{ $readonly ?? false }} ? none : all', + stickyScroll: { enabled: false } }); const observer = new MutationObserver((mutations) => { From d82be931cda525dcf45d6739ea45a52ed7e61b3a Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 22 Feb 2025 13:04:46 +0100 Subject: [PATCH 15/99] feat(ui): add textarea switching option in service compose editor --- .../project/service/edit-compose.blade.php | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/resources/views/livewire/project/service/edit-compose.blade.php b/resources/views/livewire/project/service/edit-compose.blade.php index a99c117fb..beaccac91 100644 --- a/resources/views/livewire/project/service/edit-compose.blade.php +++ b/resources/views/livewire/project/service/edit-compose.blade.php @@ -1,22 +1,33 @@ -
+
Volume names are updated upon save. The service UUID will be added as a prefix to all volumes, to prevent name collision.
To see the actual volume names, check the Deployable Compose file, or go to Storage menu.
- - +
+ + +
+
+ + +
-
+
+
+
+ Switch + Textarea +
From de299839f4b9ba02df237fa05169909a3815f568 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 22 Feb 2025 12:12:37 +0000 Subject: [PATCH 16/99] docs: update changelog --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb6fb0a41..ed72adb84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file. ## [unreleased] +### 🚀 Features + +- *(core)* Prevent using servers with existing resources as build servers +- *(ui)* Add textarea switching option in service compose editor + +### 🐛 Bug Fixes + +- *(service)* Update Fider service template healthcheck command +- *(core)* Improve server selection error handling in Docker component +- *(core)* Add server functionality check before dispatching container status +- *(ui)* Disable sticky scroll in Monaco editor + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Bump Coolify version to 4.0.0-beta.395 + +## [4.0.0-beta.394] - 2025-02-17 + ### 🐛 Bug Fixes - *(core)* Update service status refresh event handling From b0853046c23df32fb6d785987c213ab3e7a59819 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 22 Feb 2025 13:31:45 +0100 Subject: [PATCH 17/99] chore: bump Coolify version to 4.0.0-beta.396 --- config/constants.php | 2 +- versions.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/constants.php b/config/constants.php index eedb348f7..24cc25768 100644 --- a/config/constants.php +++ b/config/constants.php @@ -2,7 +2,7 @@ return [ 'coolify' => [ - 'version' => '4.0.0-beta.395', + 'version' => '4.0.0-beta.396', 'helper_version' => '1.0.6', 'realtime_version' => '1.0.5', 'self_hosted' => env('SELF_HOSTED', true), diff --git a/versions.json b/versions.json index 4070c932e..6073acfad 100644 --- a/versions.json +++ b/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.395" + "version": "4.0.0-beta.396" }, "nightly": { - "version": "4.0.0-beta.396" + "version": "4.0.0-beta.397" }, "helper": { "version": "1.0.6" From 693c7c4cb3913816bf7a69a0d7f644321cadd6d9 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 22 Feb 2025 13:32:10 +0100 Subject: [PATCH 18/99] fix(ui): Add literal and multiline env support to services. --- .../project/shared/environment-variable/show.blade.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/views/livewire/project/shared/environment-variable/show.blade.php b/resources/views/livewire/project/shared/environment-variable/show.blade.php index a005728ed..e3130e805 100644 --- a/resources/views/livewire/project/shared/environment-variable/show.blade.php +++ b/resources/views/livewire/project/shared/environment-variable/show.blade.php @@ -47,6 +47,10 @@ + + @else @if ($is_shared) Date: Mon, 24 Feb 2025 17:39:03 +0100 Subject: [PATCH 19/99] fix(services): Owncloud docs link --- templates/compose/owncloud.yaml | 2 +- templates/service-templates.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/compose/owncloud.yaml b/templates/compose/owncloud.yaml index 8d65f6c60..511397349 100644 --- a/templates/compose/owncloud.yaml +++ b/templates/compose/owncloud.yaml @@ -1,4 +1,4 @@ -# documentation: https://owncloud.com/docs +# documentation: https://owncloud.com/docs-guides/ # slogan: OwnCloud with Open Web UI integrates file management with a powerful, user-friendly interface. # tags: owncloud,file-management,open-web-ui,integration,cloud # logo: svgs/owncloud.svg diff --git a/templates/service-templates.json b/templates/service-templates.json index 0e151805b..83ce320fd 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -2324,7 +2324,7 @@ "port": "5055" }, "owncloud": { - "documentation": "https://owncloud.com/docs?utm_source=coolify.io", + "documentation": "https://owncloud.com/docs-guides/?utm_source=coolify.io", "slogan": "OwnCloud with Open Web UI integrates file management with a powerful, user-friendly interface.", "compose": "c2VydmljZXM6CiAgb3duY2xvdWQ6CiAgICBpbWFnZTogJ293bmNsb3VkL3NlcnZlcjpsYXRlc3QnCiAgICBkZXBlbmRzX29uOgogICAgICBtYXJpYWRiOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICAgIHJlZGlzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fT1dOQ0xPVURfODA4MAogICAgICAtICdPV05DTE9VRF9ET01BSU49JHtTRVJWSUNFX0ZRRE5fT1dOQ0xPVUR9JwogICAgICAtICdPV05DTE9VRF9UUlVTVEVEX0RPTUFJTlM9JHtTRVJWSUNFX1VSTF9PV05DTE9VRH0nCiAgICAgIC0gT1dOQ0xPVURfREJfVFlQRT1teXNxbAogICAgICAtIE9XTkNMT1VEX0RCX0hPU1Q9bWFyaWFkYgogICAgICAtICdPV05DTE9VRF9EQl9OQU1FPSR7REJfTkFNRTotb3duY2xvdWR9JwogICAgICAtICdPV05DTE9VRF9EQl9VU0VSTkFNRT0ke1NFUlZJQ0VfVVNFUl9NQVJJQURCfScKICAgICAgLSAnT1dOQ0xPVURfREJfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01BUklBREJ9JwogICAgICAtICdPV05DTE9VRF9BRE1JTl9VU0VSTkFNRT0ke1NFUlZJQ0VfVVNFUl9PV05DTE9VRH0nCiAgICAgIC0gJ09XTkNMT1VEX0FETUlOX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9PV05DTE9VRH0nCiAgICAgIC0gJ09XTkNMT1VEX01ZU1FMX1VURjhNQjQ9JHtNWVNRTF9VVEY4TUI0Oi10cnVlfScKICAgICAgLSAnT1dOQ0xPVURfUkVESVNfRU5BQkxFRD0ke1JFRElTX0VOQUJMRUQ6LXRydWV9JwogICAgICAtIE9XTkNMT1VEX1JFRElTX0hPU1Q9cmVkaXMKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSAvdXNyL2Jpbi9oZWFsdGhjaGVjawogICAgICBpbnRlcnZhbDogMzBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiA1CiAgICB2b2x1bWVzOgogICAgICAtICdvd25jbG91ZC1kYXRhOi9tbnQvZGF0YScKICBtYXJpYWRiOgogICAgaW1hZ2U6ICdtYXJpYWRiOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtICdNWVNRTF9ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NQVJJQURCUk9PVH0nCiAgICAgIC0gJ01ZU1FMX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUFSSUFEQn0nCiAgICAgIC0gJ01ZU1FMX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NQVJJQURCfScKICAgICAgLSAnTVlTUUxfREFUQUJBU0U9JHtEQl9OQU1FOi1vd25jbG91ZH0nCiAgICAgIC0gVFo9YXV0bwogICAgY29tbWFuZDoKICAgICAgLSAnLS1jaGFyYWN0ZXItc2V0LXNlcnZlcj11dGY4bWI0JwogICAgICAtICctLWNvbGxhdGlvbi1zZXJ2ZXI9dXRmOG1iNF9iaW4nCiAgICAgIC0gJy0tbWF4LWFsbG93ZWQtcGFja2V0PTEyOE0nCiAgICAgIC0gJy0taW5ub2RiLWxvZy1maWxlLXNpemU9NjRNJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGhlYWx0aGNoZWNrLnNoCiAgICAgICAgLSAnLS1jb25uZWN0JwogICAgICAgIC0gJy0taW5ub2RiX2luaXRpYWxpemVkJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCiAgICB2b2x1bWVzOgogICAgICAtICdvd25jbG91ZC1teXNxbC1kYXRhOi92YXIvbGliL215c3FsJwogIHJlZGlzOgogICAgaW1hZ2U6ICdyZWRpczo2JwogICAgY29tbWFuZDoKICAgICAgLSAnLS1kYXRhYmFzZXMnCiAgICAgIC0gJzEnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gcmVkaXMtY2xpCiAgICAgICAgLSBwaW5nCiAgICAgIGludGVydmFsOiAxMHMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogNQo=", "tags": [ From 86ad8a78271e3d97069d746c808f0f5c5132878a Mon Sep 17 00:00:00 2001 From: Zakher Masri <46135573+zaaakher@users.noreply.github.com> Date: Mon, 24 Feb 2025 19:41:48 +0300 Subject: [PATCH 20/99] fix(template): remove db-migration step from `infisical.yaml` (#5209) --- CHANGELOG.md | 98 ++++++++++++++++++++++++++++++++ templates/compose/infisical.yaml | 24 +++----- 2 files changed, 106 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b545cfe0..ed72adb84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,84 @@ All notable changes to this project will be documented in this file. +## [unreleased] + +### 🚀 Features + +- *(core)* Prevent using servers with existing resources as build servers +- *(ui)* Add textarea switching option in service compose editor + +### 🐛 Bug Fixes + +- *(service)* Update Fider service template healthcheck command +- *(core)* Improve server selection error handling in Docker component +- *(core)* Add server functionality check before dispatching container status +- *(ui)* Disable sticky scroll in Monaco editor + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Bump Coolify version to 4.0.0-beta.395 + +## [4.0.0-beta.394] - 2025-02-17 + +### 🐛 Bug Fixes + +- *(core)* Update service status refresh event handling +- *(ui)* Adjust polling intervals for database and service status checks + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Bump Coolify version to 4.0.0-beta.394 + +## [4.0.0-beta.393] - 2025-02-15 + +### 🚀 Features + +- *(core)* Add error logging and cron parsing to docker/server schedules + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Bump Coolify version to 4.0.0-beta.393 + +## [4.0.0-beta.392] - 2025-02-13 + +### 🚀 Features + +- *(ui)* Add top padding to pricing plans view + +### 🐛 Bug Fixes + +- Pull latest image from registry when using build server +- *(deployment)* Improve server selection for deployment cancellation +- *(deployment)* Improve log line rendering and formatting +- *(s3-storage)* Optimize team admin notification query +- *(core)* Improve connection testing with dynamic disk configuration for s3 backups + +### 🚜 Refactor + +- Use pull flag on docker compose up + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Rollback Coolify version to 4.0.0-beta.392 + ## [4.0.0-beta.391] - 2025-02-04 ### 🚀 Features @@ -13,6 +91,11 @@ All notable changes to this project will be documented in this file. - *(changelog)* Add git cliff for automatic changelog generation - *(workflows)* Improve changelog generation and workflows - *(ui)* Add periodic status checking for services +- *(deployment)* Ensure private key is stored in filesystem before deployment +- *(slack)* Show message title in notification previews (#5063) +- *(i18n)* Add Arabic translations (#4991) +- *(i18n)* Add French translations (#4992) +- *(services)* Update `service-templates.json` ### 🐛 Bug Fixes @@ -22,6 +105,17 @@ All notable changes to this project will be documented in this file. - *(ui)* Simplify service templates loading logic - *(ui)* Align title and add button vertically in various views - Handle pullrequest:updated for reliable preview deployments +- *(ui)* Fix typo on team page (#5105) +- Cal.com documentation link give 404 (#5070) +- *(slack)* Notification settings URL in `HighDiskUsage` message (#5071) +- *(ui)* Correct typo in Storage delete dialog (#5061) +- *(lang)* Add missing italian translations (#5057) +- *(service)* Improve duplicati.yaml (#4971) +- *(service)* Links in homepage service (#5002) +- *(service)* Added SMTP credentials to getoutline yaml template file (#5011) +- *(service)* Added `KEY` Variable to Beszel Template (#5021) +- *(cloudflare-tunnels)* Dead links to docs (#5104) +- System-wide GitHub apps (#5114) ### 🚜 Refactor @@ -31,12 +125,16 @@ All notable changes to this project will be documented in this file. - *(services)* Reword nitropage url and slogan - *(readme)* Add Convex to special sponsors section +- Update changelog ### ⚙️ Miscellaneous Tasks - *(config)* Increase default PHP memory limit to 256M - Add openapi response - *(workflows)* Make naming more clear and remove unused code +- Bump Coolify version to 4.0.0-beta.392/393 +- *(ci)* Update changelog generation workflow to target 'next' branch +- *(ci)* Update changelog generation workflow to target main branch ## [4.0.0-beta.390] - 2025-01-28 diff --git a/templates/compose/infisical.yaml b/templates/compose/infisical.yaml index f77c76974..8384a6549 100644 --- a/templates/compose/infisical.yaml +++ b/templates/compose/infisical.yaml @@ -14,6 +14,12 @@ services: - NODE_ENV=${NODE_ENV:-production} - ENCRYPTION_KEY=${SERVICE_PASSWORD_ENCRYPTIONKEY} - AUTH_SECRET=${SERVICE_REALBASE64_64_AUTHSECRET} + - SMTP_HOST=${SMTP_HOST} + - SMTP_USERNAME=${SMTP_USERNAME} + - SMTP_PASSWORD=${SMTP_PASSWORD} + - SMTP_PORT=${SMTP_PORT} + - SMTP_FROM_ADDRESS=${SMTP_FROM_ADDRESS} + - SMTP_FROM_NAME=${SMTP_FROM_NAME} - DB_CONNECTION_URI=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@db:5432/${POSTGRES_DB} - REDIS_URL=redis://redis:6379 healthcheck: @@ -23,8 +29,8 @@ services: depends_on: redis: condition: service_healthy - db-migration: - condition: service_completed_successfully + db: + condition: service_healthy redis: image: "redis:7" volumes: @@ -53,17 +59,3 @@ services: interval: 5s timeout: 10s retries: 10 - db-migration: - exclude_from_hc: true - image: "infisical/infisical:latest-postgres" - depends_on: - db: - condition: service_healthy - command: "npm run migration:latest" - restart: on-failure - environment: - - POSTGRES_USER=${SERVICE_USER_POSTGRES} - - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} - - POSTGRES_DB=${POSTGRES_DB:-infisical} - - DB_CONNECTION_URI=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@db:5432/${POSTGRES_DB:-infisical} - - REDIS_URL=redis://redis:6379 From f3cdcd02b52721bc5c29a51f253828d5e0c55c40 Mon Sep 17 00:00:00 2001 From: Venom Date: Mon, 24 Feb 2025 16:47:01 +0000 Subject: [PATCH 21/99] chore(services): Update zipline to use new Database env var. (#5210) --- templates/compose/zipline.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/compose/zipline.yaml b/templates/compose/zipline.yaml index c5efc4058..169545df7 100644 --- a/templates/compose/zipline.yaml +++ b/templates/compose/zipline.yaml @@ -11,6 +11,7 @@ services: - SERVICE_FQDN_ZIPLINE_3000 - CORE_RETURN_HTTPS=${CORE_RETURN_HTTPS:-false} - CORE_SECRET=${SERVICE_PASSWORD_64_ZIPLINE} + - DATABASE_URL=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@postgres/${POSTGRES_DB:-zipline-db} - CORE_DATABASE_URL=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@postgres/${POSTGRES_DB:-zipline-db} - CORE_LOGGER=${CORE_LOGGER:-true} # Default credentials are "administrator" and "password" From 6c9b0245d18efa4bb01c381c9bb4e9e084ef38b5 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:48:08 +0100 Subject: [PATCH 22/99] chore(service): upgrade authentik service --- templates/compose/authentik.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/compose/authentik.yaml b/templates/compose/authentik.yaml index 87942fffb..7cf501803 100644 --- a/templates/compose/authentik.yaml +++ b/templates/compose/authentik.yaml @@ -6,7 +6,7 @@ services: authentik-server: - image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2024.12.2} + image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.2.0} restart: unless-stopped command: server environment: @@ -35,7 +35,7 @@ services: redis: condition: service_healthy authentik-worker: - image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2024.12.2} + image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.2.0} restart: unless-stopped command: worker environment: From a0f2c361ef112bbe4406dd98a213e1b83814080c Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:48:34 +0100 Subject: [PATCH 23/99] chore(service): remove unused env from zipline --- templates/compose/zipline.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/compose/zipline.yaml b/templates/compose/zipline.yaml index 169545df7..708f0e342 100644 --- a/templates/compose/zipline.yaml +++ b/templates/compose/zipline.yaml @@ -12,7 +12,6 @@ services: - CORE_RETURN_HTTPS=${CORE_RETURN_HTTPS:-false} - CORE_SECRET=${SERVICE_PASSWORD_64_ZIPLINE} - DATABASE_URL=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@postgres/${POSTGRES_DB:-zipline-db} - - CORE_DATABASE_URL=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@postgres/${POSTGRES_DB:-zipline-db} - CORE_LOGGER=${CORE_LOGGER:-true} # Default credentials are "administrator" and "password" volumes: From d2032b049b2560ba6120ff072353bfede5ded035 Mon Sep 17 00:00:00 2001 From: "Stew Night." <22344601+stewnight@users.noreply.github.com> Date: Tue, 25 Feb 2025 05:58:34 +1300 Subject: [PATCH 24/99] fix(service): Penpot (#5047) --- templates/compose/penpot.yaml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/templates/compose/penpot.yaml b/templates/compose/penpot.yaml index 72736ab48..fa92abb7f 100644 --- a/templates/compose/penpot.yaml +++ b/templates/compose/penpot.yaml @@ -2,7 +2,7 @@ # slogan: Penpot is the first Open Source design and prototyping platform for product teams. # tags: penpot,design,prototyping,figma,open,source # logo: svgs/penpot.svg -# port: 80 +# port: 8080 services: frontend: @@ -15,10 +15,10 @@ services: penpot-exporter: condition: service_healthy environment: - - SERVICE_FQDN_FRONTEND + - SERVICE_FQDN_FRONTEND_8080 - PENPOT_FLAGS=${PENPOT_FRONTEND_FLAGS:-enable-login-with-password} healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:80"] + test: ['CMD', 'curl', '-f', 'http://127.0.0.1:8080'] interval: 2s timeout: 10s retries: 15 @@ -36,7 +36,7 @@ services: - PENPOT_FLAGS=${PENPOT_BACKEND_FLAGS:-enable-login-with-password enable-smtp enable-prepl-server} - PENPOT_HTTP_SERVER_PORT=6060 - PENPOT_SECRET_KEY=$SERVICE_REALBASE64_64_PENPOT - - PENPOT_PUBLIC_URI=$SERVICE_FQDN_FRONTEND + - PENPOT_PUBLIC_URI=$SERVICE_FQDN_FRONTEND_8080 - PENPOT_BACKEND_URI=http://penpot-backend - PENPOT_EXPORTER_URI=http://penpot-exporter - PENPOT_DATABASE_URI=postgresql://postgres/${POSTGRES_DB:-penpot} @@ -55,18 +55,18 @@ services: - PENPOT_SMTP_TLS=${PENPOT_SMTP_TLS:-false} - PENPOT_SMTP_SSL=${PENPOT_SMTP_SSL:-false} healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:6060/readyz"] - interval: 2s - timeout: 10s + test: ['CMD', 'curl', '-f', 'http://127.0.0.1:6060/readyz'] + interval: 10s + timeout: 30s retries: 15 penpot-exporter: image: penpotapp/exporter:latest environment: - - PENPOT_PUBLIC_URI=$SERVICE_FQDN_FRONTEND + - PENPOT_PUBLIC_URI=$SERVICE_FQDN_FRONTEND_8080 - PENPOT_REDIS_URI=redis://redis/0 healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:6061/readyz"] + test: ['CMD', 'curl', '-f', 'http://127.0.0.1:6061/readyz'] interval: 2s timeout: 10s retries: 15 @@ -76,7 +76,7 @@ services: environment: - SERVICE_FQDN_MAILPIT_8025 healthcheck: - test: ["CMD", "/mailpit", "readyz"] + test: ['CMD', '/mailpit', 'readyz'] interval: 5s timeout: 20s retries: 10 @@ -91,7 +91,7 @@ services: - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES - POSTGRES_DB=${POSTGRES_DB:-penpot} healthcheck: - test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + test: ['CMD-SHELL', 'pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}'] interval: 5s timeout: 20s retries: 10 @@ -102,7 +102,7 @@ services: volumes: - penpot-redis-data:/data healthcheck: - test: ["CMD", "redis-cli", "ping"] + test: ['CMD', 'redis-cli', 'ping'] interval: 5s timeout: 20s retries: 10 From b9e6d9db7361ae3219892812adcff3f2797ff4c7 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:00:42 +0100 Subject: [PATCH 25/99] Update service-templates.json --- templates/service-templates.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/service-templates.json b/templates/service-templates.json index 83ce320fd..112748c1a 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -144,7 +144,7 @@ "authentik": { "documentation": "https://docs.goauthentik.io/docs/installation/docker-compose?utm_source=coolify.io", "slogan": "An open-source Identity Provider, focused on flexibility and versatility.", - "compose": "c2VydmljZXM6CiAgYXV0aGVudGlrLXNlcnZlcjoKICAgIGltYWdlOiAnZ2hjci5pby9nb2F1dGhlbnRpay9zZXJ2ZXI6JHtBVVRIRU5USUtfVEFHOi0yMDI0LjEyLjJ9JwogICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWQKICAgIGNvbW1hbmQ6IHNlcnZlcgogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROX0FVVEhFTlRJS1NFUlZFUl85MDAwCiAgICAgIC0gJ0FVVEhFTlRJS19SRURJU19fSE9TVD0ke1JFRElTX0hPU1Q6LXJlZGlzfScKICAgICAgLSAnQVVUSEVOVElLX1BPU1RHUkVTUUxfX0hPU1Q9JHtQT1NUR1JFU19IT1NUOi1wb3N0Z3Jlc3FsfScKICAgICAgLSAnQVVUSEVOVElLX1BPU1RHUkVTUUxfX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVNRTH0nCiAgICAgIC0gJ0FVVEhFTlRJS19QT1NUR1JFU1FMX19OQU1FPSR7UE9TVEdSRVNfREI6LWF1dGhlbnRpa30nCiAgICAgIC0gJ0FVVEhFTlRJS19QT1NUR1JFU1FMX19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVNRTH0nCiAgICAgIC0gJ0FVVEhFTlRJS19TRUNSRVRfS0VZPSR7U0VSVklDRV9QQVNTV09SRF82NF9BVVRIRU5USUtTRVJWRVJ9JwogICAgICAtICdBVVRIRU5USUtfRVJST1JfUkVQT1JUSU5HX19FTkFCTEVEPSR7QVVUSEVOVElLX0VSUk9SX1JFUE9SVElOR19fRU5BQkxFRDotdHJ1ZX0nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fSE9TVD0ke0FVVEhFTlRJS19FTUFJTF9fSE9TVH0nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fUE9SVD0ke0FVVEhFTlRJS19FTUFJTF9fUE9SVH0nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fVVNFUk5BTUU9JHtBVVRIRU5USUtfRU1BSUxfX1VTRVJOQU1FfScKICAgICAgLSAnQVVUSEVOVElLX0VNQUlMX19QQVNTV09SRD0ke0FVVEhFTlRJS19FTUFJTF9fUEFTU1dPUkR9JwogICAgICAtICdBVVRIRU5USUtfRU1BSUxfX1VTRV9UTFM9JHtBVVRIRU5USUtfRU1BSUxfX1VTRV9UTFN9JwogICAgICAtICdBVVRIRU5USUtfRU1BSUxfX1VTRV9TU0w9JHtBVVRIRU5USUtfRU1BSUxfX1VTRV9TU0x9JwogICAgICAtICdBVVRIRU5USUtfRU1BSUxfX1RJTUVPVVQ9JHtBVVRIRU5USUtfRU1BSUxfX1RJTUVPVVR9JwogICAgICAtICdBVVRIRU5USUtfRU1BSUxfX0ZST009JHtBVVRIRU5USUtfRU1BSUxfX0ZST019JwogICAgdm9sdW1lczoKICAgICAgLSAnLi9tZWRpYTovbWVkaWEnCiAgICAgIC0gJy4vY3VzdG9tLXRlbXBsYXRlczovdGVtcGxhdGVzJwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXNxbDoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICByZWRpczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogIGF1dGhlbnRpay13b3JrZXI6CiAgICBpbWFnZTogJ2doY3IuaW8vZ29hdXRoZW50aWsvc2VydmVyOiR7QVVUSEVOVElLX1RBRzotMjAyNC4xMi4yfScKICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkCiAgICBjb21tYW5kOiB3b3JrZXIKICAgIGVudmlyb25tZW50OgogICAgICAtICdBVVRIRU5USUtfUkVESVNfX0hPU1Q9JHtSRURJU19IT1NUOi1yZWRpc30nCiAgICAgIC0gJ0FVVEhFTlRJS19QT1NUR1JFU1FMX19IT1NUPSR7UE9TVEdSRVNfSE9TVDotcG9zdGdyZXNxbH0nCiAgICAgIC0gJ0FVVEhFTlRJS19QT1NUR1JFU1FMX19VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTUUx9JwogICAgICAtICdBVVRIRU5USUtfUE9TVEdSRVNRTF9fTkFNRT0ke1BPU1RHUkVTX0RCOi1hdXRoZW50aWt9JwogICAgICAtICdBVVRIRU5USUtfUE9TVEdSRVNRTF9fUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTUUx9JwogICAgICAtICdBVVRIRU5USUtfU0VDUkVUX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfQVVUSEVOVElLU0VSVkVSfScKICAgICAgLSAnQVVUSEVOVElLX0VSUk9SX1JFUE9SVElOR19fRU5BQkxFRD0ke0FVVEhFTlRJS19FUlJPUl9SRVBPUlRJTkdfX0VOQUJMRUR9JwogICAgICAtICdBVVRIRU5USUtfRU1BSUxfX0hPU1Q9JHtBVVRIRU5USUtfRU1BSUxfX0hPU1R9JwogICAgICAtICdBVVRIRU5USUtfRU1BSUxfX1BPUlQ9JHtBVVRIRU5USUtfRU1BSUxfX1BPUlR9JwogICAgICAtICdBVVRIRU5USUtfRU1BSUxfX1VTRVJOQU1FPSR7QVVUSEVOVElLX0VNQUlMX19VU0VSTkFNRX0nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fUEFTU1dPUkQ9JHtBVVRIRU5USUtfRU1BSUxfX1BBU1NXT1JEfScKICAgICAgLSAnQVVUSEVOVElLX0VNQUlMX19VU0VfVExTPSR7QVVUSEVOVElLX0VNQUlMX19VU0VfVExTfScKICAgICAgLSAnQVVUSEVOVElLX0VNQUlMX19VU0VfU1NMPSR7QVVUSEVOVElLX0VNQUlMX19VU0VfU1NMfScKICAgICAgLSAnQVVUSEVOVElLX0VNQUlMX19USU1FT1VUPSR7QVVUSEVOVElLX0VNQUlMX19USU1FT1VUfScKICAgICAgLSAnQVVUSEVOVElLX0VNQUlMX19GUk9NPSR7QVVUSEVOVElLX0VNQUlMX19GUk9NfScKICAgIHVzZXI6IHJvb3QKICAgIHZvbHVtZXM6CiAgICAgIC0gJy92YXIvcnVuL2RvY2tlci5zb2NrOi92YXIvcnVuL2RvY2tlci5zb2NrJwogICAgICAtICcuL21lZGlhOi9tZWRpYScKICAgICAgLSAnLi9jZXJ0czovY2VydHMnCiAgICAgIC0gJy4vY3VzdG9tLXRlbXBsYXRlczovdGVtcGxhdGVzJwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXNxbDoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICByZWRpczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogIHBvc3RncmVzcWw6CiAgICBpbWFnZTogJ3Bvc3RncmVzOjE2LWFscGluZScKICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3BnX2lzcmVhZHkgLWQgJCR7UE9TVEdSRVNfREJ9IC1VICQke1BPU1RHUkVTX1VTRVJ9JwogICAgICBpbnRlcnZhbDogMnMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDE1CiAgICB2b2x1bWVzOgogICAgICAtICdhdXRoZW50aWstZGI6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU1FMfScKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU1FMfScKICAgICAgLSBQT1NUR1JFU19EQj1hdXRoZW50aWsKICByZWRpczoKICAgIGltYWdlOiAncmVkaXM6YWxwaW5lJwogICAgY29tbWFuZDogJy0tc2F2ZSA2MCAxIC0tbG9nbGV2ZWwgd2FybmluZycKICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3JlZGlzLWNsaSBwaW5nIHwgZ3JlcCBQT05HJwogICAgICBpbnRlcnZhbDogMnMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDE1CiAgICB2b2x1bWVzOgogICAgICAtICdyZWRpczovZGF0YScK", + "compose": "c2VydmljZXM6CiAgYXV0aGVudGlrLXNlcnZlcjoKICAgIGltYWdlOiAnZ2hjci5pby9nb2F1dGhlbnRpay9zZXJ2ZXI6JHtBVVRIRU5USUtfVEFHOi0yMDI1LjIuMH0nCiAgICByZXN0YXJ0OiB1bmxlc3Mtc3RvcHBlZAogICAgY29tbWFuZDogc2VydmVyCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fQVVUSEVOVElLU0VSVkVSXzkwMDAKICAgICAgLSAnQVVUSEVOVElLX1JFRElTX19IT1NUPSR7UkVESVNfSE9TVDotcmVkaXN9JwogICAgICAtICdBVVRIRU5USUtfUE9TVEdSRVNRTF9fSE9TVD0ke1BPU1RHUkVTX0hPU1Q6LXBvc3RncmVzcWx9JwogICAgICAtICdBVVRIRU5USUtfUE9TVEdSRVNRTF9fVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU1FMfScKICAgICAgLSAnQVVUSEVOVElLX1BPU1RHUkVTUUxfX05BTUU9JHtQT1NUR1JFU19EQjotYXV0aGVudGlrfScKICAgICAgLSAnQVVUSEVOVElLX1BPU1RHUkVTUUxfX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU1FMfScKICAgICAgLSAnQVVUSEVOVElLX1NFQ1JFVF9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0FVVEhFTlRJS1NFUlZFUn0nCiAgICAgIC0gJ0FVVEhFTlRJS19FUlJPUl9SRVBPUlRJTkdfX0VOQUJMRUQ9JHtBVVRIRU5USUtfRVJST1JfUkVQT1JUSU5HX19FTkFCTEVEOi10cnVlfScKICAgICAgLSAnQVVUSEVOVElLX0VNQUlMX19IT1NUPSR7QVVUSEVOVElLX0VNQUlMX19IT1NUfScKICAgICAgLSAnQVVUSEVOVElLX0VNQUlMX19QT1JUPSR7QVVUSEVOVElLX0VNQUlMX19QT1JUfScKICAgICAgLSAnQVVUSEVOVElLX0VNQUlMX19VU0VSTkFNRT0ke0FVVEhFTlRJS19FTUFJTF9fVVNFUk5BTUV9JwogICAgICAtICdBVVRIRU5USUtfRU1BSUxfX1BBU1NXT1JEPSR7QVVUSEVOVElLX0VNQUlMX19QQVNTV09SRH0nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fVVNFX1RMUz0ke0FVVEhFTlRJS19FTUFJTF9fVVNFX1RMU30nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fVVNFX1NTTD0ke0FVVEhFTlRJS19FTUFJTF9fVVNFX1NTTH0nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fVElNRU9VVD0ke0FVVEhFTlRJS19FTUFJTF9fVElNRU9VVH0nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fRlJPTT0ke0FVVEhFTlRJS19FTUFJTF9fRlJPTX0nCiAgICB2b2x1bWVzOgogICAgICAtICcuL21lZGlhOi9tZWRpYScKICAgICAgLSAnLi9jdXN0b20tdGVtcGxhdGVzOi90ZW1wbGF0ZXMnCiAgICBkZXBlbmRzX29uOgogICAgICBwb3N0Z3Jlc3FsOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICAgIHJlZGlzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgYXV0aGVudGlrLXdvcmtlcjoKICAgIGltYWdlOiAnZ2hjci5pby9nb2F1dGhlbnRpay9zZXJ2ZXI6JHtBVVRIRU5USUtfVEFHOi0yMDI1LjIuMH0nCiAgICByZXN0YXJ0OiB1bmxlc3Mtc3RvcHBlZAogICAgY29tbWFuZDogd29ya2VyCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnQVVUSEVOVElLX1JFRElTX19IT1NUPSR7UkVESVNfSE9TVDotcmVkaXN9JwogICAgICAtICdBVVRIRU5USUtfUE9TVEdSRVNRTF9fSE9TVD0ke1BPU1RHUkVTX0hPU1Q6LXBvc3RncmVzcWx9JwogICAgICAtICdBVVRIRU5USUtfUE9TVEdSRVNRTF9fVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU1FMfScKICAgICAgLSAnQVVUSEVOVElLX1BPU1RHUkVTUUxfX05BTUU9JHtQT1NUR1JFU19EQjotYXV0aGVudGlrfScKICAgICAgLSAnQVVUSEVOVElLX1BPU1RHUkVTUUxfX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU1FMfScKICAgICAgLSAnQVVUSEVOVElLX1NFQ1JFVF9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0FVVEhFTlRJS1NFUlZFUn0nCiAgICAgIC0gJ0FVVEhFTlRJS19FUlJPUl9SRVBPUlRJTkdfX0VOQUJMRUQ9JHtBVVRIRU5USUtfRVJST1JfUkVQT1JUSU5HX19FTkFCTEVEfScKICAgICAgLSAnQVVUSEVOVElLX0VNQUlMX19IT1NUPSR7QVVUSEVOVElLX0VNQUlMX19IT1NUfScKICAgICAgLSAnQVVUSEVOVElLX0VNQUlMX19QT1JUPSR7QVVUSEVOVElLX0VNQUlMX19QT1JUfScKICAgICAgLSAnQVVUSEVOVElLX0VNQUlMX19VU0VSTkFNRT0ke0FVVEhFTlRJS19FTUFJTF9fVVNFUk5BTUV9JwogICAgICAtICdBVVRIRU5USUtfRU1BSUxfX1BBU1NXT1JEPSR7QVVUSEVOVElLX0VNQUlMX19QQVNTV09SRH0nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fVVNFX1RMUz0ke0FVVEhFTlRJS19FTUFJTF9fVVNFX1RMU30nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fVVNFX1NTTD0ke0FVVEhFTlRJS19FTUFJTF9fVVNFX1NTTH0nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fVElNRU9VVD0ke0FVVEhFTlRJS19FTUFJTF9fVElNRU9VVH0nCiAgICAgIC0gJ0FVVEhFTlRJS19FTUFJTF9fRlJPTT0ke0FVVEhFTlRJS19FTUFJTF9fRlJPTX0nCiAgICB1c2VyOiByb290CiAgICB2b2x1bWVzOgogICAgICAtICcvdmFyL3J1bi9kb2NrZXIuc29jazovdmFyL3J1bi9kb2NrZXIuc29jaycKICAgICAgLSAnLi9tZWRpYTovbWVkaWEnCiAgICAgIC0gJy4vY2VydHM6L2NlcnRzJwogICAgICAtICcuL2N1c3RvbS10ZW1wbGF0ZXM6L3RlbXBsYXRlcycKICAgIGRlcGVuZHNfb246CiAgICAgIHBvc3RncmVzcWw6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgcmVkaXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICBwb3N0Z3Jlc3FsOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNi1hbHBpbmUnCiAgICByZXN0YXJ0OiB1bmxlc3Mtc3RvcHBlZAogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1kICQke1BPU1RHUkVTX0RCfSAtVSAkJHtQT1NUR1JFU19VU0VSfScKICAgICAgaW50ZXJ2YWw6IDJzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAxNQogICAgdm9sdW1lczoKICAgICAgLSAnYXV0aGVudGlrLWRiOi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YScKICAgIGVudmlyb25tZW50OgogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVNRTH0nCiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVNRTH0nCiAgICAgIC0gUE9TVEdSRVNfREI9YXV0aGVudGlrCiAgcmVkaXM6CiAgICBpbWFnZTogJ3JlZGlzOmFscGluZScKICAgIGNvbW1hbmQ6ICctLXNhdmUgNjAgMSAtLWxvZ2xldmVsIHdhcm5pbmcnCiAgICByZXN0YXJ0OiB1bmxlc3Mtc3RvcHBlZAogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdyZWRpcy1jbGkgcGluZyB8IGdyZXAgUE9ORycKICAgICAgaW50ZXJ2YWw6IDJzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAxNQogICAgdm9sdW1lczoKICAgICAgLSAncmVkaXM6L2RhdGEnCg==", "tags": [ "identity", "login", @@ -1394,7 +1394,7 @@ "infisical": { "documentation": "https://infisical.com/docs/documentation/getting-started/introduction?utm_source=coolify.io", "slogan": "Infisical is the open source secret management platform that developers use to centralize their application configuration and secrets like API keys and database credentials.", - "compose": "c2VydmljZXM6CiAgYmFja2VuZDoKICAgIGltYWdlOiAnaW5maXNpY2FsL2luZmlzaWNhbDpsYXRlc3QtcG9zdGdyZXMnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fQkFDS0VORF84MDgwCiAgICAgIC0gJ1NJVEVfVVJMPSR7U0VSVklDRV9GUUROX0JBQ0tFTkRfODA4MH0nCiAgICAgIC0gJ05PREVfRU5WPSR7Tk9ERV9FTlY6LXByb2R1Y3Rpb259JwogICAgICAtICdFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfRU5DUllQVElPTktFWX0nCiAgICAgIC0gJ0FVVEhfU0VDUkVUPSR7U0VSVklDRV9SRUFMQkFTRTY0XzY0X0FVVEhTRUNSRVR9JwogICAgICAtICdEQl9DT05ORUNUSU9OX1VSST1wb3N0Z3JlczovLyR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfToke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9QGRiOjU0MzIvJHtQT1NUR1JFU19EQn0nCiAgICAgIC0gJ1JFRElTX1VSTD1yZWRpczovL3JlZGlzOjYzNzknCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3dnZXQgLS1uby12ZXJib3NlIC0tdHJpZXM9MSAtLXNwaWRlciBodHRwOi8vMTI3LjAuMC4xOjgwODAvYXBpL3N0YXR1cyB8fCBleGl0IDEnCiAgICBkZXBlbmRzX29uOgogICAgICByZWRpczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBkYi1taWdyYXRpb246CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2NvbXBsZXRlZF9zdWNjZXNzZnVsbHkKICByZWRpczoKICAgIGltYWdlOiAncmVkaXM6NycKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3JlZGlzLWRhdGE6L2RhdGEnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnQUxMT1dfRU1QVFlfUEFTU1dPUkQ9JHtBTExPV19FTVBUWV9QQVNTV09SRDoteWVzfScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAncmVkaXMtY2xpIC1oIGxvY2FsaG9zdCAtcCA2Mzc5IHBpbmcnCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiAzCiAgZGI6CiAgICBpbWFnZTogJ3Bvc3RncmVzOjE0LWFscGluZScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3BnX2RhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1pbmZpc2ljYWx9JwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1oIGxvY2FsaG9zdCAtVSAkJHtQT1NUR1JFU19VU0VSfSAtZCAkJHtQT1NUR1JFU19EQn0nCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMTAKICBkYi1taWdyYXRpb246CiAgICBleGNsdWRlX2Zyb21faGM6IHRydWUKICAgIGltYWdlOiAnaW5maXNpY2FsL2luZmlzaWNhbDpsYXRlc3QtcG9zdGdyZXMnCiAgICBkZXBlbmRzX29uOgogICAgICBkYjoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgY29tbWFuZDogJ25wbSBydW4gbWlncmF0aW9uOmxhdGVzdCcKICAgIHJlc3RhcnQ6IG9uLWZhaWx1cmUKICAgIGVudmlyb25tZW50OgogICAgICAtICdQT1NUR1JFU19VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfScKICAgICAgLSAnUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotaW5maXNpY2FsfScKICAgICAgLSAnREJfQ09OTkVDVElPTl9VUkk9cG9zdGdyZXM6Ly8ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU306JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfUBkYjo1NDMyLyR7UE9TVEdSRVNfREI6LWluZmlzaWNhbH0nCiAgICAgIC0gJ1JFRElTX1VSTD1yZWRpczovL3JlZGlzOjYzNzknCg==", + "compose": "c2VydmljZXM6CiAgYmFja2VuZDoKICAgIGltYWdlOiAnaW5maXNpY2FsL2luZmlzaWNhbDpsYXRlc3QtcG9zdGdyZXMnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fQkFDS0VORF84MDgwCiAgICAgIC0gJ1NJVEVfVVJMPSR7U0VSVklDRV9GUUROX0JBQ0tFTkRfODA4MH0nCiAgICAgIC0gJ05PREVfRU5WPSR7Tk9ERV9FTlY6LXByb2R1Y3Rpb259JwogICAgICAtICdFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfRU5DUllQVElPTktFWX0nCiAgICAgIC0gJ0FVVEhfU0VDUkVUPSR7U0VSVklDRV9SRUFMQkFTRTY0XzY0X0FVVEhTRUNSRVR9JwogICAgICAtICdTTVRQX0hPU1Q9JHtTTVRQX0hPU1R9JwogICAgICAtICdTTVRQX1VTRVJOQU1FPSR7U01UUF9VU0VSTkFNRX0nCiAgICAgIC0gJ1NNVFBfUEFTU1dPUkQ9JHtTTVRQX1BBU1NXT1JEfScKICAgICAgLSAnU01UUF9QT1JUPSR7U01UUF9QT1JUfScKICAgICAgLSAnU01UUF9GUk9NX0FERFJFU1M9JHtTTVRQX0ZST01fQUREUkVTU30nCiAgICAgIC0gJ1NNVFBfRlJPTV9OQU1FPSR7U01UUF9GUk9NX05BTUV9JwogICAgICAtICdEQl9DT05ORUNUSU9OX1VSST1wb3N0Z3JlczovLyR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfToke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9QGRiOjU0MzIvJHtQT1NUR1JFU19EQn0nCiAgICAgIC0gJ1JFRElTX1VSTD1yZWRpczovL3JlZGlzOjYzNzknCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3dnZXQgLS1uby12ZXJib3NlIC0tdHJpZXM9MSAtLXNwaWRlciBodHRwOi8vMTI3LjAuMC4xOjgwODAvYXBpL3N0YXR1cyB8fCBleGl0IDEnCiAgICBkZXBlbmRzX29uOgogICAgICByZWRpczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBkYjoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogIHJlZGlzOgogICAgaW1hZ2U6ICdyZWRpczo3JwogICAgdm9sdW1lczoKICAgICAgLSAncmVkaXMtZGF0YTovZGF0YScKICAgIGVudmlyb25tZW50OgogICAgICAtICdBTExPV19FTVBUWV9QQVNTV09SRD0ke0FMTE9XX0VNUFRZX1BBU1NXT1JEOi15ZXN9JwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdyZWRpcy1jbGkgLWggbG9jYWxob3N0IC1wIDYzNzkgcGluZycKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDMKICBkYjoKICAgIGltYWdlOiAncG9zdGdyZXM6MTQtYWxwaW5lJwogICAgdm9sdW1lczoKICAgICAgLSAncGdfZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWluZmlzaWNhbH0nCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3BnX2lzcmVhZHkgLWggbG9jYWxob3N0IC1VICQke1BPU1RHUkVTX1VTRVJ9IC1kICQke1BPU1RHUkVTX0RCfScKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAxMAo=", "tags": [ "security", "environment", @@ -2364,7 +2364,7 @@ "penpot": { "documentation": "https://help.penpot.app/technical-guide/getting-started/#install-with-docker?utm_source=coolify.io", "slogan": "Penpot is the first Open Source design and prototyping platform for product teams.", - "compose": "c2VydmljZXM6CiAgZnJvbnRlbmQ6CiAgICBpbWFnZTogJ3BlbnBvdGFwcC9mcm9udGVuZDpsYXRlc3QnCiAgICB2b2x1bWVzOgogICAgICAtICdwZW5wb3QtYXNzZXRzOi9vcHQvZGF0YS9hc3NldHMnCiAgICBkZXBlbmRzX29uOgogICAgICBwZW5wb3QtYmFja2VuZDoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBwZW5wb3QtZXhwb3J0ZXI6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9GUk9OVEVORAogICAgICAtICdQRU5QT1RfRkxBR1M9JHtQRU5QT1RfRlJPTlRFTkRfRkxBR1M6LWVuYWJsZS1sb2dpbi13aXRoLXBhc3N3b3JkfScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLWYnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTo4MCcKICAgICAgaW50ZXJ2YWw6IDJzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAxNQogIHBlbnBvdC1iYWNrZW5kOgogICAgaW1hZ2U6ICdwZW5wb3RhcHAvYmFja2VuZDpsYXRlc3QnCiAgICB2b2x1bWVzOgogICAgICAtICdwZW5wb3QtYXNzZXRzOi9vcHQvZGF0YS9hc3NldHMnCiAgICBkZXBlbmRzX29uOgogICAgICBwb3N0Z3JlczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICByZWRpczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BFTlBPVF9GTEFHUz0ke1BFTlBPVF9CQUNLRU5EX0ZMQUdTOi1lbmFibGUtbG9naW4td2l0aC1wYXNzd29yZCBlbmFibGUtc210cCBlbmFibGUtcHJlcGwtc2VydmVyfScKICAgICAgLSBQRU5QT1RfSFRUUF9TRVJWRVJfUE9SVD02MDYwCiAgICAgIC0gUEVOUE9UX1NFQ1JFVF9LRVk9JFNFUlZJQ0VfUkVBTEJBU0U2NF82NF9QRU5QT1QKICAgICAgLSBQRU5QT1RfUFVCTElDX1VSST0kU0VSVklDRV9GUUROX0ZST05URU5ECiAgICAgIC0gJ1BFTlBPVF9CQUNLRU5EX1VSST1odHRwOi8vcGVucG90LWJhY2tlbmQnCiAgICAgIC0gJ1BFTlBPVF9FWFBPUlRFUl9VUkk9aHR0cDovL3BlbnBvdC1leHBvcnRlcicKICAgICAgLSAnUEVOUE9UX0RBVEFCQVNFX1VSST1wb3N0Z3Jlc3FsOi8vcG9zdGdyZXMvJHtQT1NUR1JFU19EQjotcGVucG90fScKICAgICAgLSAnUEVOUE9UX0RBVEFCQVNFX1VTRVJOQU1FPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfScKICAgICAgLSAnUEVOUE9UX0RBVEFCQVNFX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BFTlBPVF9SRURJU19VUkk9cmVkaXM6Ly9yZWRpcy8wJwogICAgICAtIFBFTlBPVF9BU1NFVFNfU1RPUkFHRV9CQUNLRU5EPWFzc2V0cy1mcwogICAgICAtIFBFTlBPVF9TVE9SQUdFX0FTU0VUU19GU19ESVJFQ1RPUlk9L29wdC9kYXRhL2Fzc2V0cwogICAgICAtICdQRU5QT1RfVEVMRU1FVFJZX0VOQUJMRUQ9JHtQRU5QT1RfVEVMRU1FVFJZX0VOQUJMRUQ6LWZhbHNlfScKICAgICAgLSAnUEVOUE9UX1NNVFBfREVGQVVMVF9GUk9NPSR7UEVOUE9UX1NNVFBfREVGQVVMVF9GUk9NOi1uby1yZXBseUBleGFtcGxlLmNvbX0nCiAgICAgIC0gJ1BFTlBPVF9TTVRQX0RFRkFVTFRfUkVQTFlfVE89JHtQRU5QT1RfU01UUF9ERUZBVUxUX1JFUExZX1RPOi1uby1yZXBseUBleGFtcGxlLmNvbX0nCiAgICAgIC0gJ1BFTlBPVF9TTVRQX0hPU1Q9JHtQRU5QT1RfU01UUF9IT1NUOi1tYWlscGl0fScKICAgICAgLSAnUEVOUE9UX1NNVFBfUE9SVD0ke1BFTlBPVF9TTVRQX1BPUlQ6LTEwMjV9JwogICAgICAtICdQRU5QT1RfU01UUF9VU0VSTkFNRT0ke1BFTlBPVF9TTVRQX1VTRVJOQU1FOi1wZW5wb3R9JwogICAgICAtICdQRU5QT1RfU01UUF9QQVNTV09SRD0ke1BFTlBPVF9TTVRQX1BBU1NXT1JEOi1wZW5wb3R9JwogICAgICAtICdQRU5QT1RfU01UUF9UTFM9JHtQRU5QT1RfU01UUF9UTFM6LWZhbHNlfScKICAgICAgLSAnUEVOUE9UX1NNVFBfU1NMPSR7UEVOUE9UX1NNVFBfU1NMOi1mYWxzZX0nCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gY3VybAogICAgICAgIC0gJy1mJwogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6NjA2MC9yZWFkeXonCiAgICAgIGludGVydmFsOiAycwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMTUKICBwZW5wb3QtZXhwb3J0ZXI6CiAgICBpbWFnZTogJ3BlbnBvdGFwcC9leHBvcnRlcjpsYXRlc3QnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBQRU5QT1RfUFVCTElDX1VSST0kU0VSVklDRV9GUUROX0ZST05URU5ECiAgICAgIC0gJ1BFTlBPVF9SRURJU19VUkk9cmVkaXM6Ly9yZWRpcy8wJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjYwNjEvcmVhZHl6JwogICAgICBpbnRlcnZhbDogMnMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDE1CiAgbWFpbHBpdDoKICAgIGltYWdlOiAnYXhsbGVudC9tYWlscGl0OmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9NQUlMUElUXzgwMjUKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSAvbWFpbHBpdAogICAgICAgIC0gcmVhZHl6CiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiAyMHMKICAgICAgcmV0cmllczogMTAKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUnCiAgICB2b2x1bWVzOgogICAgICAtICdwZW5wb3QtcG9zdGdyZXNxbC1kYXRhOi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YScKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX0lOSVREQl9BUkdTPS0tZGF0YS1jaGVja3N1bXMKICAgICAgLSBQT1NUR1JFU19VU0VSPSRTRVJWSUNFX1VTRVJfUE9TVEdSRVMKICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0kU0VSVklDRV9QQVNTV09SRF9QT1NUR1JFUwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1wZW5wb3R9JwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICQke1BPU1RHUkVTX1VTRVJ9IC1kICQke1BPU1RHUkVTX0RCfScKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAogIHJlZGlzOgogICAgaW1hZ2U6ICdyZWRpczo3LWFscGluZScKICAgIGNvbW1hbmQ6ICdyZWRpcy1zZXJ2ZXIgLS1hcHBlbmRvbmx5IHllcycKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3BlbnBvdC1yZWRpcy1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIHJlZGlzLWNsaQogICAgICAgIC0gcGluZwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCg==", + "compose": "c2VydmljZXM6CiAgZnJvbnRlbmQ6CiAgICBpbWFnZTogJ3BlbnBvdGFwcC9mcm9udGVuZDpsYXRlc3QnCiAgICB2b2x1bWVzOgogICAgICAtICdwZW5wb3QtYXNzZXRzOi9vcHQvZGF0YS9hc3NldHMnCiAgICBkZXBlbmRzX29uOgogICAgICBwZW5wb3QtYmFja2VuZDoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBwZW5wb3QtZXhwb3J0ZXI6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9GUk9OVEVORF84MDgwCiAgICAgIC0gJ1BFTlBPVF9GTEFHUz0ke1BFTlBPVF9GUk9OVEVORF9GTEFHUzotZW5hYmxlLWxvZ2luLXdpdGgtcGFzc3dvcmR9JwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjgwODAnCiAgICAgIGludGVydmFsOiAycwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMTUKICBwZW5wb3QtYmFja2VuZDoKICAgIGltYWdlOiAncGVucG90YXBwL2JhY2tlbmQ6bGF0ZXN0JwogICAgdm9sdW1lczoKICAgICAgLSAncGVucG90LWFzc2V0czovb3B0L2RhdGEvYXNzZXRzJwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgcmVkaXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtICdQRU5QT1RfRkxBR1M9JHtQRU5QT1RfQkFDS0VORF9GTEFHUzotZW5hYmxlLWxvZ2luLXdpdGgtcGFzc3dvcmQgZW5hYmxlLXNtdHAgZW5hYmxlLXByZXBsLXNlcnZlcn0nCiAgICAgIC0gUEVOUE9UX0hUVFBfU0VSVkVSX1BPUlQ9NjA2MAogICAgICAtIFBFTlBPVF9TRUNSRVRfS0VZPSRTRVJWSUNFX1JFQUxCQVNFNjRfNjRfUEVOUE9UCiAgICAgIC0gUEVOUE9UX1BVQkxJQ19VUkk9JFNFUlZJQ0VfRlFETl9GUk9OVEVORF84MDgwCiAgICAgIC0gJ1BFTlBPVF9CQUNLRU5EX1VSST1odHRwOi8vcGVucG90LWJhY2tlbmQnCiAgICAgIC0gJ1BFTlBPVF9FWFBPUlRFUl9VUkk9aHR0cDovL3BlbnBvdC1leHBvcnRlcicKICAgICAgLSAnUEVOUE9UX0RBVEFCQVNFX1VSST1wb3N0Z3Jlc3FsOi8vcG9zdGdyZXMvJHtQT1NUR1JFU19EQjotcGVucG90fScKICAgICAgLSAnUEVOUE9UX0RBVEFCQVNFX1VTRVJOQU1FPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfScKICAgICAgLSAnUEVOUE9UX0RBVEFCQVNFX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BFTlBPVF9SRURJU19VUkk9cmVkaXM6Ly9yZWRpcy8wJwogICAgICAtIFBFTlBPVF9BU1NFVFNfU1RPUkFHRV9CQUNLRU5EPWFzc2V0cy1mcwogICAgICAtIFBFTlBPVF9TVE9SQUdFX0FTU0VUU19GU19ESVJFQ1RPUlk9L29wdC9kYXRhL2Fzc2V0cwogICAgICAtICdQRU5QT1RfVEVMRU1FVFJZX0VOQUJMRUQ9JHtQRU5QT1RfVEVMRU1FVFJZX0VOQUJMRUQ6LWZhbHNlfScKICAgICAgLSAnUEVOUE9UX1NNVFBfREVGQVVMVF9GUk9NPSR7UEVOUE9UX1NNVFBfREVGQVVMVF9GUk9NOi1uby1yZXBseUBleGFtcGxlLmNvbX0nCiAgICAgIC0gJ1BFTlBPVF9TTVRQX0RFRkFVTFRfUkVQTFlfVE89JHtQRU5QT1RfU01UUF9ERUZBVUxUX1JFUExZX1RPOi1uby1yZXBseUBleGFtcGxlLmNvbX0nCiAgICAgIC0gJ1BFTlBPVF9TTVRQX0hPU1Q9JHtQRU5QT1RfU01UUF9IT1NUOi1tYWlscGl0fScKICAgICAgLSAnUEVOUE9UX1NNVFBfUE9SVD0ke1BFTlBPVF9TTVRQX1BPUlQ6LTEwMjV9JwogICAgICAtICdQRU5QT1RfU01UUF9VU0VSTkFNRT0ke1BFTlBPVF9TTVRQX1VTRVJOQU1FOi1wZW5wb3R9JwogICAgICAtICdQRU5QT1RfU01UUF9QQVNTV09SRD0ke1BFTlBPVF9TTVRQX1BBU1NXT1JEOi1wZW5wb3R9JwogICAgICAtICdQRU5QT1RfU01UUF9UTFM9JHtQRU5QT1RfU01UUF9UTFM6LWZhbHNlfScKICAgICAgLSAnUEVOUE9UX1NNVFBfU1NMPSR7UEVOUE9UX1NNVFBfU1NMOi1mYWxzZX0nCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gY3VybAogICAgICAgIC0gJy1mJwogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6NjA2MC9yZWFkeXonCiAgICAgIGludGVydmFsOiAxMHMKICAgICAgdGltZW91dDogMzBzCiAgICAgIHJldHJpZXM6IDE1CiAgcGVucG90LWV4cG9ydGVyOgogICAgaW1hZ2U6ICdwZW5wb3RhcHAvZXhwb3J0ZXI6bGF0ZXN0JwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gUEVOUE9UX1BVQkxJQ19VUkk9JFNFUlZJQ0VfRlFETl9GUk9OVEVORF84MDgwCiAgICAgIC0gJ1BFTlBPVF9SRURJU19VUkk9cmVkaXM6Ly9yZWRpcy8wJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjYwNjEvcmVhZHl6JwogICAgICBpbnRlcnZhbDogMnMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDE1CiAgbWFpbHBpdDoKICAgIGltYWdlOiAnYXhsbGVudC9tYWlscGl0OmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9NQUlMUElUXzgwMjUKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSAvbWFpbHBpdAogICAgICAgIC0gcmVhZHl6CiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiAyMHMKICAgICAgcmV0cmllczogMTAKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUnCiAgICB2b2x1bWVzOgogICAgICAtICdwZW5wb3QtcG9zdGdyZXNxbC1kYXRhOi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YScKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX0lOSVREQl9BUkdTPS0tZGF0YS1jaGVja3N1bXMKICAgICAgLSBQT1NUR1JFU19VU0VSPSRTRVJWSUNFX1VTRVJfUE9TVEdSRVMKICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0kU0VSVklDRV9QQVNTV09SRF9QT1NUR1JFUwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1wZW5wb3R9JwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICQke1BPU1RHUkVTX1VTRVJ9IC1kICQke1BPU1RHUkVTX0RCfScKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAogIHJlZGlzOgogICAgaW1hZ2U6ICdyZWRpczo3LWFscGluZScKICAgIGNvbW1hbmQ6ICdyZWRpcy1zZXJ2ZXIgLS1hcHBlbmRvbmx5IHllcycKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3BlbnBvdC1yZWRpcy1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIHJlZGlzLWNsaQogICAgICAgIC0gcGluZwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCg==", "tags": [ "penpot", "design", @@ -2375,7 +2375,7 @@ ], "logo": "svgs/penpot.svg", "minversion": "0.0.0", - "port": "80" + "port": "8080" }, "phpmyadmin": { "documentation": "https://phpmyadmin.net?utm_source=coolify.io", @@ -3317,7 +3317,7 @@ "zipline": { "documentation": "https://github.com/diced/zipline?utm_source=coolify.io", "slogan": "A ShareX/file upload server that is easy to use, packed with features, and with an easy setup!", - "compose": "c2VydmljZXM6CiAgemlwbGluZToKICAgIGltYWdlOiAnZ2hjci5pby9kaWNlZC96aXBsaW5lOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9aSVBMSU5FXzMwMDAKICAgICAgLSAnQ09SRV9SRVRVUk5fSFRUUFM9JHtDT1JFX1JFVFVSTl9IVFRQUzotZmFsc2V9JwogICAgICAtICdDT1JFX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfWklQTElORX0nCiAgICAgIC0gJ0NPUkVfREFUQUJBU0VfVVJMPXBvc3RncmVzOi8vJHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9OiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU31AcG9zdGdyZXMvJHtQT1NUR1JFU19EQjotemlwbGluZS1kYn0nCiAgICAgIC0gJ0NPUkVfTE9HR0VSPSR7Q09SRV9MT0dHRVI6LXRydWV9JwogICAgdm9sdW1lczoKICAgICAgLSAnemlwbGluZS11cGxvYWRzOi96aXBsaW5lL3VwbG9hZHMnCiAgICAgIC0gJ3ppcGxpbmUtcHVibGljOi96aXBsaW5lL3B1YmxpYycKICAgIGRlcGVuZHNfb246CiAgICAgIHBvc3RncmVzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gd2dldAogICAgICAgIC0gJy1xJwogICAgICAgIC0gJy0tc3BpZGVyJwogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6MzAwMC9hdXRoL2xvZ2luJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCiAgcG9zdGdyZXM6CiAgICBpbWFnZTogJ3Bvc3RncmVzOjE2LWFscGluZScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3ppcGxpbmUtcG9zdGdyZXMtZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LXppcGxpbmUtZGJ9JwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICQke1BPU1RHUkVTX1VTRVJ9IC1kICQke1BPU1RHUkVTX0RCfScKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAo=", + "compose": "c2VydmljZXM6CiAgemlwbGluZToKICAgIGltYWdlOiAnZ2hjci5pby9kaWNlZC96aXBsaW5lOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9aSVBMSU5FXzMwMDAKICAgICAgLSAnQ09SRV9SRVRVUk5fSFRUUFM9JHtDT1JFX1JFVFVSTl9IVFRQUzotZmFsc2V9JwogICAgICAtICdDT1JFX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfWklQTElORX0nCiAgICAgIC0gJ0RBVEFCQVNFX1VSTD1wb3N0Z3JlczovLyR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfToke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9QHBvc3RncmVzLyR7UE9TVEdSRVNfREI6LXppcGxpbmUtZGJ9JwogICAgICAtICdDT1JFX0xPR0dFUj0ke0NPUkVfTE9HR0VSOi10cnVlfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3ppcGxpbmUtdXBsb2FkczovemlwbGluZS91cGxvYWRzJwogICAgICAtICd6aXBsaW5lLXB1YmxpYzovemlwbGluZS9wdWJsaWMnCiAgICBkZXBlbmRzX29uOgogICAgICBwb3N0Z3JlczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIHdnZXQKICAgICAgICAtICctcScKICAgICAgICAtICctLXNwaWRlcicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjMwMDAvYXV0aC9sb2dpbicKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAogIHBvc3RncmVzOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNi1hbHBpbmUnCiAgICB2b2x1bWVzOgogICAgICAtICd6aXBsaW5lLXBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi16aXBsaW5lLWRifScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAncGdfaXNyZWFkeSAtVSAkJHtQT1NUR1JFU19VU0VSfSAtZCAkJHtQT1NUR1JFU19EQn0nCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiAyMHMKICAgICAgcmV0cmllczogMTAK", "tags": [ "zipline", "file-sharing", From a46caf209f196c321d78d675505c8372dc735ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=8F=94=EF=B8=8F=20Peak?= <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:08:54 +0100 Subject: [PATCH 26/99] Chore: Bump all dependencies (#5216) * chore: bump all docker dependecies * chore: update composer and npm dep --- composer.lock | 1418 +++++++++++---------- docker-compose.prod.yml | 2 +- docker-compose.windows.yml | 2 +- docker/coolify-helper/Dockerfile | 14 +- docker/coolify-realtime/Dockerfile | 2 +- docker/coolify-realtime/package-lock.json | 199 ++- docker/coolify-realtime/package.json | 2 +- docker/development/Dockerfile | 4 +- docker/production/Dockerfile | 4 +- docker/testing-host/Dockerfile | 6 +- other/nightly/versions.json | 4 +- package-lock.json | 369 +++--- package.json | 12 +- versions.json | 4 +- 14 files changed, 1160 insertions(+), 882 deletions(-) diff --git a/composer.lock b/composer.lock index 97b40f7c7..65271cb1a 100644 --- a/composer.lock +++ b/composer.lock @@ -66,16 +66,16 @@ }, { "name": "amphp/amp", - "version": "v3.0.2", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/amphp/amp.git", - "reference": "138801fb68cfc9c329da8a7b39d01ce7291ee4b0" + "reference": "7cf7fef3d667bfe4b2560bc87e67d5387a7bcde9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/138801fb68cfc9c329da8a7b39d01ce7291ee4b0", - "reference": "138801fb68cfc9c329da8a7b39d01ce7291ee4b0", + "url": "https://api.github.com/repos/amphp/amp/zipball/7cf7fef3d667bfe4b2560bc87e67d5387a7bcde9", + "reference": "7cf7fef3d667bfe4b2560bc87e67d5387a7bcde9", "shasum": "" }, "require": { @@ -135,7 +135,7 @@ ], "support": { "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v3.0.2" + "source": "https://github.com/amphp/amp/tree/v3.1.0" }, "funding": [ { @@ -143,7 +143,7 @@ "type": "github" } ], - "time": "2024-05-10T21:37:46+00:00" + "time": "2025-01-26T16:07:39+00:00" }, { "name": "amphp/byte-stream", @@ -287,16 +287,16 @@ }, { "name": "amphp/dns", - "version": "v2.3.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/amphp/dns.git", - "reference": "166c43737cef1b77782c648a9d9ed11ee0c9859f" + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/dns/zipball/166c43737cef1b77782c648a9d9ed11ee0c9859f", - "reference": "166c43737cef1b77782c648a9d9ed11ee0c9859f", + "url": "https://api.github.com/repos/amphp/dns/zipball/78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", "shasum": "" }, "require": { @@ -364,7 +364,7 @@ ], "support": { "issues": "https://github.com/amphp/dns/issues", - "source": "https://github.com/amphp/dns/tree/v2.3.0" + "source": "https://github.com/amphp/dns/tree/v2.4.0" }, "funding": [ { @@ -372,7 +372,7 @@ "type": "github" } ], - "time": "2024-12-21T01:15:34+00:00" + "time": "2025-01-19T15:43:40+00:00" }, { "name": "amphp/parallel", @@ -522,16 +522,16 @@ }, { "name": "amphp/pipeline", - "version": "v1.2.1", + "version": "v1.2.2", "source": { "type": "git", "url": "https://github.com/amphp/pipeline.git", - "reference": "66c095673aa5b6e689e63b52d19e577459129ab3" + "reference": "97cbf289f4d8877acfe58dd90ed5a4370a43caa4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/pipeline/zipball/66c095673aa5b6e689e63b52d19e577459129ab3", - "reference": "66c095673aa5b6e689e63b52d19e577459129ab3", + "url": "https://api.github.com/repos/amphp/pipeline/zipball/97cbf289f4d8877acfe58dd90ed5a4370a43caa4", + "reference": "97cbf289f4d8877acfe58dd90ed5a4370a43caa4", "shasum": "" }, "require": { @@ -577,7 +577,7 @@ ], "support": { "issues": "https://github.com/amphp/pipeline/issues", - "source": "https://github.com/amphp/pipeline/tree/v1.2.1" + "source": "https://github.com/amphp/pipeline/tree/v1.2.2" }, "funding": [ { @@ -585,7 +585,7 @@ "type": "github" } ], - "time": "2024-07-04T00:56:47+00:00" + "time": "2025-01-19T15:42:46+00:00" }, { "name": "amphp/process", @@ -928,16 +928,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.337.1", + "version": "3.339.19", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "fa70febad922e9868c83bfe03c6d078fc2633e17" + "reference": "18f05efe983860ad899082e04c13f06ec9fd6e41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/fa70febad922e9868c83bfe03c6d078fc2633e17", - "reference": "fa70febad922e9868c83bfe03c6d078fc2633e17", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/18f05efe983860ad899082e04c13f06ec9fd6e41", + "reference": "18f05efe983860ad899082e04c13f06ec9fd6e41", "shasum": "" }, "require": { @@ -945,31 +945,30 @@ "ext-json": "*", "ext-pcre": "*", "ext-simplexml": "*", - "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", - "guzzlehttp/promises": "^1.4.0 || ^2.0", - "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", - "mtdowling/jmespath.php": "^2.6", - "php": ">=7.2.5", - "psr/http-message": "^1.0 || ^2.0" + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/promises": "^2.0", + "guzzlehttp/psr7": "^2.4.5", + "mtdowling/jmespath.php": "^2.8.0", + "php": ">=8.1", + "psr/http-message": "^2.0" }, "require-dev": { "andrewsville/php-token-reflection": "^1.4", "aws/aws-php-sns-message-validator": "~1.0", "behat/behat": "~3.0", - "composer/composer": "^1.10.22", + "composer/composer": "^2.7.8", "dms/phpunit-arraysubset-asserts": "^0.4.0", "doctrine/cache": "~1.4", "ext-dom": "*", "ext-openssl": "*", "ext-pcntl": "*", "ext-sockets": "*", - "nette/neon": "^2.3", - "paragonie/random_compat": ">= 2", "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", - "psr/cache": "^1.0 || ^2.0 || ^3.0", - "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", - "sebastian/comparator": "^1.2.3 || ^4.0", - "yoast/phpunit-polyfills": "^1.0" + "psr/cache": "^2.0 || ^3.0", + "psr/simple-cache": "^2.0 || ^3.0", + "sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0", + "symfony/filesystem": "^v6.4.0 || ^v7.1.0", + "yoast/phpunit-polyfills": "^2.0" }, "suggest": { "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", @@ -1018,11 +1017,11 @@ "sdk" ], "support": { - "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", + "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.337.1" + "source": "https://github.com/aws/aws-sdk-php/tree/3.339.19" }, - "time": "2025-01-16T19:12:46+00:00" + "time": "2025-02-21T19:13:15+00:00" }, { "name": "bacon/bacon-qr-code", @@ -1944,16 +1943,16 @@ }, { "name": "firebase/php-jwt", - "version": "v6.10.2", + "version": "v6.11.0", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "30c19ed0f3264cb660ea496895cfb6ef7ee3653b" + "reference": "8f718f4dfc9c5d5f0c994cdfd103921b43592712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/30c19ed0f3264cb660ea496895cfb6ef7ee3653b", - "reference": "30c19ed0f3264cb660ea496895cfb6ef7ee3653b", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/8f718f4dfc9c5d5f0c994cdfd103921b43592712", + "reference": "8f718f4dfc9c5d5f0c994cdfd103921b43592712", "shasum": "" }, "require": { @@ -2001,9 +2000,9 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.10.2" + "source": "https://github.com/firebase/php-jwt/tree/v6.11.0" }, - "time": "2024-11-24T11:22:49+00:00" + "time": "2025-01-23T05:11:06+00:00" }, { "name": "fruitcake/php-cors", @@ -2465,16 +2464,16 @@ }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.3", + "version": "v1.0.4", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c" + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/ecea8feef63bd4fef1f037ecb288386999ecc11c", - "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/30e286560c137526eccd4ce21b2de477ab0676d2", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2", "shasum": "" }, "require": { @@ -2531,7 +2530,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.3" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.4" }, "funding": [ { @@ -2547,7 +2546,7 @@ "type": "tidelift" } ], - "time": "2023-12-03T19:50:20+00:00" + "time": "2025-02-03T10:55:03+00:00" }, { "name": "jean85/pretty-package-versions", @@ -2668,31 +2667,31 @@ }, { "name": "laravel/fortify", - "version": "v1.25.2", + "version": "v1.25.4", "source": { "type": "git", "url": "https://github.com/laravel/fortify.git", - "reference": "a20e8033e7329b05820007c398f06065a38ae188" + "reference": "f185600e2d3a861834ad00ee3b7863f26ac25d3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/fortify/zipball/a20e8033e7329b05820007c398f06065a38ae188", - "reference": "a20e8033e7329b05820007c398f06065a38ae188", + "url": "https://api.github.com/repos/laravel/fortify/zipball/f185600e2d3a861834ad00ee3b7863f26ac25d3f", + "reference": "f185600e2d3a861834ad00ee3b7863f26ac25d3f", "shasum": "" }, "require": { "bacon/bacon-qr-code": "^3.0", "ext-json": "*", - "illuminate/support": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0|^12.0", "php": "^8.1", "pragmarx/google2fa": "^8.0", "symfony/console": "^6.0|^7.0" }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^8.16|^9.0", + "orchestra/testbench": "^8.16|^9.0|^10.0", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.4" + "phpunit/phpunit": "^10.4|^11.3" }, "type": "library", "extra": { @@ -2729,20 +2728,20 @@ "issues": "https://github.com/laravel/fortify/issues", "source": "https://github.com/laravel/fortify" }, - "time": "2025-01-10T20:33:47+00:00" + "time": "2025-01-26T19:34:46+00:00" }, { "name": "laravel/framework", - "version": "v11.38.2", + "version": "v11.44.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "9d290aa90fcad44048bedca5219d2b872e98772a" + "reference": "e9a33da34815ac1ed46c7e4c477a775f4592f0a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/9d290aa90fcad44048bedca5219d2b872e98772a", - "reference": "9d290aa90fcad44048bedca5219d2b872e98772a", + "url": "https://api.github.com/repos/laravel/framework/zipball/e9a33da34815ac1ed46c7e4c477a775f4592f0a7", + "reference": "e9a33da34815ac1ed46c7e4c477a775f4592f0a7", "shasum": "" }, "require": { @@ -2768,7 +2767,7 @@ "league/flysystem-local": "^3.25.1", "league/uri": "^7.5.1", "monolog/monolog": "^3.0", - "nesbot/carbon": "^2.72.2|^3.4", + "nesbot/carbon": "^2.72.6|^3.8.4", "nunomaduro/termwind": "^2.0", "php": "^8.2", "psr/container": "^1.1.1|^2.0.1", @@ -2843,17 +2842,18 @@ "fakerphp/faker": "^1.24", "guzzlehttp/promises": "^2.0.3", "guzzlehttp/psr7": "^2.4", + "laravel/pint": "^1.18", "league/flysystem-aws-s3-v3": "^3.25.1", "league/flysystem-ftp": "^3.25.1", "league/flysystem-path-prefixing": "^3.25.1", "league/flysystem-read-only": "^3.25.1", "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", - "orchestra/testbench-core": "^9.6", + "orchestra/testbench-core": "^9.9.4", "pda/pheanstalk": "^5.0.6", "php-http/discovery": "^1.15", - "phpstan/phpstan": "^1.11.5", - "phpunit/phpunit": "^10.5.35|^11.3.6", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.5.35|^11.3.6|^12.0.1", "predis/predis": "^2.3", "resend/resend-php": "^0.10.0", "symfony/cache": "^7.0.3", @@ -2885,7 +2885,7 @@ "mockery/mockery": "Required to use mocking (^1.6).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", - "phpunit/phpunit": "Required to use assertions and run tests (^10.5|^11.0).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.3.6|^12.0.1).", "predis/predis": "Required to use the predis connector (^2.3).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", @@ -2943,29 +2943,29 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-01-15T00:06:46+00:00" + "time": "2025-02-24T13:08:54+00:00" }, { "name": "laravel/horizon", - "version": "v5.30.2", + "version": "v5.30.3", "source": { "type": "git", "url": "https://github.com/laravel/horizon.git", - "reference": "baef526f036717b0090754cbd9c9b67f879739fd" + "reference": "7b9ee870bf0e425b956fd0433f616f98fe951f72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/horizon/zipball/baef526f036717b0090754cbd9c9b67f879739fd", - "reference": "baef526f036717b0090754cbd9c9b67f879739fd", + "url": "https://api.github.com/repos/laravel/horizon/zipball/7b9ee870bf0e425b956fd0433f616f98fe951f72", + "reference": "7b9ee870bf0e425b956fd0433f616f98fe951f72", "shasum": "" }, "require": { "ext-json": "*", "ext-pcntl": "*", "ext-posix": "*", - "illuminate/contracts": "^9.21|^10.0|^11.0", - "illuminate/queue": "^9.21|^10.0|^11.0", - "illuminate/support": "^9.21|^10.0|^11.0", + "illuminate/contracts": "^9.21|^10.0|^11.0|^12.0", + "illuminate/queue": "^9.21|^10.0|^11.0|^12.0", + "illuminate/support": "^9.21|^10.0|^11.0|^12.0", "nesbot/carbon": "^2.17|^3.0", "php": "^8.0", "ramsey/uuid": "^4.0", @@ -2976,9 +2976,9 @@ }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^7.0|^8.0|^9.0", + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.0|^10.4", + "phpunit/phpunit": "^9.0|^10.4|^11.5", "predis/predis": "^1.1|^2.0" }, "suggest": { @@ -3021,41 +3021,41 @@ ], "support": { "issues": "https://github.com/laravel/horizon/issues", - "source": "https://github.com/laravel/horizon/tree/v5.30.2" + "source": "https://github.com/laravel/horizon/tree/v5.30.3" }, - "time": "2025-01-13T16:51:22+00:00" + "time": "2025-02-11T13:52:50+00:00" }, { "name": "laravel/pail", - "version": "v1.2.1", + "version": "v1.2.2", "source": { "type": "git", "url": "https://github.com/laravel/pail.git", - "reference": "353ac12134b98e2e7c3333d916bd3e523931e583" + "reference": "f31f4980f52be17c4667f3eafe034e6826787db2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pail/zipball/353ac12134b98e2e7c3333d916bd3e523931e583", - "reference": "353ac12134b98e2e7c3333d916bd3e523931e583", + "url": "https://api.github.com/repos/laravel/pail/zipball/f31f4980f52be17c4667f3eafe034e6826787db2", + "reference": "f31f4980f52be17c4667f3eafe034e6826787db2", "shasum": "" }, "require": { "ext-mbstring": "*", - "illuminate/console": "^10.24|^11.0", - "illuminate/contracts": "^10.24|^11.0", - "illuminate/log": "^10.24|^11.0", - "illuminate/process": "^10.24|^11.0", - "illuminate/support": "^10.24|^11.0", + "illuminate/console": "^10.24|^11.0|^12.0", + "illuminate/contracts": "^10.24|^11.0|^12.0", + "illuminate/log": "^10.24|^11.0|^12.0", + "illuminate/process": "^10.24|^11.0|^12.0", + "illuminate/support": "^10.24|^11.0|^12.0", "nunomaduro/termwind": "^1.15|^2.0", "php": "^8.2", "symfony/console": "^6.0|^7.0" }, "require-dev": { - "laravel/framework": "^10.24|^11.0", + "laravel/framework": "^10.24|^11.0|^12.0", "laravel/pint": "^1.13", - "orchestra/testbench-core": "^8.12|^9.0", - "pestphp/pest": "^2.20", - "pestphp/pest-plugin-type-coverage": "^2.3", + "orchestra/testbench-core": "^8.13|^9.0|^10.0", + "pestphp/pest": "^2.20|^3.0", + "pestphp/pest-plugin-type-coverage": "^2.3|^3.0", "phpstan/phpstan": "^1.10", "symfony/var-dumper": "^6.3|^7.0" }, @@ -3101,20 +3101,20 @@ "issues": "https://github.com/laravel/pail/issues", "source": "https://github.com/laravel/pail" }, - "time": "2024-10-23T12:56:23+00:00" + "time": "2025-01-28T15:15:15+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.3", + "version": "v0.3.5", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "749395fcd5f8f7530fe1f00dfa84eb22c83d94ea" + "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/749395fcd5f8f7530fe1f00dfa84eb22c83d94ea", - "reference": "749395fcd5f8f7530fe1f00dfa84eb22c83d94ea", + "url": "https://api.github.com/repos/laravel/prompts/zipball/57b8f7efe40333cdb925700891c7d7465325d3b1", + "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1", "shasum": "" }, "require": { @@ -3128,7 +3128,7 @@ "laravel/framework": ">=10.17.0 <10.25.0" }, "require-dev": { - "illuminate/collections": "^10.0|^11.0", + "illuminate/collections": "^10.0|^11.0|^12.0", "mockery/mockery": "^1.5", "pestphp/pest": "^2.3|^3.4", "phpstan/phpstan": "^1.11", @@ -3158,38 +3158,38 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.3" + "source": "https://github.com/laravel/prompts/tree/v0.3.5" }, - "time": "2024-12-30T15:53:31+00:00" + "time": "2025-02-11T13:34:40+00:00" }, { "name": "laravel/sanctum", - "version": "v4.0.7", + "version": "v4.0.8", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "698064236a46df016e64a7eb059b1414e0b281df" + "reference": "ec1dd9ddb2ab370f79dfe724a101856e0963f43c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/698064236a46df016e64a7eb059b1414e0b281df", - "reference": "698064236a46df016e64a7eb059b1414e0b281df", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/ec1dd9ddb2ab370f79dfe724a101856e0963f43c", + "reference": "ec1dd9ddb2ab370f79dfe724a101856e0963f43c", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/console": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/database": "^11.0", - "illuminate/support": "^11.0", + "illuminate/console": "^11.0|^12.0", + "illuminate/contracts": "^11.0|^12.0", + "illuminate/database": "^11.0|^12.0", + "illuminate/support": "^11.0|^12.0", "php": "^8.2", "symfony/console": "^7.0" }, "require-dev": { "mockery/mockery": "^1.6", - "orchestra/testbench": "^9.0", + "orchestra/testbench": "^9.0|^10.0", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { @@ -3224,29 +3224,29 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2024-12-11T16:40:21+00:00" + "time": "2025-01-26T19:34:36+00:00" }, { "name": "laravel/serializable-closure", - "version": "v2.0.1", + "version": "v2.0.3", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "613b2d4998f85564d40497e05e89cb6d9bd1cbe8" + "reference": "f379c13663245f7aa4512a7869f62eb14095f23f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/613b2d4998f85564d40497e05e89cb6d9bd1cbe8", - "reference": "613b2d4998f85564d40497e05e89cb6d9bd1cbe8", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f379c13663245f7aa4512a7869f62eb14095f23f", + "reference": "f379c13663245f7aa4512a7869f62eb14095f23f", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "illuminate/support": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0|^12.0", "nesbot/carbon": "^2.67|^3.0", - "pestphp/pest": "^2.36", + "pestphp/pest": "^2.36|^3.0", "phpstan/phpstan": "^2.0", "symfony/var-dumper": "^6.2.0|^7.0.0" }, @@ -3285,38 +3285,38 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2024-12-16T15:26:28+00:00" + "time": "2025-02-11T15:03:05+00:00" }, { "name": "laravel/socialite", - "version": "v5.16.1", + "version": "v5.18.0", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "4e5be83c0b3ecf81b2ffa47092e917d1f79dce71" + "reference": "7809dc71250e074cd42970f0f803f2cddc04c5de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/4e5be83c0b3ecf81b2ffa47092e917d1f79dce71", - "reference": "4e5be83c0b3ecf81b2ffa47092e917d1f79dce71", + "url": "https://api.github.com/repos/laravel/socialite/zipball/7809dc71250e074cd42970f0f803f2cddc04c5de", + "reference": "7809dc71250e074cd42970f0f803f2cddc04c5de", "shasum": "" }, "require": { "ext-json": "*", "firebase/php-jwt": "^6.4", "guzzlehttp/guzzle": "^6.0|^7.0", - "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/http": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/http": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", "league/oauth1-client": "^1.11", "php": "^7.2|^8.0", "phpseclib/phpseclib": "^3.0" }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0|^9.0", + "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0|^9.0|^10.0", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.0|^9.3|^10.4" + "phpunit/phpunit": "^8.0|^9.3|^10.4|^11.5" }, "type": "library", "extra": { @@ -3357,26 +3357,26 @@ "issues": "https://github.com/laravel/socialite/issues", "source": "https://github.com/laravel/socialite" }, - "time": "2024-12-11T16:43:51+00:00" + "time": "2025-02-11T13:38:19+00:00" }, { "name": "laravel/tinker", - "version": "v2.10.0", + "version": "v2.10.1", "source": { "type": "git", "url": "https://github.com/laravel/tinker.git", - "reference": "ba4d51eb56de7711b3a37d63aa0643e99a339ae5" + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/ba4d51eb56de7711b3a37d63aa0643e99a339ae5", - "reference": "ba4d51eb56de7711b3a37d63aa0643e99a339ae5", + "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", "shasum": "" }, "require": { - "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", "php": "^7.2.5|^8.0", "psy/psysh": "^0.11.1|^0.12.0", "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" @@ -3384,10 +3384,10 @@ "require-dev": { "mockery/mockery": "~1.3.3|^1.4.2", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.5.8|^9.3.3" + "phpunit/phpunit": "^8.5.8|^9.3.3|^10.0" }, "suggest": { - "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0)." + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0)." }, "type": "library", "extra": { @@ -3421,35 +3421,35 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.10.0" + "source": "https://github.com/laravel/tinker/tree/v2.10.1" }, - "time": "2024-09-23T13:32:56+00:00" + "time": "2025-01-27T14:24:01+00:00" }, { "name": "laravel/ui", - "version": "v4.6.0", + "version": "v4.6.1", "source": { "type": "git", "url": "https://github.com/laravel/ui.git", - "reference": "a34609b15ae0c0512a0cf47a21695a2729cb7f93" + "reference": "7d6ffa38d79f19c9b3e70a751a9af845e8f41d88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/ui/zipball/a34609b15ae0c0512a0cf47a21695a2729cb7f93", - "reference": "a34609b15ae0c0512a0cf47a21695a2729cb7f93", + "url": "https://api.github.com/repos/laravel/ui/zipball/7d6ffa38d79f19c9b3e70a751a9af845e8f41d88", + "reference": "7d6ffa38d79f19c9b3e70a751a9af845e8f41d88", "shasum": "" }, "require": { - "illuminate/console": "^9.21|^10.0|^11.0", - "illuminate/filesystem": "^9.21|^10.0|^11.0", - "illuminate/support": "^9.21|^10.0|^11.0", - "illuminate/validation": "^9.21|^10.0|^11.0", + "illuminate/console": "^9.21|^10.0|^11.0|^12.0", + "illuminate/filesystem": "^9.21|^10.0|^11.0|^12.0", + "illuminate/support": "^9.21|^10.0|^11.0|^12.0", + "illuminate/validation": "^9.21|^10.0|^11.0|^12.0", "php": "^8.0", "symfony/console": "^6.0|^7.0" }, "require-dev": { - "orchestra/testbench": "^7.35|^8.15|^9.0", - "phpunit/phpunit": "^9.3|^10.4|^11.0" + "orchestra/testbench": "^7.35|^8.15|^9.0|^10.0", + "phpunit/phpunit": "^9.3|^10.4|^11.5" }, "type": "library", "extra": { @@ -3484,22 +3484,22 @@ "ui" ], "support": { - "source": "https://github.com/laravel/ui/tree/v4.6.0" + "source": "https://github.com/laravel/ui/tree/v4.6.1" }, - "time": "2024-11-21T15:06:41+00:00" + "time": "2025-01-28T15:15:29+00:00" }, { "name": "lcobucci/jwt", - "version": "5.4.2", + "version": "5.5.0", "source": { "type": "git", "url": "https://github.com/lcobucci/jwt.git", - "reference": "ea1ce71cbf9741e445a5914e2f67cdbb484ff712" + "reference": "a835af59b030d3f2967725697cf88300f579088e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/ea1ce71cbf9741e445a5914e2f67cdbb484ff712", - "reference": "ea1ce71cbf9741e445a5914e2f67cdbb484ff712", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/a835af59b030d3f2967725697cf88300f579088e", + "reference": "a835af59b030d3f2967725697cf88300f579088e", "shasum": "" }, "require": { @@ -3547,7 +3547,7 @@ ], "support": { "issues": "https://github.com/lcobucci/jwt/issues", - "source": "https://github.com/lcobucci/jwt/tree/5.4.2" + "source": "https://github.com/lcobucci/jwt/tree/5.5.0" }, "funding": [ { @@ -3559,7 +3559,7 @@ "type": "patreon" } ], - "time": "2024-11-07T12:54:35+00:00" + "time": "2025-01-26T21:29:45+00:00" }, { "name": "league/commonmark", @@ -4294,23 +4294,23 @@ }, { "name": "livewire/livewire", - "version": "v3.5.18", + "version": "v3.5.20", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "62f0fa6b340a467c25baa590a567d9a134b357da" + "reference": "509f2258c51741f6d06deb65d4437654520694e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/62f0fa6b340a467c25baa590a567d9a134b357da", - "reference": "62f0fa6b340a467c25baa590a567d9a134b357da", + "url": "https://api.github.com/repos/livewire/livewire/zipball/509f2258c51741f6d06deb65d4437654520694e6", + "reference": "509f2258c51741f6d06deb65d4437654520694e6", "shasum": "" }, "require": { - "illuminate/database": "^10.0|^11.0", - "illuminate/routing": "^10.0|^11.0", - "illuminate/support": "^10.0|^11.0", - "illuminate/validation": "^10.0|^11.0", + "illuminate/database": "^10.0|^11.0|^12.0", + "illuminate/routing": "^10.0|^11.0|^12.0", + "illuminate/support": "^10.0|^11.0|^12.0", + "illuminate/validation": "^10.0|^11.0|^12.0", "laravel/prompts": "^0.1.24|^0.2|^0.3", "league/mime-type-detection": "^1.9", "php": "^8.1", @@ -4319,11 +4319,11 @@ }, "require-dev": { "calebporzio/sushi": "^2.1", - "laravel/framework": "^10.15.0|^11.0", + "laravel/framework": "^10.15.0|^11.0|^12.0", "mockery/mockery": "^1.3.1", - "orchestra/testbench": "^8.21.0|^9.0", - "orchestra/testbench-dusk": "^8.24|^9.1", - "phpunit/phpunit": "^10.4", + "orchestra/testbench": "^8.21.0|^9.0|^10.0", + "orchestra/testbench-dusk": "^8.24|^9.1|^10.0", + "phpunit/phpunit": "^10.4|^11.5", "psy/psysh": "^0.11.22|^0.12" }, "type": "library", @@ -4358,7 +4358,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.5.18" + "source": "https://github.com/livewire/livewire/tree/v3.5.20" }, "funding": [ { @@ -4366,7 +4366,7 @@ "type": "github" } ], - "time": "2024-12-23T15:05:02+00:00" + "time": "2025-02-13T21:05:24+00:00" }, { "name": "log1x/laravel-webfonts", @@ -4432,16 +4432,16 @@ }, { "name": "lorisleiva/laravel-actions", - "version": "v2.8.5", + "version": "v2.8.6", "source": { "type": "git", "url": "https://github.com/lorisleiva/laravel-actions.git", - "reference": "ae6f5e8dc1f450a0879f73059242e5834b2dbdec" + "reference": "4647523599bee13cfd6b9bc9acdaf4503d4801ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lorisleiva/laravel-actions/zipball/ae6f5e8dc1f450a0879f73059242e5834b2dbdec", - "reference": "ae6f5e8dc1f450a0879f73059242e5834b2dbdec", + "url": "https://api.github.com/repos/lorisleiva/laravel-actions/zipball/4647523599bee13cfd6b9bc9acdaf4503d4801ce", + "reference": "4647523599bee13cfd6b9bc9acdaf4503d4801ce", "shasum": "" }, "require": { @@ -4496,7 +4496,7 @@ ], "support": { "issues": "https://github.com/lorisleiva/laravel-actions/issues", - "source": "https://github.com/lorisleiva/laravel-actions/tree/v2.8.5" + "source": "https://github.com/lorisleiva/laravel-actions/tree/v2.8.6" }, "funding": [ { @@ -4504,7 +4504,7 @@ "type": "github" } ], - "time": "2024-12-19T15:58:09+00:00" + "time": "2025-02-04T08:36:29+00:00" }, { "name": "lorisleiva/lody", @@ -4749,16 +4749,16 @@ }, { "name": "nesbot/carbon", - "version": "3.8.4", + "version": "3.8.6", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "129700ed449b1f02d70272d2ac802357c8c30c58" + "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/129700ed449b1f02d70272d2ac802357c8c30c58", - "reference": "129700ed449b1f02d70272d2ac802357c8c30c58", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ff2f20cf83bd4d503720632ce8a426dc747bf7fd", + "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd", "shasum": "" }, "require": { @@ -4834,8 +4834,8 @@ ], "support": { "docs": "https://carbon.nesbot.com/docs", - "issues": "https://github.com/briannesbitt/Carbon/issues", - "source": "https://github.com/briannesbitt/Carbon" + "issues": "https://github.com/CarbonPHP/carbon/issues", + "source": "https://github.com/CarbonPHP/carbon" }, "funding": [ { @@ -4851,7 +4851,7 @@ "type": "tidelift" } ], - "time": "2024-12-27T09:25:35+00:00" + "time": "2025-02-20T17:33:38+00:00" }, { "name": "nette/schema", @@ -5485,6 +5485,134 @@ }, "time": "2024-09-04T12:51:01+00:00" }, + { + "name": "php-di/invoker", + "version": "2.3.6", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/Invoker.git", + "reference": "59f15608528d8a8838d69b422a919fd6b16aa576" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/59f15608528d8a8838d69b422a919fd6b16aa576", + "reference": "59f15608528d8a8838d69b422a919fd6b16aa576", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "psr/container": "^1.0|^2.0" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "mnapoli/hard-mode": "~0.3.0", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Invoker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Generic and extensible callable invoker", + "homepage": "https://github.com/PHP-DI/Invoker", + "keywords": [ + "callable", + "dependency", + "dependency-injection", + "injection", + "invoke", + "invoker" + ], + "support": { + "issues": "https://github.com/PHP-DI/Invoker/issues", + "source": "https://github.com/PHP-DI/Invoker/tree/2.3.6" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + } + ], + "time": "2025-01-17T12:49:27+00:00" + }, + { + "name": "php-di/php-di", + "version": "7.0.8", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/PHP-DI.git", + "reference": "98ddc81f8f768a2ad39e4cbe737285eaeabe577a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/98ddc81f8f768a2ad39e4cbe737285eaeabe577a", + "reference": "98ddc81f8f768a2ad39e4cbe737285eaeabe577a", + "shasum": "" + }, + "require": { + "laravel/serializable-closure": "^1.0 || ^2.0", + "php": ">=8.0", + "php-di/invoker": "^2.0", + "psr/container": "^1.1 || ^2.0" + }, + "provide": { + "psr/container-implementation": "^1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3", + "friendsofphp/proxy-manager-lts": "^1", + "mnapoli/phpunit-easymock": "^1.3", + "phpunit/phpunit": "^9.6", + "vimeo/psalm": "^4.6" + }, + "suggest": { + "friendsofphp/proxy-manager-lts": "Install it if you want to use lazy injection (version ^1)" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "DI\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The dependency injection container for humans", + "homepage": "https://php-di.org/", + "keywords": [ + "PSR-11", + "container", + "container-interop", + "dependency injection", + "di", + "ioc", + "psr11" + ], + "support": { + "issues": "https://github.com/PHP-DI/PHP-DI/issues", + "source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.8" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/php-di/php-di", + "type": "tidelift" + } + ], + "time": "2025-01-28T21:02:46+00:00" + }, { "name": "phpdocumentor/reflection", "version": "6.1.0", @@ -5914,16 +6042,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299" + "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/c00d78fb6b29658347f9d37ebe104bffadf36299", - "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", + "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", "shasum": "" }, "require": { @@ -5955,62 +6083,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.1.0" }, - "time": "2024-10-13T11:29:49+00:00" - }, - { - "name": "pimple/pimple", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/silexphp/Pimple.git", - "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a94b3a4db7fb774b3d78dad2315ddc07629e1bed", - "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1 || ^2.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^5.4@dev" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4.x-dev" - } - }, - "autoload": { - "psr-0": { - "Pimple": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Pimple, a simple Dependency Injection Container", - "homepage": "https://pimple.symfony.com", - "keywords": [ - "container", - "dependency injection" - ], - "support": { - "source": "https://github.com/silexphp/Pimple/tree/v3.5.0" - }, - "time": "2021-10-28T11:13:42+00:00" + "time": "2025-02-19T13:28:12+00:00" }, { "name": "pion/laravel-chunk-upload", @@ -7176,16 +7251,16 @@ }, { "name": "revolt/event-loop", - "version": "v1.0.6", + "version": "v1.0.7", "source": { "type": "git", "url": "https://github.com/revoltphp/event-loop.git", - "reference": "25de49af7223ba039f64da4ae9a28ec2d10d0254" + "reference": "09bf1bf7f7f574453efe43044b06fafe12216eb3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/25de49af7223ba039f64da4ae9a28ec2d10d0254", - "reference": "25de49af7223ba039f64da4ae9a28ec2d10d0254", + "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/09bf1bf7f7f574453efe43044b06fafe12216eb3", + "reference": "09bf1bf7f7f574453efe43044b06fafe12216eb3", "shasum": "" }, "require": { @@ -7242,9 +7317,9 @@ ], "support": { "issues": "https://github.com/revoltphp/event-loop/issues", - "source": "https://github.com/revoltphp/event-loop/tree/v1.0.6" + "source": "https://github.com/revoltphp/event-loop/tree/v1.0.7" }, - "time": "2023-11-30T05:34:44+00:00" + "time": "2025-01-25T19:27:39+00:00" }, { "name": "sentry/sentry", @@ -7337,20 +7412,20 @@ }, { "name": "sentry/sentry-laravel", - "version": "4.10.2", + "version": "4.13.0", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-laravel.git", - "reference": "0e2e5bc4311da51349487afcf67b8fca937f6d94" + "reference": "d232ac494258e0d50a77c575a5af5f1a426d3f87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/0e2e5bc4311da51349487afcf67b8fca937f6d94", - "reference": "0e2e5bc4311da51349487afcf67b8fca937f6d94", + "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/d232ac494258e0d50a77c575a5af5f1a426d3f87", + "reference": "d232ac494258e0d50a77c575a5af5f1a426d3f87", "shasum": "" }, "require": { - "illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0", + "illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0", "nyholm/psr7": "^1.0", "php": "^7.2 | ^8.0", "sentry/sentry": "^4.10", @@ -7360,12 +7435,12 @@ "friendsofphp/php-cs-fixer": "^3.11", "guzzlehttp/guzzle": "^7.2", "laravel/folio": "^1.1", - "laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0", + "laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0", "livewire/livewire": "^2.0 | ^3.0", "mockery/mockery": "^1.3", - "orchestra/testbench": "^4.7 | ^5.1 | ^6.0 | ^7.0 | ^8.0 | ^9.0", + "orchestra/testbench": "^4.7 | ^5.1 | ^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.4 | ^9.3 | ^10.4" + "phpunit/phpunit": "^8.4 | ^9.3 | ^10.4 | ^11.5" }, "type": "library", "extra": { @@ -7410,7 +7485,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-laravel/issues", - "source": "https://github.com/getsentry/sentry-laravel/tree/4.10.2" + "source": "https://github.com/getsentry/sentry-laravel/tree/4.13.0" }, "funding": [ { @@ -7422,7 +7497,7 @@ "type": "custom" } ], - "time": "2024-12-17T11:38:58+00:00" + "time": "2025-02-18T10:09:29+00:00" }, { "name": "socialiteproviders/authentik", @@ -7715,29 +7790,29 @@ }, { "name": "spatie/laravel-activitylog", - "version": "4.9.1", + "version": "4.10.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-activitylog.git", - "reference": "9abddaa9f2681d97943748c7fa04161cf4642e8c" + "reference": "466f30f7245fe3a6e328ad5e6812bd43b4bddea5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/9abddaa9f2681d97943748c7fa04161cf4642e8c", - "reference": "9abddaa9f2681d97943748c7fa04161cf4642e8c", + "url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/466f30f7245fe3a6e328ad5e6812bd43b4bddea5", + "reference": "466f30f7245fe3a6e328ad5e6812bd43b4bddea5", "shasum": "" }, "require": { - "illuminate/config": "^8.0 || ^9.0 || ^10.0 || ^11.0", - "illuminate/database": "^8.69 || ^9.27 || ^10.0 || ^11.0", - "illuminate/support": "^8.0 || ^9.0 || ^10.0 || ^11.0", + "illuminate/config": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "illuminate/database": "^8.69 || ^9.27 || ^10.0 || ^11.0 || ^12.0", + "illuminate/support": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", "php": "^8.1", "spatie/laravel-package-tools": "^1.6.3" }, "require-dev": { "ext-json": "*", - "orchestra/testbench": "^6.23 || ^7.0 || ^8.0 || ^9.0", - "pestphp/pest": "^1.20 || ^2.0" + "orchestra/testbench": "^6.23 || ^7.0 || ^8.0 || ^9.0 || ^10.0", + "pestphp/pest": "^1.20 || ^2.0 || ^3.0" }, "type": "library", "extra": { @@ -7790,7 +7865,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-activitylog/issues", - "source": "https://github.com/spatie/laravel-activitylog/tree/4.9.1" + "source": "https://github.com/spatie/laravel-activitylog/tree/4.10.1" }, "funding": [ { @@ -7802,24 +7877,24 @@ "type": "github" } ], - "time": "2024-11-18T11:31:57+00:00" + "time": "2025-02-10T15:38:25+00:00" }, { "name": "spatie/laravel-data", - "version": "4.11.1", + "version": "4.13.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-data.git", - "reference": "df5b58baebae34475ca35338b4e9a131c9e2a8e0" + "reference": "14252330397cf84647cc086324ea1a30dbe5f7cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-data/zipball/df5b58baebae34475ca35338b4e9a131c9e2a8e0", - "reference": "df5b58baebae34475ca35338b4e9a131c9e2a8e0", + "url": "https://api.github.com/repos/spatie/laravel-data/zipball/14252330397cf84647cc086324ea1a30dbe5f7cc", + "reference": "14252330397cf84647cc086324ea1a30dbe5f7cc", "shasum": "" }, "require": { - "illuminate/contracts": "^10.0|^11.0", + "illuminate/contracts": "^10.0|^11.0|^12.0", "php": "^8.1", "phpdocumentor/reflection": "^6.0", "spatie/laravel-package-tools": "^1.9.0", @@ -7828,18 +7903,16 @@ "require-dev": { "fakerphp/faker": "^1.14", "friendsofphp/php-cs-fixer": "^3.0", - "inertiajs/inertia-laravel": "^1.2", "livewire/livewire": "^3.0", "mockery/mockery": "^1.6", - "nesbot/carbon": "^2.63", - "nunomaduro/larastan": "^2.0", - "orchestra/testbench": "^8.0|^9.0", - "pestphp/pest": "^2.31", - "pestphp/pest-plugin-laravel": "^2.0", - "pestphp/pest-plugin-livewire": "^2.1", + "nesbot/carbon": "^2.63|^3.0", + "orchestra/testbench": "^8.0|^9.0|^10.0", + "pestphp/pest": "^2.31|^3.0", + "pestphp/pest-plugin-laravel": "^2.0|^3.0", + "pestphp/pest-plugin-livewire": "^2.1|^3.0", "phpbench/phpbench": "^1.2", "phpstan/extension-installer": "^1.1", - "phpunit/phpunit": "^10.0", + "phpunit/phpunit": "^10.0|^11.0|^12.0", "spatie/invade": "^1.0", "spatie/laravel-typescript-transformer": "^2.5", "spatie/pest-plugin-snapshots": "^2.1", @@ -7878,7 +7951,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-data/issues", - "source": "https://github.com/spatie/laravel-data/tree/4.11.1" + "source": "https://github.com/spatie/laravel-data/tree/4.13.1" }, "funding": [ { @@ -7886,31 +7959,31 @@ "type": "github" } ], - "time": "2024-10-23T07:14:53+00:00" + "time": "2025-02-14T14:29:16+00:00" }, { "name": "spatie/laravel-package-tools", - "version": "1.18.0", + "version": "1.19.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-package-tools.git", - "reference": "8332205b90d17164913244f4a8e13ab7e6761d29" + "reference": "1c9c30ac6a6576b8d15c6c37b6cf23d748df2faa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/8332205b90d17164913244f4a8e13ab7e6761d29", - "reference": "8332205b90d17164913244f4a8e13ab7e6761d29", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/1c9c30ac6a6576b8d15c6c37b6cf23d748df2faa", + "reference": "1c9c30ac6a6576b8d15c6c37b6cf23d748df2faa", "shasum": "" }, "require": { - "illuminate/contracts": "^9.28|^10.0|^11.0", + "illuminate/contracts": "^9.28|^10.0|^11.0|^12.0", "php": "^8.0" }, "require-dev": { "mockery/mockery": "^1.5", - "orchestra/testbench": "^7.7|^8.0|^9.0", - "pestphp/pest": "^1.22|^2", - "phpunit/phpunit": "^9.5.24|^10.5", + "orchestra/testbench": "^7.7|^8.0|^9.0|^10.0", + "pestphp/pest": "^1.23|^2.1|^3.1", + "phpunit/phpunit": "^9.5.24|^10.5|^11.5", "spatie/pest-plugin-test-time": "^1.1|^2.2" }, "type": "library", @@ -7938,7 +8011,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-package-tools/issues", - "source": "https://github.com/spatie/laravel-package-tools/tree/1.18.0" + "source": "https://github.com/spatie/laravel-package-tools/tree/1.19.0" }, "funding": [ { @@ -7946,43 +8019,43 @@ "type": "github" } ], - "time": "2024-12-30T13:13:39+00:00" + "time": "2025-02-06T14:58:20+00:00" }, { "name": "spatie/laravel-ray", - "version": "1.39.0", + "version": "1.39.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ray.git", - "reference": "31b601f98590606d20e76b5dd68578dc1642cd2c" + "reference": "0d890fa2cd2c0b6175cf54c56b9321d81047571d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ray/zipball/31b601f98590606d20e76b5dd68578dc1642cd2c", - "reference": "31b601f98590606d20e76b5dd68578dc1642cd2c", + "url": "https://api.github.com/repos/spatie/laravel-ray/zipball/0d890fa2cd2c0b6175cf54c56b9321d81047571d", + "reference": "0d890fa2cd2c0b6175cf54c56b9321d81047571d", "shasum": "" }, "require": { "composer-runtime-api": "^2.2", "ext-json": "*", - "illuminate/contracts": "^7.20 || ^8.19 || ^9.0 || ^10.0 || ^11.0", - "illuminate/database": "^7.20 || ^8.19 || ^9.0 || ^10.0 || ^11.0", - "illuminate/queue": "^7.20 || ^8.19 || ^9.0 || ^10.0 || ^11.0", - "illuminate/support": "^7.20 || ^8.19 || ^9.0 || ^10.0 || ^11.0", + "illuminate/contracts": "^7.20 || ^8.19 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "illuminate/database": "^7.20 || ^8.19 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "illuminate/queue": "^7.20 || ^8.19 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "illuminate/support": "^7.20 || ^8.19 || ^9.0 || ^10.0 || ^11.0 || ^12.0", "php": "^7.4 || ^8.0", - "spatie/backtrace": "^1.0", + "spatie/backtrace": "^1.7.1", "spatie/ray": "^1.41.3", "symfony/stopwatch": "4.2 || ^5.1 || ^6.0 || ^7.0", "zbateson/mail-mime-parser": "^1.3.1 || ^2.0 || ^3.0" }, "require-dev": { "guzzlehttp/guzzle": "^7.3", - "laravel/framework": "^7.20 || ^8.19 || ^9.0 || ^10.0 || ^11.0", - "orchestra/testbench-core": "^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0", - "pestphp/pest": "^1.22 || ^2.0", + "laravel/framework": "^7.20 || ^8.19 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "orchestra/testbench-core": "^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0", + "pestphp/pest": "^1.22 || ^2.0 || ^3.0", "phpstan/phpstan": "^1.10.57 || ^2.0.2", - "phpunit/phpunit": "^9.3 || ^10.1", - "rector/rector": "dev-main", + "phpunit/phpunit": "^9.3 || ^10.1 || ^11.0.10", + "rector/rector": "^0.19.2 || ^1.0.1 || ^2.0.0", "spatie/pest-plugin-snapshots": "^1.1 || ^2.0", "symfony/var-dumper": "^4.2 || ^5.1 || ^6.0 || ^7.0.3" }, @@ -8022,7 +8095,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-ray/issues", - "source": "https://github.com/spatie/laravel-ray/tree/1.39.0" + "source": "https://github.com/spatie/laravel-ray/tree/1.39.1" }, "funding": [ { @@ -8034,26 +8107,26 @@ "type": "other" } ], - "time": "2024-12-11T09:34:41+00:00" + "time": "2025-02-05T08:16:15+00:00" }, { "name": "spatie/laravel-schemaless-attributes", - "version": "2.5.0", + "version": "2.5.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-schemaless-attributes.git", - "reference": "f7b00a3e224728d6385af81069a75a162ab1ff04" + "reference": "3561875fb6886ae55e5378f20ba5ac87f20b265a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-schemaless-attributes/zipball/f7b00a3e224728d6385af81069a75a162ab1ff04", - "reference": "f7b00a3e224728d6385af81069a75a162ab1ff04", + "url": "https://api.github.com/repos/spatie/laravel-schemaless-attributes/zipball/3561875fb6886ae55e5378f20ba5ac87f20b265a", + "reference": "3561875fb6886ae55e5378f20ba5ac87f20b265a", "shasum": "" }, "require": { - "illuminate/contracts": "^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/database": "^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/support": "^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/contracts": "^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/database": "^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", "php": "^8.0", "spatie/laravel-package-tools": "^1.4.3" }, @@ -8061,9 +8134,9 @@ "brianium/paratest": "^6.2|^7.4", "mockery/mockery": "^1.4", "nunomaduro/collision": "^5.3|^6.0|^8.0", - "orchestra/testbench": "^6.15|^7.0|^8.0|^9.0", - "pestphp/pest-plugin-laravel": "^1.3|^2.1", - "phpunit/phpunit": "^9.6|^10.5" + "orchestra/testbench": "^6.15|^7.0|^8.0|^9.0|^10.0", + "pestphp/pest-plugin-laravel": "^1.3|^2.1|^3.1", + "phpunit/phpunit": "^9.6|^10.5|^11.5|^12.0" }, "type": "library", "extra": { @@ -8098,7 +8171,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-schemaless-attributes/issues", - "source": "https://github.com/spatie/laravel-schemaless-attributes/tree/2.5.0" + "source": "https://github.com/spatie/laravel-schemaless-attributes/tree/2.5.1" }, "funding": [ { @@ -8110,7 +8183,7 @@ "type": "github" } ], - "time": "2024-02-29T08:18:20+00:00" + "time": "2025-02-10T09:28:22+00:00" }, { "name": "spatie/macroable", @@ -8164,38 +8237,37 @@ }, { "name": "spatie/php-structure-discoverer", - "version": "2.3.0", + "version": "2.3.1", "source": { "type": "git", "url": "https://github.com/spatie/php-structure-discoverer.git", - "reference": "42d161298630ede76c61e8a437a06eea2e106f4c" + "reference": "42f4d731d3dd4b3b85732e05a8c1928fcfa2f4bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/php-structure-discoverer/zipball/42d161298630ede76c61e8a437a06eea2e106f4c", - "reference": "42d161298630ede76c61e8a437a06eea2e106f4c", + "url": "https://api.github.com/repos/spatie/php-structure-discoverer/zipball/42f4d731d3dd4b3b85732e05a8c1928fcfa2f4bc", + "reference": "42f4d731d3dd4b3b85732e05a8c1928fcfa2f4bc", "shasum": "" }, "require": { "amphp/amp": "^v3.0", "amphp/parallel": "^2.2", - "illuminate/collections": "^10.0|^11.0", + "illuminate/collections": "^10.0|^11.0|^12.0", "php": "^8.1", "spatie/laravel-package-tools": "^1.4.3", "symfony/finder": "^6.0|^7.0" }, "require-dev": { - "illuminate/console": "^10.0|^11.0", + "illuminate/console": "^10.0|^11.0|^12.0", "laravel/pint": "^1.0", "nunomaduro/collision": "^7.0|^8.0", - "nunomaduro/larastan": "^2.0.1", - "orchestra/testbench": "^7.0|^8.0|^9.0", - "pestphp/pest": "^2.0", - "pestphp/pest-plugin-laravel": "^2.0", + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", + "pestphp/pest": "^2.0|^3.0", + "pestphp/pest-plugin-laravel": "^2.0|^3.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^9.5|^10.0", + "phpunit/phpunit": "^9.5|^10.0|^11.5.3", "spatie/laravel-ray": "^1.26" }, "type": "library", @@ -8232,7 +8304,7 @@ ], "support": { "issues": "https://github.com/spatie/php-structure-discoverer/issues", - "source": "https://github.com/spatie/php-structure-discoverer/tree/2.3.0" + "source": "https://github.com/spatie/php-structure-discoverer/tree/2.3.1" }, "funding": [ { @@ -8240,20 +8312,20 @@ "type": "github" } ], - "time": "2025-01-13T13:15:29+00:00" + "time": "2025-02-14T10:18:38+00:00" }, { "name": "spatie/ray", - "version": "1.41.4", + "version": "1.41.5", "source": { "type": "git", "url": "https://github.com/spatie/ray.git", - "reference": "c5dbda0548c1881b30549ccc0b6d485f7471aaa5" + "reference": "9d078f04ffa32ad543a20716844ec343fdd7d856" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ray/zipball/c5dbda0548c1881b30549ccc0b6d485f7471aaa5", - "reference": "c5dbda0548c1881b30549ccc0b6d485f7471aaa5", + "url": "https://api.github.com/repos/spatie/ray/zipball/9d078f04ffa32ad543a20716844ec343fdd7d856", + "reference": "9d078f04ffa32ad543a20716844ec343fdd7d856", "shasum": "" }, "require": { @@ -8261,18 +8333,18 @@ "ext-json": "*", "php": "^7.4 || ^8.0", "ramsey/uuid": "^3.0 || ^4.1", - "spatie/backtrace": "^1.1", + "spatie/backtrace": "^1.7.1", "spatie/macroable": "^1.0 || ^2.0", "symfony/stopwatch": "^4.2 || ^5.1 || ^6.0 || ^7.0", "symfony/var-dumper": "^4.2 || ^5.1 || ^6.0 || ^7.0.3" }, "require-dev": { - "illuminate/support": "^7.20 || ^8.18 || ^9.0 || ^10.0 || ^11.0", - "nesbot/carbon": "^2.63", + "illuminate/support": "^7.20 || ^8.18 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "nesbot/carbon": "^2.63 || ^3.8.4", "pestphp/pest": "^1.22", - "phpstan/phpstan": "^1.10.57 || ^2.0.2", + "phpstan/phpstan": "^1.10.57 || ^2.0.3", "phpunit/phpunit": "^9.5", - "rector/rector": "dev-main", + "rector/rector": "^0.19.2 || ^1.0.1 || ^2.0.0", "spatie/phpunit-snapshot-assertions": "^4.2", "spatie/test-time": "^1.2" }, @@ -8313,7 +8385,7 @@ ], "support": { "issues": "https://github.com/spatie/ray/issues", - "source": "https://github.com/spatie/ray/tree/1.41.4" + "source": "https://github.com/spatie/ray/tree/1.41.5" }, "funding": [ { @@ -8325,7 +8397,7 @@ "type": "other" } ], - "time": "2024-12-09T11:32:15+00:00" + "time": "2025-02-14T12:51:43+00:00" }, { "name": "spatie/url", @@ -8391,27 +8463,27 @@ }, { "name": "stevebauman/purify", - "version": "v6.2.2", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/stevebauman/purify.git", - "reference": "a449299a3d5f5f8ef177e626721b3f69143890a4" + "reference": "2e5e6e1bfe072189b6056c6ad4a8c68ba57f3ba1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stevebauman/purify/zipball/a449299a3d5f5f8ef177e626721b3f69143890a4", - "reference": "a449299a3d5f5f8ef177e626721b3f69143890a4", + "url": "https://api.github.com/repos/stevebauman/purify/zipball/2e5e6e1bfe072189b6056c6ad4a8c68ba57f3ba1", + "reference": "2e5e6e1bfe072189b6056c6ad4a8c68ba57f3ba1", "shasum": "" }, "require": { "ezyang/htmlpurifier": "^4.17", - "illuminate/contracts": "^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/support": "^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/contracts": "^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", "php": ">=7.4" }, "require-dev": { - "orchestra/testbench": "^5.0|^6.0|^7.0|^8.0|^9.0", - "phpunit/phpunit": "^8.0|^9.0|^10.0" + "orchestra/testbench": "^5.0|^6.0|^7.0|^8.0|^9.0|^10.0", + "phpunit/phpunit": "^8.0|^9.0|^10.0|^11.5.3" }, "type": "library", "extra": { @@ -8451,22 +8523,22 @@ ], "support": { "issues": "https://github.com/stevebauman/purify/issues", - "source": "https://github.com/stevebauman/purify/tree/v6.2.2" + "source": "https://github.com/stevebauman/purify/tree/v6.3.0" }, - "time": "2024-09-24T12:27:10+00:00" + "time": "2025-02-18T23:08:15+00:00" }, { "name": "stripe/stripe-php", - "version": "v16.4.0", + "version": "v16.5.1", "source": { "type": "git", "url": "https://github.com/stripe/stripe-php.git", - "reference": "4aa86099f888db9368f5f778f29feb14e6294dfb" + "reference": "05c7c3a8a15b1bc396f09d17c88539c0db3d3255" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stripe/stripe-php/zipball/4aa86099f888db9368f5f778f29feb14e6294dfb", - "reference": "4aa86099f888db9368f5f778f29feb14e6294dfb", + "url": "https://api.github.com/repos/stripe/stripe-php/zipball/05c7c3a8a15b1bc396f09d17c88539c0db3d3255", + "reference": "05c7c3a8a15b1bc396f09d17c88539c0db3d3255", "shasum": "" }, "require": { @@ -8510,9 +8582,9 @@ ], "support": { "issues": "https://github.com/stripe/stripe-php/issues", - "source": "https://github.com/stripe/stripe-php/tree/v16.4.0" + "source": "https://github.com/stripe/stripe-php/tree/v16.5.1" }, - "time": "2024-12-18T23:42:15+00:00" + "time": "2025-02-07T21:24:29+00:00" }, { "name": "symfony/clock", @@ -8815,16 +8887,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.2.1", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "6150b89186573046167796fa5f3f76601d5145f8" + "reference": "959a74d044a6db21f4caa6d695648dcb5584cb49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/6150b89186573046167796fa5f3f76601d5145f8", - "reference": "6150b89186573046167796fa5f3f76601d5145f8", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/959a74d044a6db21f4caa6d695648dcb5584cb49", + "reference": "959a74d044a6db21f4caa6d695648dcb5584cb49", "shasum": "" }, "require": { @@ -8870,7 +8942,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.2.1" + "source": "https://github.com/symfony/error-handler/tree/v7.2.3" }, "funding": [ { @@ -8886,7 +8958,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:50:44+00:00" + "time": "2025-01-07T09:39:55+00:00" }, { "name": "symfony/event-dispatcher", @@ -9110,16 +9182,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.2.2", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "62d1a43796ca3fea3f83a8470dfe63a4af3bc588" + "reference": "ee1b504b8926198be89d05e5b6fc4c3810c090f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/62d1a43796ca3fea3f83a8470dfe63a4af3bc588", - "reference": "62d1a43796ca3fea3f83a8470dfe63a4af3bc588", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ee1b504b8926198be89d05e5b6fc4c3810c090f0", + "reference": "ee1b504b8926198be89d05e5b6fc4c3810c090f0", "shasum": "" }, "require": { @@ -9168,7 +9240,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.2.2" + "source": "https://github.com/symfony/http-foundation/tree/v7.2.3" }, "funding": [ { @@ -9184,20 +9256,20 @@ "type": "tidelift" } ], - "time": "2024-12-30T19:00:17+00:00" + "time": "2025-01-17T10:56:55+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.2.2", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "3c432966bd8c7ec7429663105f5a02d7e75b4306" + "reference": "caae9807f8e25a9b43ce8cc6fafab6cf91f0cc9b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3c432966bd8c7ec7429663105f5a02d7e75b4306", - "reference": "3c432966bd8c7ec7429663105f5a02d7e75b4306", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/caae9807f8e25a9b43ce8cc6fafab6cf91f0cc9b", + "reference": "caae9807f8e25a9b43ce8cc6fafab6cf91f0cc9b", "shasum": "" }, "require": { @@ -9282,7 +9354,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.2" + "source": "https://github.com/symfony/http-kernel/tree/v7.2.3" }, "funding": [ { @@ -9298,20 +9370,20 @@ "type": "tidelift" } ], - "time": "2024-12-31T14:59:40+00:00" + "time": "2025-01-29T07:40:13+00:00" }, { "name": "symfony/mailer", - "version": "v7.2.0", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "e4d358702fb66e4c8a2af08e90e7271a62de39cc" + "reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/e4d358702fb66e4c8a2af08e90e7271a62de39cc", - "reference": "e4d358702fb66e4c8a2af08e90e7271a62de39cc", + "url": "https://api.github.com/repos/symfony/mailer/zipball/f3871b182c44997cf039f3b462af4a48fb85f9d3", + "reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3", "shasum": "" }, "require": { @@ -9362,7 +9434,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.2.0" + "source": "https://github.com/symfony/mailer/tree/v7.2.3" }, "funding": [ { @@ -9378,20 +9450,20 @@ "type": "tidelift" } ], - "time": "2024-11-25T15:21:05+00:00" + "time": "2025-01-27T11:08:17+00:00" }, { "name": "symfony/mime", - "version": "v7.2.1", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283" + "reference": "2fc3b4bd67e4747e45195bc4c98bea4628476204" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/7f9617fcf15cb61be30f8b252695ed5e2bfac283", - "reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283", + "url": "https://api.github.com/repos/symfony/mime/zipball/2fc3b4bd67e4747e45195bc4c98bea4628476204", + "reference": "2fc3b4bd67e4747e45195bc4c98bea4628476204", "shasum": "" }, "require": { @@ -9446,7 +9518,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.2.1" + "source": "https://github.com/symfony/mime/tree/v7.2.3" }, "funding": [ { @@ -9462,7 +9534,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:50:44+00:00" + "time": "2025-01-27T11:08:17+00:00" }, { "name": "symfony/options-resolver", @@ -10393,16 +10465,16 @@ }, { "name": "symfony/routing", - "version": "v7.2.0", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "e10a2450fa957af6c448b9b93c9010a4e4c0725e" + "reference": "ee9a67edc6baa33e5fae662f94f91fd262930996" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/e10a2450fa957af6c448b9b93c9010a4e4c0725e", - "reference": "e10a2450fa957af6c448b9b93c9010a4e4c0725e", + "url": "https://api.github.com/repos/symfony/routing/zipball/ee9a67edc6baa33e5fae662f94f91fd262930996", + "reference": "ee9a67edc6baa33e5fae662f94f91fd262930996", "shasum": "" }, "require": { @@ -10454,7 +10526,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.2.0" + "source": "https://github.com/symfony/routing/tree/v7.2.3" }, "funding": [ { @@ -10470,7 +10542,7 @@ "type": "tidelift" } ], - "time": "2024-11-25T11:08:51+00:00" + "time": "2025-01-17T10:56:55+00:00" }, { "name": "symfony/service-contracts", @@ -10953,16 +11025,16 @@ }, { "name": "symfony/var-dumper", - "version": "v7.2.0", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c" + "reference": "82b478c69745d8878eb60f9a049a4d584996f73a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c6a22929407dec8765d6e2b6ff85b800b245879c", - "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/82b478c69745d8878eb60f9a049a4d584996f73a", + "reference": "82b478c69745d8878eb60f9a049a4d584996f73a", "shasum": "" }, "require": { @@ -11016,7 +11088,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.2.0" + "source": "https://github.com/symfony/var-dumper/tree/v7.2.3" }, "funding": [ { @@ -11032,20 +11104,20 @@ "type": "tidelift" } ], - "time": "2024-11-08T15:48:14+00:00" + "time": "2025-01-17T11:39:41+00:00" }, { "name": "symfony/yaml", - "version": "v7.2.0", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "099581e99f557e9f16b43c5916c26380b54abb22" + "reference": "ac238f173df0c9c1120f862d0f599e17535a87ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/099581e99f557e9f16b43c5916c26380b54abb22", - "reference": "099581e99f557e9f16b43c5916c26380b54abb22", + "url": "https://api.github.com/repos/symfony/yaml/zipball/ac238f173df0c9c1120f862d0f599e17535a87ec", + "reference": "ac238f173df0c9c1120f862d0f599e17535a87ec", "shasum": "" }, "require": { @@ -11088,7 +11160,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.2.0" + "source": "https://github.com/symfony/yaml/tree/v7.2.3" }, "funding": [ { @@ -11104,7 +11176,7 @@ "type": "tidelift" } ], - "time": "2024-10-23T06:56:12+00:00" + "time": "2025-01-07T12:55:42+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -11547,30 +11619,31 @@ }, { "name": "zbateson/mail-mime-parser", - "version": "2.4.1", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/zbateson/mail-mime-parser.git", - "reference": "ff49e02f6489b38f7cc3d1bd3971adc0f872569c" + "reference": "e0d4423fe27850c9dd301190767dbc421acc2f19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/ff49e02f6489b38f7cc3d1bd3971adc0f872569c", - "reference": "ff49e02f6489b38f7cc3d1bd3971adc0f872569c", + "url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/e0d4423fe27850c9dd301190767dbc421acc2f19", + "reference": "e0d4423fe27850c9dd301190767dbc421acc2f19", "shasum": "" }, "require": { - "guzzlehttp/psr7": "^1.7.0|^2.0", - "php": ">=7.1", - "pimple/pimple": "^3.0", - "zbateson/mb-wrapper": "^1.0.1", - "zbateson/stream-decorators": "^1.0.6" + "guzzlehttp/psr7": "^2.5", + "php": ">=8.0", + "php-di/php-di": "^6.0|^7.0", + "psr/log": "^1|^2|^3", + "zbateson/mb-wrapper": "^2.0", + "zbateson/stream-decorators": "^2.1" }, "require-dev": { "friendsofphp/php-cs-fixer": "*", - "mikey179/vfsstream": "^1.6.0", + "monolog/monolog": "^2|^3", "phpstan/phpstan": "*", - "phpunit/phpunit": "<10" + "phpunit/phpunit": "^9.6" }, "suggest": { "ext-iconv": "For best support/performance", @@ -11618,31 +11691,31 @@ "type": "github" } ], - "time": "2024-04-28T00:58:54+00:00" + "time": "2024-08-10T18:44:09+00:00" }, { "name": "zbateson/mb-wrapper", - "version": "1.2.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/zbateson/mb-wrapper.git", - "reference": "09a8b77eb94af3823a9a6623dcc94f8d988da67f" + "reference": "50a14c0c9537f978a61cde9fdc192a0267cc9cff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zbateson/mb-wrapper/zipball/09a8b77eb94af3823a9a6623dcc94f8d988da67f", - "reference": "09a8b77eb94af3823a9a6623dcc94f8d988da67f", + "url": "https://api.github.com/repos/zbateson/mb-wrapper/zipball/50a14c0c9537f978a61cde9fdc192a0267cc9cff", + "reference": "50a14c0c9537f978a61cde9fdc192a0267cc9cff", "shasum": "" }, "require": { - "php": ">=7.1", + "php": ">=8.0", "symfony/polyfill-iconv": "^1.9", "symfony/polyfill-mbstring": "^1.9" }, "require-dev": { "friendsofphp/php-cs-fixer": "*", "phpstan/phpstan": "*", - "phpunit/phpunit": "<10.0" + "phpunit/phpunit": "^9.6|^10.0" }, "suggest": { "ext-iconv": "For best support/performance", @@ -11679,7 +11752,7 @@ ], "support": { "issues": "https://github.com/zbateson/mb-wrapper/issues", - "source": "https://github.com/zbateson/mb-wrapper/tree/1.2.1" + "source": "https://github.com/zbateson/mb-wrapper/tree/2.0.1" }, "funding": [ { @@ -11687,31 +11760,31 @@ "type": "github" } ], - "time": "2024-03-18T04:31:04+00:00" + "time": "2024-12-20T22:05:33+00:00" }, { "name": "zbateson/stream-decorators", - "version": "1.2.1", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/zbateson/stream-decorators.git", - "reference": "783b034024fda8eafa19675fb2552f8654d3a3e9" + "reference": "32a2a62fb0f26313395c996ebd658d33c3f9c4e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zbateson/stream-decorators/zipball/783b034024fda8eafa19675fb2552f8654d3a3e9", - "reference": "783b034024fda8eafa19675fb2552f8654d3a3e9", + "url": "https://api.github.com/repos/zbateson/stream-decorators/zipball/32a2a62fb0f26313395c996ebd658d33c3f9c4e5", + "reference": "32a2a62fb0f26313395c996ebd658d33c3f9c4e5", "shasum": "" }, "require": { - "guzzlehttp/psr7": "^1.9 | ^2.0", - "php": ">=7.2", - "zbateson/mb-wrapper": "^1.0.0" + "guzzlehttp/psr7": "^2.5", + "php": ">=8.0", + "zbateson/mb-wrapper": "^2.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "*", "phpstan/phpstan": "*", - "phpunit/phpunit": "<10.0" + "phpunit/phpunit": "^9.6|^10.0" }, "type": "library", "autoload": { @@ -11742,7 +11815,7 @@ ], "support": { "issues": "https://github.com/zbateson/stream-decorators/issues", - "source": "https://github.com/zbateson/stream-decorators/tree/1.2.1" + "source": "https://github.com/zbateson/stream-decorators/tree/2.1.1" }, "funding": [ { @@ -11750,20 +11823,20 @@ "type": "github" } ], - "time": "2023-05-30T22:51:52+00:00" + "time": "2024-04-29T21:42:39+00:00" }, { "name": "zircote/swagger-php", - "version": "5.0.3", + "version": "5.0.5", "source": { "type": "git", "url": "https://github.com/zircote/swagger-php.git", - "reference": "7708510b17502a416214148edaa8c9958b23b6cd" + "reference": "2eb4005840058d8844a0bcc14403932331331068" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zircote/swagger-php/zipball/7708510b17502a416214148edaa8c9958b23b6cd", - "reference": "7708510b17502a416214148edaa8c9958b23b6cd", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/2eb4005840058d8844a0bcc14403932331331068", + "reference": "2eb4005840058d8844a0bcc14403932331331068", "shasum": "" }, "require": { @@ -11834,38 +11907,41 @@ ], "support": { "issues": "https://github.com/zircote/swagger-php/issues", - "source": "https://github.com/zircote/swagger-php/tree/5.0.3" + "source": "https://github.com/zircote/swagger-php/tree/5.0.5" }, - "time": "2025-01-15T21:02:43+00:00" + "time": "2025-02-24T00:48:00+00:00" } ], "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.14.10", + "version": "v3.15.1", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "56b9bd235e3fe62e250124804009ce5bab97cc63" + "reference": "62b222166a9505926d54fadf7663bb4a26ed9014" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/56b9bd235e3fe62e250124804009ce5bab97cc63", - "reference": "56b9bd235e3fe62e250124804009ce5bab97cc63", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/62b222166a9505926d54fadf7663bb4a26ed9014", + "reference": "62b222166a9505926d54fadf7663bb4a26ed9014", "shasum": "" }, "require": { - "illuminate/routing": "^9|^10|^11", - "illuminate/session": "^9|^10|^11", - "illuminate/support": "^9|^10|^11", - "maximebf/debugbar": "~1.23.0", - "php": "^8.0", + "illuminate/routing": "^9|^10|^11|^12", + "illuminate/session": "^9|^10|^11|^12", + "illuminate/support": "^9|^10|^11|^12", + "php": "^8.1", + "php-debugbar/php-debugbar": "~2.1.1", "symfony/finder": "^6|^7" }, + "conflict": { + "maximebf/debugbar": "*" + }, "require-dev": { "mockery/mockery": "^1.3.3", - "orchestra/testbench-dusk": "^5|^6|^7|^8|^9", - "phpunit/phpunit": "^9.6|^10.5", + "orchestra/testbench-dusk": "^7|^8|^9|^10", + "phpunit/phpunit": "^9.5.10|^10|^11", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", @@ -11879,7 +11955,7 @@ ] }, "branch-alias": { - "dev-master": "3.14-dev" + "dev-master": "3.15-dev" } }, "autoload": { @@ -11904,13 +11980,14 @@ "keywords": [ "debug", "debugbar", + "dev", "laravel", "profiler", "webprofiler" ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.14.10" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.15.1" }, "funding": [ { @@ -11922,7 +11999,7 @@ "type": "github" } ], - "time": "2024-12-23T10:10:42+00:00" + "time": "2025-02-24T10:48:28+00:00" }, { "name": "brianium/paratest", @@ -12019,16 +12096,16 @@ }, { "name": "driftingly/rector-laravel", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/driftingly/rector-laravel.git", - "reference": "973d87d51c1a0d42340758bbddaef15a14155a54" + "reference": "f0e3a9e2c92ff760730d1af34fbdc43f51f3b868" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/973d87d51c1a0d42340758bbddaef15a14155a54", - "reference": "973d87d51c1a0d42340758bbddaef15a14155a54", + "url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/f0e3a9e2c92ff760730d1af34fbdc43f51f3b868", + "reference": "f0e3a9e2c92ff760730d1af34fbdc43f51f3b868", "shasum": "" }, "require": { @@ -12048,9 +12125,9 @@ "description": "Rector upgrades rules for Laravel Framework", "support": { "issues": "https://github.com/driftingly/rector-laravel/issues", - "source": "https://github.com/driftingly/rector-laravel/tree/2.0.1" + "source": "https://github.com/driftingly/rector-laravel/tree/2.0.2" }, - "time": "2025-01-03T16:28:38+00:00" + "time": "2025-01-17T18:07:03+00:00" }, { "name": "fakerphp/faker", @@ -12178,16 +12255,16 @@ }, { "name": "filp/whoops", - "version": "2.16.0", + "version": "2.17.0", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "befcdc0e5dce67252aa6322d82424be928214fa2" + "reference": "075bc0c26631110584175de6523ab3f1652eb28e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/befcdc0e5dce67252aa6322d82424be928214fa2", - "reference": "befcdc0e5dce67252aa6322d82424be928214fa2", + "url": "https://api.github.com/repos/filp/whoops/zipball/075bc0c26631110584175de6523ab3f1652eb28e", + "reference": "075bc0c26631110584175de6523ab3f1652eb28e", "shasum": "" }, "require": { @@ -12237,7 +12314,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.16.0" + "source": "https://github.com/filp/whoops/tree/2.17.0" }, "funding": [ { @@ -12245,7 +12322,7 @@ "type": "github" } ], - "time": "2024-09-25T12:00:00+00:00" + "time": "2025-01-25T12:00:00+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -12300,24 +12377,24 @@ }, { "name": "laravel/dusk", - "version": "v8.2.13", + "version": "v8.3.1", "source": { "type": "git", "url": "https://github.com/laravel/dusk.git", - "reference": "8ddd53a74c2e6f9c3b68cf8189dad44077b585b0" + "reference": "541ca2d2004ae4ed04446b9e712b68180fca158c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/dusk/zipball/8ddd53a74c2e6f9c3b68cf8189dad44077b585b0", - "reference": "8ddd53a74c2e6f9c3b68cf8189dad44077b585b0", + "url": "https://api.github.com/repos/laravel/dusk/zipball/541ca2d2004ae4ed04446b9e712b68180fca158c", + "reference": "541ca2d2004ae4ed04446b9e712b68180fca158c", "shasum": "" }, "require": { "ext-json": "*", "ext-zip": "*", "guzzlehttp/guzzle": "^7.5", - "illuminate/console": "^10.0|^11.0", - "illuminate/support": "^10.0|^11.0", + "illuminate/console": "^10.0|^11.0|^12.0", + "illuminate/support": "^10.0|^11.0|^12.0", "php": "^8.1", "php-webdriver/webdriver": "^1.15.2", "symfony/console": "^6.2|^7.0", @@ -12326,11 +12403,13 @@ "vlucas/phpdotenv": "^5.2" }, "require-dev": { + "laravel/framework": "^10.0|^11.0|^12.0", "mockery/mockery": "^1.6", - "orchestra/testbench": "^8.19|^9.0", + "orchestra/testbench-core": "^8.19|^9.0|^10.0", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.1|^11.0", - "psy/psysh": "^0.11.12|^0.12" + "phpunit/phpunit": "^10.1|^11.0|^12.0.1", + "psy/psysh": "^0.11.12|^0.12", + "symfony/yaml": "^6.2|^7.0" }, "suggest": { "ext-pcntl": "Used to gracefully terminate Dusk when tests are running." @@ -12366,22 +12445,22 @@ ], "support": { "issues": "https://github.com/laravel/dusk/issues", - "source": "https://github.com/laravel/dusk/tree/v8.2.13" + "source": "https://github.com/laravel/dusk/tree/v8.3.1" }, - "time": "2025-01-06T14:52:17+00:00" + "time": "2025-02-12T16:14:51+00:00" }, { "name": "laravel/pint", - "version": "v1.20.0", + "version": "v1.21.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b" + "reference": "531fa0871fbde719c51b12afa3a443b8f4e4b425" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/53072e8ea22213a7ed168a8a15b96fbb8b82d44b", - "reference": "53072e8ea22213a7ed168a8a15b96fbb8b82d44b", + "url": "https://api.github.com/repos/laravel/pint/zipball/531fa0871fbde719c51b12afa3a443b8f4e4b425", + "reference": "531fa0871fbde719c51b12afa3a443b8f4e4b425", "shasum": "" }, "require": { @@ -12389,15 +12468,15 @@ "ext-mbstring": "*", "ext-tokenizer": "*", "ext-xml": "*", - "php": "^8.1.0" + "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.66.0", - "illuminate/view": "^10.48.25", - "larastan/larastan": "^2.9.12", - "laravel-zero/framework": "^10.48.25", + "friendsofphp/php-cs-fixer": "^3.68.5", + "illuminate/view": "^11.42.0", + "larastan/larastan": "^3.0.4", + "laravel-zero/framework": "^11.36.1", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^1.17.0", + "nunomaduro/termwind": "^2.3", "pestphp/pest": "^2.36.0" }, "bin": [ @@ -12434,25 +12513,25 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2025-01-14T16:20:53+00:00" + "time": "2025-02-18T03:18:57+00:00" }, { "name": "laravel/telescope", - "version": "v5.3.0", + "version": "v5.5.0", "source": { "type": "git", "url": "https://github.com/laravel/telescope.git", - "reference": "216fd8d41eb17b49469bea9359b4f0f711b882b3" + "reference": "2594b20b946155ba767002d8af971e33e1095637" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/telescope/zipball/216fd8d41eb17b49469bea9359b4f0f711b882b3", - "reference": "216fd8d41eb17b49469bea9359b4f0f711b882b3", + "url": "https://api.github.com/repos/laravel/telescope/zipball/2594b20b946155ba767002d8af971e33e1095637", + "reference": "2594b20b946155ba767002d8af971e33e1095637", "shasum": "" }, "require": { "ext-json": "*", - "laravel/framework": "^8.37|^9.0|^10.0|^11.0", + "laravel/framework": "^8.37|^9.0|^10.0|^11.0|^12.0", "php": "^8.0", "symfony/console": "^5.3|^6.0|^7.0", "symfony/var-dumper": "^5.0|^6.0|^7.0" @@ -12461,9 +12540,9 @@ "ext-gd": "*", "guzzlehttp/guzzle": "^6.0|^7.0", "laravel/octane": "^1.4|^2.0|dev-develop", - "orchestra/testbench": "^6.40|^7.37|^8.17|^9.0", + "orchestra/testbench": "^6.40|^7.37|^8.17|^9.0|^10.0", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.0|^10.5" + "phpunit/phpunit": "^9.0|^10.5|^11.5" }, "type": "library", "extra": { @@ -12501,77 +12580,9 @@ ], "support": { "issues": "https://github.com/laravel/telescope/issues", - "source": "https://github.com/laravel/telescope/tree/v5.3.0" + "source": "https://github.com/laravel/telescope/tree/v5.5.0" }, - "time": "2024-12-26T21:37:35+00:00" - }, - { - "name": "maximebf/debugbar", - "version": "v1.23.5", - "source": { - "type": "git", - "url": "https://github.com/php-debugbar/php-debugbar.git", - "reference": "eeabd61a1f19ba5dcd5ac4585a477130ee03ce25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/eeabd61a1f19ba5dcd5ac4585a477130ee03ce25", - "reference": "eeabd61a1f19ba5dcd5ac4585a477130ee03ce25", - "shasum": "" - }, - "require": { - "php": "^7.2|^8", - "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^4|^5|^6|^7" - }, - "require-dev": { - "dbrekelmans/bdi": "^1", - "phpunit/phpunit": "^8|^9", - "symfony/panther": "^1|^2.1", - "twig/twig": "^1.38|^2.7|^3.0" - }, - "suggest": { - "kriswallsmith/assetic": "The best way to manage assets", - "monolog/monolog": "Log using Monolog", - "predis/predis": "Redis storage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.23-dev" - } - }, - "autoload": { - "psr-4": { - "DebugBar\\": "src/DebugBar/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Maxime Bouroumeau-Fuseau", - "email": "maxime.bouroumeau@gmail.com", - "homepage": "http://maximebf.com" - }, - { - "name": "Barry vd. Heuvel", - "email": "barryvdh@gmail.com" - } - ], - "description": "Debug bar in the browser for php application", - "homepage": "https://github.com/maximebf/php-debugbar", - "keywords": [ - "debug", - "debugbar" - ], - "support": { - "issues": "https://github.com/php-debugbar/php-debugbar/issues", - "source": "https://github.com/php-debugbar/php-debugbar/tree/v1.23.5" - }, - "time": "2024-12-15T19:20:42+00:00" + "time": "2025-02-11T15:01:27+00:00" }, { "name": "mockery/mockery", @@ -12658,16 +12669,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.12.1", + "version": "1.13.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" + "reference": "024473a478be9df5fdaca2c793f2232fe788e414" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", + "reference": "024473a478be9df5fdaca2c793f2232fe788e414", "shasum": "" }, "require": { @@ -12706,7 +12717,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" }, "funding": [ { @@ -12714,41 +12725,41 @@ "type": "tidelift" } ], - "time": "2024-11-08T17:47:46+00:00" + "time": "2025-02-12T12:17:51+00:00" }, { "name": "nunomaduro/collision", - "version": "v8.5.0", + "version": "v8.6.1", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "f5c101b929c958e849a633283adff296ed5f38f5" + "reference": "86f003c132143d5a2ab214e19933946409e0cae7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f5c101b929c958e849a633283adff296ed5f38f5", - "reference": "f5c101b929c958e849a633283adff296ed5f38f5", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/86f003c132143d5a2ab214e19933946409e0cae7", + "reference": "86f003c132143d5a2ab214e19933946409e0cae7", "shasum": "" }, "require": { "filp/whoops": "^2.16.0", - "nunomaduro/termwind": "^2.1.0", + "nunomaduro/termwind": "^2.3.0", "php": "^8.2.0", - "symfony/console": "^7.1.5" + "symfony/console": "^7.2.1" }, "conflict": { - "laravel/framework": "<11.0.0 || >=12.0.0", - "phpunit/phpunit": "<10.5.1 || >=12.0.0" + "laravel/framework": "<11.39.1 || >=13.0.0", + "phpunit/phpunit": "<11.5.3 || >=12.0.0" }, "require-dev": { - "larastan/larastan": "^2.9.8", - "laravel/framework": "^11.28.0", - "laravel/pint": "^1.18.1", - "laravel/sail": "^1.36.0", - "laravel/sanctum": "^4.0.3", + "larastan/larastan": "^2.9.12", + "laravel/framework": "^11.39.1", + "laravel/pint": "^1.20.0", + "laravel/sail": "^1.40.0", + "laravel/sanctum": "^4.0.7", "laravel/tinker": "^2.10.0", - "orchestra/testbench-core": "^9.5.3", - "pestphp/pest": "^2.36.0 || ^3.4.0", + "orchestra/testbench-core": "^9.9.2", + "pestphp/pest": "^3.7.3", "sebastian/environment": "^6.1.0 || ^7.2.0" }, "type": "library", @@ -12786,6 +12797,7 @@ "cli", "command-line", "console", + "dev", "error", "handling", "laravel", @@ -12811,41 +12823,41 @@ "type": "patreon" } ], - "time": "2024-10-15T16:06:32+00:00" + "time": "2025-01-23T13:41:43+00:00" }, { "name": "pestphp/pest", - "version": "v3.7.1", + "version": "v3.7.4", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "bf3178473dcaa53b0458f21dfdb271306ea62512" + "reference": "4a987d3d5c4e3ba36c76fecbf56113baac2d1b2b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/bf3178473dcaa53b0458f21dfdb271306ea62512", - "reference": "bf3178473dcaa53b0458f21dfdb271306ea62512", + "url": "https://api.github.com/repos/pestphp/pest/zipball/4a987d3d5c4e3ba36c76fecbf56113baac2d1b2b", + "reference": "4a987d3d5c4e3ba36c76fecbf56113baac2d1b2b", "shasum": "" }, "require": { "brianium/paratest": "^7.7.0", - "nunomaduro/collision": "^8.5.0", + "nunomaduro/collision": "^8.6.1", "nunomaduro/termwind": "^2.3.0", "pestphp/pest-plugin": "^3.0.0", "pestphp/pest-plugin-arch": "^3.0.0", "pestphp/pest-plugin-mutate": "^3.0.5", "php": "^8.2.0", - "phpunit/phpunit": "^11.5.1" + "phpunit/phpunit": "^11.5.3" }, "conflict": { "filp/whoops": "<2.16.0", - "phpunit/phpunit": ">11.5.1", + "phpunit/phpunit": ">11.5.3", "sebastian/exporter": "<6.0.0", "webmozart/assert": "<1.11.0" }, "require-dev": { "pestphp/pest-dev-tools": "^3.3.0", - "pestphp/pest-plugin-type-coverage": "^3.2.0", + "pestphp/pest-plugin-type-coverage": "^3.2.3", "symfony/process": "^7.2.0" }, "bin": [ @@ -12911,7 +12923,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v3.7.1" + "source": "https://github.com/pestphp/pest/tree/v3.7.4" }, "funding": [ { @@ -12923,7 +12935,7 @@ "type": "github" } ], - "time": "2024-12-12T11:52:01+00:00" + "time": "2025-01-23T14:03:29+00:00" }, { "name": "pestphp/pest-plugin", @@ -13255,6 +13267,76 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "php-debugbar/php-debugbar", + "version": "v2.1.6", + "source": { + "type": "git", + "url": "https://github.com/php-debugbar/php-debugbar.git", + "reference": "16fa68da5617220594aa5e33fa9de415f94784a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/16fa68da5617220594aa5e33fa9de415f94784a0", + "reference": "16fa68da5617220594aa5e33fa9de415f94784a0", + "shasum": "" + }, + "require": { + "php": "^8", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^4|^5|^6|^7" + }, + "require-dev": { + "dbrekelmans/bdi": "^1", + "phpunit/phpunit": "^8|^9", + "symfony/panther": "^1|^2.1", + "twig/twig": "^1.38|^2.7|^3.0" + }, + "suggest": { + "kriswallsmith/assetic": "The best way to manage assets", + "monolog/monolog": "Log using Monolog", + "predis/predis": "Redis storage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "DebugBar\\": "src/DebugBar/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maxime Bouroumeau-Fuseau", + "email": "maxime.bouroumeau@gmail.com", + "homepage": "http://maximebf.com" + }, + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "Debug bar in the browser for php application", + "homepage": "https://github.com/php-debugbar/php-debugbar", + "keywords": [ + "debug", + "debug bar", + "debugbar", + "dev" + ], + "support": { + "issues": "https://github.com/php-debugbar/php-debugbar/issues", + "source": "https://github.com/php-debugbar/php-debugbar/tree/v2.1.6" + }, + "time": "2025-02-21T17:47:03+00:00" + }, { "name": "php-webdriver/webdriver", "version": "1.15.2", @@ -13323,16 +13405,16 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.1", + "version": "2.1.6", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7" + "reference": "6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7", - "reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c", + "reference": "6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c", "shasum": "" }, "require": { @@ -13377,7 +13459,7 @@ "type": "github" } ], - "time": "2025-01-05T16:43:48+00:00" + "time": "2025-02-19T15:46:42+00:00" }, { "name": "phpunit/php-code-coverage", @@ -13704,16 +13786,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.5.1", + "version": "11.5.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2b94d4f2450b9869fa64a46fd8a6a41997aef56a" + "reference": "30e319e578a7b5da3543073e30002bf82042f701" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2b94d4f2450b9869fa64a46fd8a6a41997aef56a", - "reference": "2b94d4f2450b9869fa64a46fd8a6a41997aef56a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/30e319e578a7b5da3543073e30002bf82042f701", + "reference": "30e319e578a7b5da3543073e30002bf82042f701", "shasum": "" }, "require": { @@ -13727,14 +13809,14 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.2", - "phpunit/php-code-coverage": "^11.0.7", + "phpunit/php-code-coverage": "^11.0.8", "phpunit/php-file-iterator": "^5.1.0", "phpunit/php-invoker": "^5.0.1", "phpunit/php-text-template": "^4.0.1", "phpunit/php-timer": "^7.0.1", "sebastian/cli-parser": "^3.0.2", - "sebastian/code-unit": "^3.0.1", - "sebastian/comparator": "^6.2.1", + "sebastian/code-unit": "^3.0.2", + "sebastian/comparator": "^6.3.0", "sebastian/diff": "^6.0.2", "sebastian/environment": "^7.2.0", "sebastian/exporter": "^6.3.0", @@ -13785,7 +13867,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.1" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.3" }, "funding": [ { @@ -13801,25 +13883,25 @@ "type": "tidelift" } ], - "time": "2024-12-11T10:52:48+00:00" + "time": "2025-01-13T09:36:00+00:00" }, { "name": "rector/rector", - "version": "2.0.6", + "version": "2.0.9", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "fa0cb009dc3df084bf549032ae4080a0481a2036" + "reference": "4393230e478c0006795770fe74c223b5c64ed68c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/fa0cb009dc3df084bf549032ae4080a0481a2036", - "reference": "fa0cb009dc3df084bf549032ae4080a0481a2036", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/4393230e478c0006795770fe74c223b5c64ed68c", + "reference": "4393230e478c0006795770fe74c223b5c64ed68c", "shasum": "" }, "require": { "php": "^7.4|^8.0", - "phpstan/phpstan": "^2.1.1" + "phpstan/phpstan": "^2.1.3" }, "conflict": { "rector/rector-doctrine": "*", @@ -13852,7 +13934,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.0.6" + "source": "https://github.com/rectorphp/rector/tree/2.0.9" }, "funding": [ { @@ -13860,7 +13942,7 @@ "type": "github" } ], - "time": "2025-01-06T10:38:36+00:00" + "time": "2025-02-10T08:14:01+00:00" }, { "name": "sebastian/cli-parser", @@ -14835,30 +14917,30 @@ }, { "name": "spatie/error-solutions", - "version": "1.1.2", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/spatie/error-solutions.git", - "reference": "d239a65235a1eb128dfa0a4e4c4ef032ea11b541" + "reference": "e495d7178ca524f2dd0fe6a1d99a1e608e1c9936" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/error-solutions/zipball/d239a65235a1eb128dfa0a4e4c4ef032ea11b541", - "reference": "d239a65235a1eb128dfa0a4e4c4ef032ea11b541", + "url": "https://api.github.com/repos/spatie/error-solutions/zipball/e495d7178ca524f2dd0fe6a1d99a1e608e1c9936", + "reference": "e495d7178ca524f2dd0fe6a1d99a1e608e1c9936", "shasum": "" }, "require": { "php": "^8.0" }, "require-dev": { - "illuminate/broadcasting": "^10.0|^11.0", - "illuminate/cache": "^10.0|^11.0", - "illuminate/support": "^10.0|^11.0", - "livewire/livewire": "^2.11|^3.3.5", + "illuminate/broadcasting": "^10.0|^11.0|^12.0", + "illuminate/cache": "^10.0|^11.0|^12.0", + "illuminate/support": "^10.0|^11.0|^12.0", + "livewire/livewire": "^2.11|^3.5.20", "openai-php/client": "^0.10.1", - "orchestra/testbench": "^7.0|8.22.3|^9.0", - "pestphp/pest": "^2.20", - "phpstan/phpstan": "^1.11", + "orchestra/testbench": "8.22.3|^9.0|^10.0", + "pestphp/pest": "^2.20|^3.0", + "phpstan/phpstan": "^2.1", "psr/simple-cache": "^3.0", "psr/simple-cache-implementation": "^3.0", "spatie/ray": "^1.28", @@ -14897,7 +14979,7 @@ ], "support": { "issues": "https://github.com/spatie/error-solutions/issues", - "source": "https://github.com/spatie/error-solutions/tree/1.1.2" + "source": "https://github.com/spatie/error-solutions/tree/1.1.3" }, "funding": [ { @@ -14905,24 +14987,24 @@ "type": "github" } ], - "time": "2024-12-11T09:51:56+00:00" + "time": "2025-02-14T12:29:50+00:00" }, { "name": "spatie/flare-client-php", - "version": "1.10.0", + "version": "1.10.1", "source": { "type": "git", "url": "https://github.com/spatie/flare-client-php.git", - "reference": "140a42b2c5d59ac4ecf8f5b493386a4f2eb28272" + "reference": "bf1716eb98bd689451b071548ae9e70738dce62f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/140a42b2c5d59ac4ecf8f5b493386a4f2eb28272", - "reference": "140a42b2c5d59ac4ecf8f5b493386a4f2eb28272", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/bf1716eb98bd689451b071548ae9e70738dce62f", + "reference": "bf1716eb98bd689451b071548ae9e70738dce62f", "shasum": "" }, "require": { - "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0", + "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0|^12.0", "php": "^8.0", "spatie/backtrace": "^1.6.1", "symfony/http-foundation": "^5.2|^6.0|^7.0", @@ -14966,7 +15048,7 @@ ], "support": { "issues": "https://github.com/spatie/flare-client-php/issues", - "source": "https://github.com/spatie/flare-client-php/tree/1.10.0" + "source": "https://github.com/spatie/flare-client-php/tree/1.10.1" }, "funding": [ { @@ -14974,20 +15056,20 @@ "type": "github" } ], - "time": "2024-12-02T14:30:06+00:00" + "time": "2025-02-14T13:42:06+00:00" }, { "name": "spatie/ignition", - "version": "1.15.0", + "version": "1.15.1", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2" + "reference": "31f314153020aee5af3537e507fef892ffbf8c85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/e3a68e137371e1eb9edc7f78ffa733f3b98991d2", - "reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2", + "url": "https://api.github.com/repos/spatie/ignition/zipball/31f314153020aee5af3537e507fef892ffbf8c85", + "reference": "31f314153020aee5af3537e507fef892ffbf8c85", "shasum": "" }, "require": { @@ -15000,7 +15082,7 @@ "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "require-dev": { - "illuminate/cache": "^9.52|^10.0|^11.0", + "illuminate/cache": "^9.52|^10.0|^11.0|^12.0", "mockery/mockery": "^1.4", "pestphp/pest": "^1.20|^2.0", "phpstan/extension-installer": "^1.1", @@ -15057,27 +15139,27 @@ "type": "github" } ], - "time": "2024-06-12T14:55:22+00:00" + "time": "2025-02-21T14:31:39+00:00" }, { "name": "spatie/laravel-ignition", - "version": "2.9.0", + "version": "2.9.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "62042df15314b829d0f26e02108f559018e2aad0" + "reference": "1baee07216d6748ebd3a65ba97381b051838707a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/62042df15314b829d0f26e02108f559018e2aad0", - "reference": "62042df15314b829d0f26e02108f559018e2aad0", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/1baee07216d6748ebd3a65ba97381b051838707a", + "reference": "1baee07216d6748ebd3a65ba97381b051838707a", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "illuminate/support": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0|^12.0", "php": "^8.1", "spatie/ignition": "^1.15", "symfony/console": "^6.2.3|^7.0", @@ -15086,12 +15168,12 @@ "require-dev": { "livewire/livewire": "^2.11|^3.3.5", "mockery/mockery": "^1.5.1", - "openai-php/client": "^0.8.1", - "orchestra/testbench": "8.22.3|^9.0", - "pestphp/pest": "^2.34", + "openai-php/client": "^0.8.1|^0.10", + "orchestra/testbench": "8.22.3|^9.0|^10.0", + "pestphp/pest": "^2.34|^3.7", "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan-deprecation-rules": "^1.1.1", - "phpstan/phpstan-phpunit": "^1.3.16", + "phpstan/phpstan-deprecation-rules": "^1.1.1|^2.0", + "phpstan/phpstan-phpunit": "^1.3.16|^2.0", "vlucas/phpdotenv": "^5.5" }, "suggest": { @@ -15148,7 +15230,7 @@ "type": "github" } ], - "time": "2024-12-02T08:43:31+00:00" + "time": "2025-02-20T13:13:55+00:00" }, { "name": "staabm/side-effects-detector", @@ -15204,16 +15286,16 @@ }, { "name": "symfony/http-client", - "version": "v7.2.2", + "version": "v7.2.3", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "339ba21476eb184290361542f732ad12c97591ec" + "reference": "7ce6078c79a4a7afff931c413d2959d3bffbfb8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/339ba21476eb184290361542f732ad12c97591ec", - "reference": "339ba21476eb184290361542f732ad12c97591ec", + "url": "https://api.github.com/repos/symfony/http-client/zipball/7ce6078c79a4a7afff931c413d2959d3bffbfb8d", + "reference": "7ce6078c79a4a7afff931c413d2959d3bffbfb8d", "shasum": "" }, "require": { @@ -15279,7 +15361,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.2" + "source": "https://github.com/symfony/http-client/tree/v7.2.3" }, "funding": [ { @@ -15295,7 +15377,7 @@ "type": "tidelift" } ], - "time": "2024-12-30T18:35:15+00:00" + "time": "2025-01-28T15:51:35+00:00" }, { "name": "symfony/http-client-contracts", diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 2e46438bd..23a65cca6 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -61,7 +61,7 @@ services: retries: 10 timeout: 2s soketi: - image: 'ghcr.io/coollabsio/coolify-realtime:1.0.5' + image: 'ghcr.io/coollabsio/coolify-realtime:1.0.6' ports: - "${SOKETI_PORT:-6001}:6001" - "6002:6002" diff --git a/docker-compose.windows.yml b/docker-compose.windows.yml index 1e2601b34..519309e39 100644 --- a/docker-compose.windows.yml +++ b/docker-compose.windows.yml @@ -103,7 +103,7 @@ services: retries: 10 timeout: 2s soketi: - image: 'ghcr.io/coollabsio/coolify-realtime:1.0.4' + image: 'ghcr.io/coollabsio/coolify-realtime:1.0.6' pull_policy: always container_name: coolify-realtime restart: always diff --git a/docker/coolify-helper/Dockerfile b/docker/coolify-helper/Dockerfile index 7486acdcd..657610014 100644 --- a/docker/coolify-helper/Dockerfile +++ b/docker/coolify-helper/Dockerfile @@ -1,20 +1,18 @@ # Versions - - # https://hub.docker.com/_/alpine ARG BASE_IMAGE=alpine:3.21 # https://download.docker.com/linux/static/stable/ -ARG DOCKER_VERSION=27.4.1 +ARG DOCKER_VERSION=28.0.0 # https://github.com/docker/compose/releases -ARG DOCKER_COMPOSE_VERSION=2.32.2 +ARG DOCKER_COMPOSE_VERSION=2.33.1 # https://github.com/docker/buildx/releases -ARG DOCKER_BUILDX_VERSION=0.19.3 +ARG DOCKER_BUILDX_VERSION=0.21.1 # https://github.com/buildpacks/pack/releases -ARG PACK_VERSION=0.36.2 +ARG PACK_VERSION=0.36.4 # https://github.com/railwayapp/nixpacks/releases -ARG NIXPACKS_VERSION=1.29.0 +ARG NIXPACKS_VERSION=1.33.0 # https://github.com/minio/mc/releases -ARG MINIO_VERSION=RELEASE.2024-11-21T17-21-54Z +ARG MINIO_VERSION=RELEASE.2025-02-15T10-36-16Z FROM minio/mc:${MINIO_VERSION} AS minio-client diff --git a/docker/coolify-realtime/Dockerfile b/docker/coolify-realtime/Dockerfile index be72bd836..3a53da490 100644 --- a/docker/coolify-realtime/Dockerfile +++ b/docker/coolify-realtime/Dockerfile @@ -2,7 +2,7 @@ # https://github.com/soketi/soketi/releases ARG SOKETI_VERSION=1.6-16-alpine # https://github.com/cloudflare/cloudflared/releases -ARG CLOUDFLARED_VERSION=2025.1.0 +ARG CLOUDFLARED_VERSION=2025.2.0 FROM quay.io/soketi/soketi:${SOKETI_VERSION} diff --git a/docker/coolify-realtime/package-lock.json b/docker/coolify-realtime/package-lock.json index 37f0c73eb..aea3952c0 100644 --- a/docker/coolify-realtime/package-lock.json +++ b/docker/coolify-realtime/package-lock.json @@ -11,7 +11,7 @@ "cookie": "1.0.2", "dotenv": "16.4.7", "node-pty": "1.0.0", - "ws": "8.18.0" + "ws": "8.18.1" } }, "node_modules/@xterm/addon-fit": { @@ -46,6 +46,19 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -88,6 +101,65 @@ "url": "https://dotenvx.com" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/follow-redirects": { "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", @@ -109,19 +181,126 @@ } }, "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -144,9 +323,9 @@ } }, "node_modules/nan": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", - "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.1.tgz", + "integrity": "sha512-pfRR4ZcNTSm2ZFHaztuvbICf+hyiG6ecA06SfAxoPmuHjvMu0KUIae7Y8GyVkbBqeEIidsmXeYooWIX9+qjfRQ==", "license": "MIT" }, "node_modules/node-pty": { @@ -166,9 +345,9 @@ "license": "MIT" }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/docker/coolify-realtime/package.json b/docker/coolify-realtime/package.json index fbf2fcd34..0a9b80cb5 100644 --- a/docker/coolify-realtime/package.json +++ b/docker/coolify-realtime/package.json @@ -8,6 +8,6 @@ "axios": "1.7.9", "dotenv": "16.4.7", "node-pty": "1.0.0", - "ws": "8.18.0" + "ws": "8.18.1" } } diff --git a/docker/development/Dockerfile b/docker/development/Dockerfile index 95933c0c2..094600455 100644 --- a/docker/development/Dockerfile +++ b/docker/development/Dockerfile @@ -2,9 +2,9 @@ # https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine ARG SERVERSIDEUP_PHP_VERSION=8.4-fpm-nginx-alpine # https://github.com/minio/mc/releases -ARG MINIO_VERSION=RELEASE.2024-11-21T17-21-54Z +ARG MINIO_VERSION=RELEASE.2025-02-15T10-36-16Z # https://github.com/cloudflare/cloudflared/releases -ARG CLOUDFLARED_VERSION=2025.1.0 +ARG CLOUDFLARED_VERSION=2025.2.0 # https://www.postgresql.org/support/versioning/ ARG POSTGRES_VERSION=15 diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile index 3032d3ef7..75d9b44eb 100644 --- a/docker/production/Dockerfile +++ b/docker/production/Dockerfile @@ -2,9 +2,9 @@ # https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine ARG SERVERSIDEUP_PHP_VERSION=8.4-fpm-nginx-alpine # https://github.com/minio/mc/releases -ARG MINIO_VERSION=RELEASE.2024-11-21T17-21-54Z +ARG MINIO_VERSION= RELEASE.2025-02-15T10-36-16Z # https://github.com/cloudflare/cloudflared/releases -ARG CLOUDFLARED_VERSION=2025.1.0 +ARG CLOUDFLARED_VERSION=2025.2.0 # https://www.postgresql.org/support/versioning/ ARG POSTGRES_VERSION=15 diff --git a/docker/testing-host/Dockerfile b/docker/testing-host/Dockerfile index 4b424279d..c6f5d800e 100644 --- a/docker/testing-host/Dockerfile +++ b/docker/testing-host/Dockerfile @@ -1,10 +1,10 @@ # Versions # https://download.docker.com/linux/static/stable/ -ARG DOCKER_VERSION=27.4.1 +ARG DOCKER_VERSION=28.0.0 # https://github.com/docker/compose/releases -ARG DOCKER_COMPOSE_VERSION=2.32.2 +ARG DOCKER_COMPOSE_VERSION=2.33.1 # https://github.com/docker/buildx/releases -ARG DOCKER_BUILDX_VERSION=0.19.3 +ARG DOCKER_BUILDX_VERSION=0.21.1 FROM debian:12-slim diff --git a/other/nightly/versions.json b/other/nightly/versions.json index f8214d091..fa0e454d7 100644 --- a/other/nightly/versions.json +++ b/other/nightly/versions.json @@ -7,10 +7,10 @@ "version": "4.0.0-beta.383" }, "helper": { - "version": "1.0.4" + "version": "1.0.7" }, "realtime": { - "version": "1.0.5" + "version": "1.0.6" }, "sentinel": { "version": "0.0.15" diff --git a/package-lock.json b/package-lock.json index fed13e28a..0fb1d210a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,19 +10,19 @@ "@tailwindcss/typography": "0.5.16", "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", - "ioredis": "5.4.2" + "ioredis": "5.5.0" }, "devDependencies": { "@vitejs/plugin-vue": "5.2.1", "autoprefixer": "10.4.20", "axios": "1.7.9", - "laravel-echo": "1.17.1", - "laravel-vite-plugin": "1.1.1", - "postcss": "8.4.49", - "pusher-js": "8.4.0-rc2", + "laravel-echo": "2.0.2", + "laravel-vite-plugin": "^1.2.0", + "postcss": "8.5.3", + "pusher-js": "8.4.0", "tailwind-scrollbar": "^3.1.0", "tailwindcss": "3.4.17", - "vite": "6.0.11", + "vite": "^6.1.1", "vue": "3.5.13" } }, @@ -535,9 +535,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -586,6 +586,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -598,6 +599,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -606,6 +608,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -625,9 +628,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.25.0.tgz", - "integrity": "sha512-CC/ZqFZwlAIbU1wUPisHyV/XRc5RydFrNLtgl3dGYskdwPZdt4HERtKm50a/+DtTlKeCq9IXFEWR+P6blwjqBA==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz", + "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==", "cpu": [ "arm" ], @@ -639,9 +642,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.25.0.tgz", - "integrity": "sha512-/Y76tmLGUJqVBXXCfVS8Q8FJqYGhgH4wl4qTA24E9v/IJM0XvJCGQVSW1QZ4J+VURO9h8YCa28sTFacZXwK7Rg==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz", + "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==", "cpu": [ "arm64" ], @@ -653,9 +656,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.25.0.tgz", - "integrity": "sha512-YVT6L3UrKTlC0FpCZd0MGA7NVdp7YNaEqkENbWQ7AOVOqd/7VzyHpgIpc1mIaxRAo1ZsJRH45fq8j4N63I/vvg==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz", + "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==", "cpu": [ "arm64" ], @@ -667,9 +670,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.25.0.tgz", - "integrity": "sha512-ZRL+gexs3+ZmmWmGKEU43Bdn67kWnMeWXLFhcVv5Un8FQcx38yulHBA7XR2+KQdYIOtD0yZDWBCudmfj6lQJoA==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz", + "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==", "cpu": [ "x64" ], @@ -681,9 +684,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.25.0.tgz", - "integrity": "sha512-xpEIXhiP27EAylEpreCozozsxWQ2TJbOLSivGfXhU4G1TBVEYtUPi2pOZBnvGXHyOdLAUUhPnJzH3ah5cqF01g==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz", + "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==", "cpu": [ "arm64" ], @@ -695,9 +698,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.25.0.tgz", - "integrity": "sha512-sC5FsmZGlJv5dOcURrsnIK7ngc3Kirnx3as2XU9uER+zjfyqIjdcMVgzy4cOawhsssqzoAX19qmxgJ8a14Qrqw==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz", + "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==", "cpu": [ "x64" ], @@ -709,9 +712,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.25.0.tgz", - "integrity": "sha512-uD/dbLSs1BEPzg564TpRAQ/YvTnCds2XxyOndAO8nJhaQcqQGFgv/DAVko/ZHap3boCvxnzYMa3mTkV/B/3SWA==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz", + "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==", "cpu": [ "arm" ], @@ -723,9 +726,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.25.0.tgz", - "integrity": "sha512-ZVt/XkrDlQWegDWrwyC3l0OfAF7yeJUF4fq5RMS07YM72BlSfn2fQQ6lPyBNjt+YbczMguPiJoCfaQC2dnflpQ==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz", + "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==", "cpu": [ "arm" ], @@ -737,9 +740,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.25.0.tgz", - "integrity": "sha512-qboZ+T0gHAW2kkSDPHxu7quaFaaBlynODXpBVnPxUgvWYaE84xgCKAPEYE+fSMd3Zv5PyFZR+L0tCdYCMAtG0A==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz", + "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==", "cpu": [ "arm64" ], @@ -751,9 +754,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.25.0.tgz", - "integrity": "sha512-ndWTSEmAaKr88dBuogGH2NZaxe7u2rDoArsejNslugHZ+r44NfWiwjzizVS1nUOHo+n1Z6qV3X60rqE/HlISgw==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz", + "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==", "cpu": [ "arm64" ], @@ -764,10 +767,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz", + "integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.25.0.tgz", - "integrity": "sha512-BVSQvVa2v5hKwJSy6X7W1fjDex6yZnNKy3Kx1JGimccHft6HV0THTwNtC2zawtNXKUu+S5CjXslilYdKBAadzA==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz", + "integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==", "cpu": [ "ppc64" ], @@ -779,9 +796,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.25.0.tgz", - "integrity": "sha512-G4hTREQrIdeV0PE2JruzI+vXdRnaK1pg64hemHq2v5fhv8C7WjVaeXc9P5i4Q5UC06d/L+zA0mszYIKl+wY8oA==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz", + "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==", "cpu": [ "riscv64" ], @@ -793,9 +810,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.25.0.tgz", - "integrity": "sha512-9T/w0kQ+upxdkFL9zPVB6zy9vWW1deA3g8IauJxojN4bnz5FwSsUAD034KpXIVX5j5p/rn6XqumBMxfRkcHapQ==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz", + "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==", "cpu": [ "s390x" ], @@ -807,9 +824,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.25.0.tgz", - "integrity": "sha512-ThcnU0EcMDn+J4B9LD++OgBYxZusuA7iemIIiz5yzEcFg04VZFzdFjuwPdlURmYPZw+fgVrFzj4CA64jSTG4Ig==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz", + "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==", "cpu": [ "x64" ], @@ -821,9 +838,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.25.0.tgz", - "integrity": "sha512-zx71aY2oQxGxAT1JShfhNG79PnjYhMC6voAjzpu/xmMjDnKNf6Nl/xv7YaB/9SIa9jDYf8RBPWEnjcdlhlv1rQ==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz", + "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==", "cpu": [ "x64" ], @@ -835,9 +852,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.25.0.tgz", - "integrity": "sha512-JT8tcjNocMs4CylWY/CxVLnv8e1lE7ff1fi6kbGocWwxDq9pj30IJ28Peb+Y8yiPNSF28oad42ApJB8oUkwGww==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz", + "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==", "cpu": [ "arm64" ], @@ -849,9 +866,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.25.0.tgz", - "integrity": "sha512-dRLjLsO3dNOfSN6tjyVlG+Msm4IiZnGkuZ7G5NmpzwF9oOc582FZG05+UdfTbz5Jd4buK/wMb6UeHFhG18+OEg==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz", + "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==", "cpu": [ "ia32" ], @@ -863,9 +880,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.25.0.tgz", - "integrity": "sha512-/RqrIFtLB926frMhZD0a5oDa4eFIbyNEwLLloMTEjmqfwZWXywwVVOVmwTsuyhC9HKkVEZcOOi+KV4U9wmOdlg==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz", + "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==", "cpu": [ "x64" ], @@ -1155,7 +1172,8 @@ "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" }, "node_modules/asynckit": { "version": "0.4.0", @@ -1248,9 +1266,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, "funding": [ { @@ -1268,9 +1286,9 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { @@ -1284,14 +1302,15 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001680", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", - "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", + "version": "1.0.30001700", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz", + "integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==", "dev": true, "funding": [ { @@ -1459,12 +1478,14 @@ "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "license": "Apache-2.0" }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" }, "node_modules/eastasianwidth": { "version": "0.2.0", @@ -1473,9 +1494,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.55", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.55.tgz", - "integrity": "sha512-6maZ2ASDOTBtjt9FhqYPRnbvKU5tjG0IN9SztUOWYw2AzNDNpKJYLJmlK0/En4Hs/aiWnB+JZ+gW19PIGszgKg==", + "version": "1.5.103", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.103.tgz", + "integrity": "sha512-P6+XzIkfndgsrjROJWfSvVEgNHtPgbhVyTkwLjUM2HU/h7pZRORgaTlHqfAikqxKmdJMLW8fftrdGWbd/Ds0FA==", "dev": true, "license": "ISC" }, @@ -1557,15 +1578,16 @@ "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -1575,6 +1597,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1583,9 +1606,10 @@ } }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", + "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -1656,6 +1680,7 @@ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, + "license": "MIT", "engines": { "node": "*" }, @@ -1710,6 +1735,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -1729,18 +1755,10 @@ "node": ">= 0.4" } }, - "node_modules/immutable": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", - "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/ioredis": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.2.tgz", - "integrity": "sha512-0SZXGNGZ+WzISQ67QDyZ2x0+wVxjjUndtD8oSeik/4ajifeiRufed8fCb8QW8VMyi4MXcS+UO1k/0NGhvq1PAg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.5.0.tgz", + "integrity": "sha512-7CutT89g23FfSa8MDoIFs2GYYa0PaNiW/OrT+nRyjRXHDZd17HmIgy+reOQ/yhh72NznNjGuS8kbCAcA4Ro4mw==", "license": "MIT", "dependencies": { "@ioredis/commands": "^1.1.1", @@ -1773,9 +1791,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -1854,19 +1872,19 @@ } }, "node_modules/laravel-echo": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-1.17.1.tgz", - "integrity": "sha512-ORWc4vDfnBj/Oe5ThZ5kYyGItRjLDqAQUyhD/7UhehUOqc+s5x9HEBjtMVludNMP6VuXw6t7Uxt8bp63kaTofg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-2.0.2.tgz", + "integrity": "sha512-Ciai6hA7r35MFqNRb8G034cvm9WiveSTFQQKRGJhWtZGbng7C8BBa5QvqDxk/Mw5GeJ+q19jrEwQhf7r1b1lcg==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=20" } }, "node_modules/laravel-vite-plugin": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.1.1.tgz", - "integrity": "sha512-HMZXpoSs1OR+7Lw1+g4Iy/s3HF3Ldl8KxxYT2Ot8pEB4XB/QRuZeWgDYJdu552UN03YRSRNK84CLC9NzYRtncA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.2.0.tgz", + "integrity": "sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1946,6 +1964,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -1954,6 +1973,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -2050,9 +2070,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, "license": "MIT" }, @@ -2069,6 +2089,7 @@ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2086,6 +2107,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", "engines": { "node": ">= 6" } @@ -2108,7 +2130,8 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", @@ -2147,6 +2170,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2161,9 +2185,9 @@ } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -2180,7 +2204,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -2192,6 +2216,7 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -2208,6 +2233,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" }, @@ -2298,7 +2324,8 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" }, "node_modules/proxy-from-env": { "version": "1.1.0", @@ -2307,10 +2334,11 @@ "dev": true }, "node_modules/pusher-js": { - "version": "8.4.0-rc2", - "resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-8.4.0-rc2.tgz", - "integrity": "sha512-d87GjOEEl9QgO5BWmViSqW0LOzPvybvX6WA9zLUstNdB57jVJuR27zHkRnrav2a3+zAMlHbP2Og8wug+rG8T+g==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-8.4.0.tgz", + "integrity": "sha512-wp3HqIIUc1GRyu1XrP6m2dgyE9MoCsXVsWNlohj0rjSkLf+a0jLvEyVubdg58oMk7bhjBWnFClgp8jfAa6Ak4Q==", "dev": true, + "license": "MIT", "dependencies": { "tweetnacl": "^1.0.3" } @@ -2332,12 +2360,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "license": "MIT", "dependencies": { "pify": "^2.3.0" } @@ -2373,18 +2403,21 @@ } }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2393,15 +2426,16 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, "node_modules/rollup": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.25.0.tgz", - "integrity": "sha512-uVbClXmR6wvx5R1M3Od4utyLUxrmOcEm3pAtMphn73Apq19PDtHpgZoEvqH2YnnaNUuvKmg2DgRd2Sqv+odyqg==", + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz", + "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2415,24 +2449,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.25.0", - "@rollup/rollup-android-arm64": "4.25.0", - "@rollup/rollup-darwin-arm64": "4.25.0", - "@rollup/rollup-darwin-x64": "4.25.0", - "@rollup/rollup-freebsd-arm64": "4.25.0", - "@rollup/rollup-freebsd-x64": "4.25.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.25.0", - "@rollup/rollup-linux-arm-musleabihf": "4.25.0", - "@rollup/rollup-linux-arm64-gnu": "4.25.0", - "@rollup/rollup-linux-arm64-musl": "4.25.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.25.0", - "@rollup/rollup-linux-riscv64-gnu": "4.25.0", - "@rollup/rollup-linux-s390x-gnu": "4.25.0", - "@rollup/rollup-linux-x64-gnu": "4.25.0", - "@rollup/rollup-linux-x64-musl": "4.25.0", - "@rollup/rollup-win32-arm64-msvc": "4.25.0", - "@rollup/rollup-win32-ia32-msvc": "4.25.0", - "@rollup/rollup-win32-x64-msvc": "4.25.0", + "@rollup/rollup-android-arm-eabi": "4.34.8", + "@rollup/rollup-android-arm64": "4.34.8", + "@rollup/rollup-darwin-arm64": "4.34.8", + "@rollup/rollup-darwin-x64": "4.34.8", + "@rollup/rollup-freebsd-arm64": "4.34.8", + "@rollup/rollup-freebsd-x64": "4.34.8", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", + "@rollup/rollup-linux-arm-musleabihf": "4.34.8", + "@rollup/rollup-linux-arm64-gnu": "4.34.8", + "@rollup/rollup-linux-arm64-musl": "4.34.8", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", + "@rollup/rollup-linux-riscv64-gnu": "4.34.8", + "@rollup/rollup-linux-s390x-gnu": "4.34.8", + "@rollup/rollup-linux-x64-gnu": "4.34.8", + "@rollup/rollup-linux-x64-musl": "4.34.8", + "@rollup/rollup-win32-arm64-msvc": "4.34.8", + "@rollup/rollup-win32-ia32-msvc": "4.34.8", + "@rollup/rollup-win32-x64-msvc": "4.34.8", "fsevents": "~2.3.2" } }, @@ -2454,29 +2489,11 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, - "node_modules/sass": { - "version": "1.62.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz", - "integrity": "sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -2646,6 +2663,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2748,9 +2766,9 @@ "dev": true }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "dev": true, "funding": [ { @@ -2769,7 +2787,7 @@ "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -2784,15 +2802,15 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/vite": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", - "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.1.tgz", + "integrity": "sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" + "postcss": "^8.5.2", + "rollup": "^4.30.1" }, "bin": { "vite": "bin/vite.js" @@ -2856,10 +2874,11 @@ } }, "node_modules/vite-plugin-full-reload": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.1.0.tgz", - "integrity": "sha512-3cObNDzX6DdfhD9E7kf6w2mNunFpD7drxyNgHLw+XwIYAgb+Xt16SEXo0Up4VH+TMf3n+DSVJZtW2POBGcBYAA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.2.0.tgz", + "integrity": "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA==", "dev": true, + "license": "MIT", "dependencies": { "picocolors": "^1.0.0", "picomatch": "^2.3.1" diff --git a/package.json b/package.json index 4e2cf6700..0060a1199 100644 --- a/package.json +++ b/package.json @@ -10,13 +10,13 @@ "@vitejs/plugin-vue": "5.2.1", "autoprefixer": "10.4.20", "axios": "1.7.9", - "laravel-echo": "1.17.1", - "laravel-vite-plugin": "1.1.1", - "postcss": "8.4.49", - "pusher-js": "8.4.0-rc2", + "laravel-echo": "2.0.2", + "laravel-vite-plugin": "^1.2.0", + "postcss": "8.5.3", + "pusher-js": "8.4.0", "tailwind-scrollbar": "^3.1.0", "tailwindcss": "3.4.17", - "vite": "6.0.11", + "vite": "^6.1.1", "vue": "3.5.13" }, "dependencies": { @@ -24,6 +24,6 @@ "@tailwindcss/typography": "0.5.16", "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", - "ioredis": "5.4.2" + "ioredis": "5.5.0" } } diff --git a/versions.json b/versions.json index 6073acfad..eb8e5c923 100644 --- a/versions.json +++ b/versions.json @@ -7,10 +7,10 @@ "version": "4.0.0-beta.397" }, "helper": { - "version": "1.0.6" + "version": "1.0.7" }, "realtime": { - "version": "1.0.5" + "version": "1.0.6" }, "sentinel": { "version": "0.0.15" From c3c1bbc120368abb73505cc2e60f5f272ed1cbe3 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:12:48 +0100 Subject: [PATCH 27/99] fix(core): production dockerfile --- docker/production/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile index 75d9b44eb..86fae4a13 100644 --- a/docker/production/Dockerfile +++ b/docker/production/Dockerfile @@ -2,7 +2,7 @@ # https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine ARG SERVERSIDEUP_PHP_VERSION=8.4-fpm-nginx-alpine # https://github.com/minio/mc/releases -ARG MINIO_VERSION= RELEASE.2025-02-15T10-36-16Z +ARG MINIO_VERSION=RELEASE.2025-02-15T10-36-16Z # https://github.com/cloudflare/cloudflared/releases ARG CLOUDFLARED_VERSION=2025.2.0 # https://www.postgresql.org/support/versioning/ From 044abb0d6f6995cc38f6cdef40aa42dcfb5dcfad Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:36:54 +0100 Subject: [PATCH 28/99] chore: bump helper and realtime version --- config/constants.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/constants.php b/config/constants.php index 24cc25768..ffd870c7d 100644 --- a/config/constants.php +++ b/config/constants.php @@ -3,8 +3,8 @@ return [ 'coolify' => [ 'version' => '4.0.0-beta.396', - 'helper_version' => '1.0.6', - 'realtime_version' => '1.0.5', + 'helper_version' => '1.0.7', + 'realtime_version' => '1.0.6', 'self_hosted' => env('SELF_HOSTED', true), 'autoupdate' => env('AUTOUPDATE'), 'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'), From 2df6b344d47680da187bba455ade42f4a22f1c5d Mon Sep 17 00:00:00 2001 From: Manish Gupta <59428681+mguptahub@users.noreply.github.com> Date: Tue, 25 Feb 2025 14:32:13 +0530 Subject: [PATCH 29/99] updated plane version to v0.25.0 --- templates/compose/plane.yaml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/templates/compose/plane.yaml b/templates/compose/plane.yaml index d1fcf78fa..c90e15a1a 100644 --- a/templates/compose/plane.yaml +++ b/templates/compose/plane.yaml @@ -5,7 +5,7 @@ x-app-env: &app-env environment: - - APP_RELEASE=${APP_RELEASE:-v0.24.1} + - APP_RELEASE=${APP_RELEASE:-v0.25.0} - WEB_URL=${SERVICE_FQDN_PLANE} - DEBUG=${DEBUG:-0} - CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGIN:-http://localhost} @@ -55,7 +55,7 @@ services: - SERVICE_FQDN_PLANE - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880} - BUCKET_NAME=${BUCKET_NAME:-uploads} - image: makeplane/plane-proxy:${APP_RELEASE:-v0.24.1} + image: makeplane/plane-proxy:${APP_RELEASE:-v0.25.0} depends_on: - web - api @@ -67,7 +67,7 @@ services: retries: 15 web: - image: makeplane/plane-frontend:${APP_RELEASE:-v0.24.1} + image: makeplane/plane-frontend:${APP_RELEASE:-v0.25.0} command: node web/server.js web depends_on: - api @@ -78,7 +78,7 @@ services: timeout: 10s retries: 15 space: - image: makeplane/plane-space:${APP_RELEASE:-v0.24.1} + image: makeplane/plane-space:${APP_RELEASE:-v0.25.0} command: node space/server.js space depends_on: - api @@ -91,7 +91,7 @@ services: retries: 15 admin: - image: makeplane/plane-admin:${APP_RELEASE:-v0.24.1} + image: makeplane/plane-admin:${APP_RELEASE:-v0.25.0} command: node admin/server.js admin depends_on: - api @@ -104,7 +104,7 @@ services: live: <<: *app-env - image: makeplane/plane-live:${APP_RELEASE:-v0.24.1} + image: makeplane/plane-live:${APP_RELEASE:-v0.25.0} command: node live/dist/server.js live depends_on: - api @@ -117,7 +117,7 @@ services: api: <<: *app-env - image: makeplane/plane-backend:${APP_RELEASE:-v0.24.1} + image: makeplane/plane-backend:${APP_RELEASE:-v0.25.0} command: ./bin/docker-entrypoint-api.sh volumes: - logs_api:/code/plane/logs @@ -132,7 +132,7 @@ services: worker: <<: *app-env - image: makeplane/plane-backend:${APP_RELEASE:-v0.24.1} + image: makeplane/plane-backend:${APP_RELEASE:-v0.25.0} command: ./bin/docker-entrypoint-worker.sh volumes: - logs_worker:/code/plane/logs @@ -148,7 +148,7 @@ services: beat-worker: <<: *app-env - image: makeplane/plane-backend:${APP_RELEASE:-v0.24.1} + image: makeplane/plane-backend:${APP_RELEASE:-v0.25.0} command: ./bin/docker-entrypoint-beat.sh volumes: - logs_beat-worker:/code/plane/logs @@ -164,7 +164,7 @@ services: migrator: <<: *app-env - image: makeplane/plane-backend:${APP_RELEASE:-v0.24.1} + image: makeplane/plane-backend:${APP_RELEASE:-v0.25.0} restart: "no" command: ./bin/docker-entrypoint-migrator.sh volumes: From 0798eb714da69f9c66d0ce35899af233cc18ea35 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 26 Feb 2025 08:22:45 +0100 Subject: [PATCH 30/99] fix(ui): Update storage configuration guidance link --- .../views/livewire/project/service/configuration.blade.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/views/livewire/project/service/configuration.blade.php b/resources/views/livewire/project/service/configuration.blade.php index 81c628998..3e6bcd1c6 100644 --- a/resources/views/livewire/project/service/configuration.blade.php +++ b/resources/views/livewire/project/service/configuration.blade.php @@ -176,7 +176,9 @@
Persistent storage to preserve data between deployments.
If you would like to add a volume, you must add it to - your compose file (Service Stack tab).
+ your compose file (General tab).
@foreach ($applications as $application) From fd09b5b30f0cac51dbe0d0256024c038deccc87c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 26 Feb 2025 08:22:55 +0100 Subject: [PATCH 31/99] refactor(ui): Simplify file storage modal confirmations --- .../project/service/file-storage.blade.php | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/resources/views/livewire/project/service/file-storage.blade.php b/resources/views/livewire/project/service/file-storage.blade.php index b37137923..550b43c20 100644 --- a/resources/views/livewire/project/service/file-storage.blade.php +++ b/resources/views/livewire/project/service/file-storage.blade.php @@ -21,15 +21,6 @@ ]" confirmationText="{{ $fs_path }}" confirmationLabel="Please confirm the execution of the actions by entering the Filepath below" shortConfirmationLabel="Filepath" :confirmWithPassword="false" step2ButtonText="Convert to file" /> - @else - - @endif - @if ($fileStorage->is_directory) @else + @endif - - @if (!$fileStorage->is_based_on_git) + {{-- @if (!$fileStorage->is_based_on_git)
This storage will be deleted. It is not reversible. Please @@ -58,7 +54,7 @@ label="Permanently delete file from the server?"> @endif - @endif + @endif --}}
@if (!$fileStorage->is_directory) @if (data_get($resource, 'settings.is_preserve_repository_enabled')) @@ -75,6 +71,5 @@ Save @endif @endif -
From 6455012109a6078caf2453d286ad31b9e70dbf64 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 26 Feb 2025 08:36:50 +0100 Subject: [PATCH 32/99] feat(ui): Add wire:key to two-step confirmation settings --- resources/views/livewire/settings/index.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/livewire/settings/index.blade.php b/resources/views/livewire/settings/index.blade.php index 2bf2402a2..8b1c6cfed 100644 --- a/resources/views/livewire/settings/index.blade.php +++ b/resources/views/livewire/settings/index.blade.php @@ -132,12 +132,12 @@

Confirmation Settings

@if ($disable_two_step_confirmation) -
+
@else -
+
id-$service->name"; $statusFromDb = $service->status; if ($statusFromDb !== $containerStatus) { - // ray('Updating status: ' . $containerStatus); $service->update(['status' => $containerStatus]); } else { $service->update(['last_online_at' => now()]); diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php index ff926bf70..4762a04b9 100644 --- a/app/Http/Controllers/Api/ApplicationsController.php +++ b/app/Http/Controllers/Api/ApplicationsController.php @@ -1291,11 +1291,6 @@ class ApplicationsController extends Controller $dockerCompose = base64_decode($request->docker_compose_raw); $dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); - // $isValid = validateComposeFile($dockerComposeRaw, $server_id); - // if ($isValid !== 'OK') { - // return $this->dispatch('error', "Invalid docker-compose file.\n$isValid"); - // } - $service = new Service; removeUnnecessaryFieldsFromRequest($request); $service->fill($request->all()); diff --git a/app/Http/Controllers/Webhook/Bitbucket.php b/app/Http/Controllers/Webhook/Bitbucket.php index b629daf54..33d8f8532 100644 --- a/app/Http/Controllers/Webhook/Bitbucket.php +++ b/app/Http/Controllers/Webhook/Bitbucket.php @@ -49,7 +49,7 @@ class Bitbucket extends Controller $full_name = data_get($payload, 'repository.full_name'); $commit = data_get($payload, 'push.changes.0.new.target.hash'); - if (!$branch) { + if (! $branch) { return response([ 'status' => 'failed', 'message' => 'Nothing to do. No branch found in the request.', diff --git a/app/Http/Controllers/Webhook/Gitea.php b/app/Http/Controllers/Webhook/Gitea.php index cc53f2034..dbdd0b27d 100644 --- a/app/Http/Controllers/Webhook/Gitea.php +++ b/app/Http/Controllers/Webhook/Gitea.php @@ -202,7 +202,6 @@ class Gitea extends Controller if ($found) { $found->delete(); $container_name = generateApplicationContainerName($application, $pull_request_id); - // ray('Stopping container: ' . $container_name); instant_remote_process(["docker rm -f $container_name"], $application->destination->server); $return_payloads->push([ 'application' => $application->name, diff --git a/app/Http/Controllers/Webhook/Github.php b/app/Http/Controllers/Webhook/Github.php index ac1d4ded2..882f2be8b 100644 --- a/app/Http/Controllers/Webhook/Github.php +++ b/app/Http/Controllers/Webhook/Github.php @@ -208,7 +208,6 @@ class Github extends Controller if ($found) { $found->delete(); $container_name = generateApplicationContainerName($application, $pull_request_id); - // ray('Stopping container: ' . $container_name); instant_remote_process(["docker rm -f $container_name"], $application->destination->server); $return_payloads->push([ 'application' => $application->name, diff --git a/app/Http/Controllers/Webhook/Gitlab.php b/app/Http/Controllers/Webhook/Gitlab.php index d8dcc0c3b..cf6874b8c 100644 --- a/app/Http/Controllers/Webhook/Gitlab.php +++ b/app/Http/Controllers/Webhook/Gitlab.php @@ -227,7 +227,6 @@ class Gitlab extends Controller if ($found) { $found->delete(); $container_name = generateApplicationContainerName($application, $pull_request_id); - // ray('Stopping container: ' . $container_name); instant_remote_process(["docker rm -f $container_name"], $application->destination->server); $return_payloads->push([ 'application' => $application->name, diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index c28f22742..d0e88df44 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -1207,7 +1207,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue if ($this->application->custom_healthcheck_found) { $this->application_deployment_queue->addLogEntry('Custom healthcheck found, skipping default healthcheck.'); } - // ray('New container name: ', $this->container_name); if ($this->container_name) { $counter = 1; $this->application_deployment_queue->addLogEntry('Waiting for healthcheck to pass on the new container.'); @@ -1410,7 +1409,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue continue; } - // ray('Deploying to additional destination: ', $server->name); $deployment_uuid = new Cuid2; queue_application_deployment( deployment_uuid: $deployment_uuid, diff --git a/app/Livewire/MonacoEditor.php b/app/Livewire/MonacoEditor.php index 42d276e64..53ca1d386 100644 --- a/app/Livewire/MonacoEditor.php +++ b/app/Livewire/MonacoEditor.php @@ -2,7 +2,7 @@ namespace App\Livewire; -//use Livewire\Component; +// use Livewire\Component; use Illuminate\View\Component; use Visus\Cuid2\Cuid2; diff --git a/app/Livewire/Project/New/DockerCompose.php b/app/Livewire/Project/New/DockerCompose.php index 27975eaa2..2f51094d1 100644 --- a/app/Livewire/Project/New/DockerCompose.php +++ b/app/Livewire/Project/New/DockerCompose.php @@ -52,12 +52,6 @@ class DockerCompose extends Component 'dockerComposeRaw' => 'required', ]); $this->dockerComposeRaw = Yaml::dump(Yaml::parse($this->dockerComposeRaw), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); - - $isValid = validateComposeFile($this->dockerComposeRaw, $server_id); - if ($isValid !== 'OK') { - return $this->dispatch('error', "Invalid docker-compose file.\n$isValid"); - } - $project = Project::where('uuid', $this->parameters['project_uuid'])->first(); $environment = $project->load(['environments'])->environments->where('uuid', $this->parameters['environment_uuid'])->first(); diff --git a/app/Livewire/Project/Service/EditCompose.php b/app/Livewire/Project/Service/EditCompose.php index dc043e65a..8ece12790 100644 --- a/app/Livewire/Project/Service/EditCompose.php +++ b/app/Livewire/Project/Service/EditCompose.php @@ -39,6 +39,16 @@ class EditCompose extends Component $this->service = Service::find($this->serviceId); } + public function validateCompose() + { + $isValid = validateComposeFile($this->service->docker_compose_raw, $this->service->server_id); + if ($isValid !== 'OK') { + $this->dispatch('error', "Invalid docker-compose file.\n$isValid"); + } else { + $this->dispatch('success', 'Docker compose is valid.'); + } + } + public function saveEditedCompose() { $this->dispatch('info', 'Saving new docker compose...'); diff --git a/app/Livewire/Project/Service/StackForm.php b/app/Livewire/Project/Service/StackForm.php index 2c751aa92..368598466 100644 --- a/app/Livewire/Project/Service/StackForm.php +++ b/app/Livewire/Project/Service/StackForm.php @@ -63,7 +63,7 @@ class StackForm extends Component public function saveCompose($raw) { $this->service->docker_compose_raw = $raw; - $this->submit(notify: false); + $this->submit(notify: true); } public function instantSave() @@ -76,10 +76,6 @@ class StackForm extends Component { try { $this->validate(); - $isValid = validateComposeFile($this->service->docker_compose_raw, $this->service->server->id); - if ($isValid !== 'OK') { - throw new \Exception("Invalid docker-compose file.\n$isValid"); - } $this->service->save(); $this->service->saveExtraFields($this->fields); $this->service->parse(); diff --git a/app/Livewire/Project/Shared/Webhooks.php b/app/Livewire/Project/Shared/Webhooks.php index aab1fdc47..57c65c4dd 100644 --- a/app/Livewire/Project/Shared/Webhooks.php +++ b/app/Livewire/Project/Shared/Webhooks.php @@ -29,8 +29,6 @@ class Webhooks extends Component public function mount() { - // ray()->clearAll(); - // ray()->showQueries(); $this->deploywebhook = generateDeployWebhook($this->resource); $this->githubManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_github'); diff --git a/app/Livewire/Server/Proxy/Deploy.php b/app/Livewire/Server/Proxy/Deploy.php index 4f9d41092..f823ff3d4 100644 --- a/app/Livewire/Server/Proxy/Deploy.php +++ b/app/Livewire/Server/Proxy/Deploy.php @@ -105,7 +105,6 @@ class Deploy extends Component $startTime = Carbon::now()->getTimestamp(); while ($process->running()) { - ray('running'); if (Carbon::now()->getTimestamp() - $startTime >= $timeout) { $this->forceStopContainer($containerName); break; diff --git a/app/Livewire/Source/Github/Change.php b/app/Livewire/Source/Github/Change.php index fc597748e..20f52c322 100644 --- a/app/Livewire/Source/Github/Change.php +++ b/app/Livewire/Source/Github/Change.php @@ -101,7 +101,6 @@ class Change extends Component // ]); // } - // ray($runners_by_repository); // } public function mount() diff --git a/app/Models/Server.php b/app/Models/Server.php index 187685d66..f5cf84604 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -437,10 +437,6 @@ class Server extends BaseModel "mkdir -p $dynamic_config_path", "echo '$base64' | base64 -d | tee $file > /dev/null", ], $this); - - if (config('app.env') === 'local') { - // ray($yaml); - } } } elseif ($this->proxyType() === 'CADDY') { $file = "$dynamic_config_path/coolify.caddy"; @@ -970,10 +966,8 @@ $schema://$host { } }); if ($supported->count() === 1) { - // ray('supported'); return str($supported->first()); } else { - // ray('not supported'); return false; } } diff --git a/app/Notifications/Dto/PushoverMessage.php b/app/Notifications/Dto/PushoverMessage.php index 0efd1d526..abf6f1b7a 100644 --- a/app/Notifications/Dto/PushoverMessage.php +++ b/app/Notifications/Dto/PushoverMessage.php @@ -40,7 +40,7 @@ class PushoverMessage if ($buttonUrl && str_contains($buttonUrl, 'http://localhost')) { $buttonUrl = str_replace('http://localhost', config('app.url'), $buttonUrl); } - $payload['message'] .= " " . $text . ''; + $payload['message'] .= " ".$text.''; } Log::info('Pushover message', $payload); diff --git a/app/Traits/HasNotificationSettings.php b/app/Traits/HasNotificationSettings.php index ef858d0b6..bb088896a 100644 --- a/app/Traits/HasNotificationSettings.php +++ b/app/Traits/HasNotificationSettings.php @@ -4,9 +4,9 @@ namespace App\Traits; use App\Notifications\Channels\DiscordChannel; use App\Notifications\Channels\EmailChannel; +use App\Notifications\Channels\PushoverChannel; use App\Notifications\Channels\SlackChannel; use App\Notifications\Channels\TelegramChannel; -use App\Notifications\Channels\PushoverChannel; use Illuminate\Database\Eloquent\Model; trait HasNotificationSettings diff --git a/bootstrap/helpers/applications.php b/bootstrap/helpers/applications.php index 73d5389ae..d5283898e 100644 --- a/bootstrap/helpers/applications.php +++ b/bootstrap/helpers/applications.php @@ -91,8 +91,6 @@ function next_queuable(string $server_id, string $application_id): bool $server = Server::find($server_id); $concurrent_builds = $server->settings->concurrent_builds; - // ray("serverId:{$server->id}", "concurrentBuilds:{$concurrent_builds}", "deployments:{$deployments->count()}", "sameApplicationDeployments:{$same_application_deployments->count()}")->green(); - if ($deployments->count() > $concurrent_builds) { return false; } diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 696f6a8c4..59318eec5 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -569,7 +569,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview if ($shouldGenerateLabelsExactly) { switch ($application->destination->server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $labels = $labels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, @@ -577,10 +577,11 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); break; case ProxyTypes::CADDY->value: - $labels = $labels->merge(fqdnLabelsForCaddy( + $proxyLabels = fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -589,11 +590,12 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); break; } } else { - $labels = $labels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, @@ -601,8 +603,8 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - )); - $labels = $labels->merge(fqdnLabelsForCaddy( + ); + $proxyLabels = fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -611,7 +613,8 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); } } } else { @@ -624,17 +627,18 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview if ($shouldGenerateLabelsExactly) { switch ($application->destination->server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $labels = $labels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); break; case ProxyTypes::CADDY->value: - $labels = $labels->merge(fqdnLabelsForCaddy( + $proxyLabels = fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -642,19 +646,20 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); break; } } else { - $labels = $labels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - )); - $labels = $labels->merge(fqdnLabelsForCaddy( + ); + $proxyLabels = fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -662,7 +667,8 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - )); + ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); } } @@ -778,7 +784,6 @@ function convertDockerRunToCompose(?string $custom_docker_run_options = null) } } } - ray($payload); $compose_options->put('deploy', [ 'resources' => [ 'reservations' => [ @@ -829,26 +834,20 @@ function generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker function validateComposeFile(string $compose, int $server_id): string|Throwable { - return 'OK'; + $uuid = Str::random(10); try { - $uuid = Str::random(10); - $server = Server::findOrFail($server_id); + $server = Server::ownedByCurrentTeam()->findOrFail($server_id); $base64_compose = base64_encode($compose); - $output = instant_remote_process([ + instant_remote_process([ "echo {$base64_compose} | base64 -d | tee /tmp/{$uuid}.yml > /dev/null", - "docker compose -f /tmp/{$uuid}.yml config", + "chmod 600 /tmp/{$uuid}.yml", + "docker compose -f /tmp/{$uuid}.yml config --no-interpolate --no-path-resolution -q", + "rm /tmp/{$uuid}.yml", ], $server); - ray($output); return 'OK'; } catch (\Throwable $e) { - ray($e); - return $e->getMessage(); - } finally { - instant_remote_process([ - "rm /tmp/{$uuid}.yml", - ], $server); } } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 3fba7edb7..c3d7d0bfc 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -800,7 +800,6 @@ function parseEnvVariable(Str|string $value) } else { // SERVICE_BASE64_64_UMAMI $command = $value->after('SERVICE_')->beforeLast('_'); - ray($command); } } } @@ -952,7 +951,6 @@ function validate_dns_entry(string $fqdn, Server $server) $type = \PurplePixie\PhpDns\DNSTypes::NAME_A; foreach ($dns_servers as $dns_server) { try { - ray("Checking $host on $dns_server"); $query = new DNSQuery($dns_server); $results = $query->query($host, $type); if ($results === false || $query->hasError()) { @@ -961,13 +959,10 @@ function validate_dns_entry(string $fqdn, Server $server) foreach ($results as $result) { if ($result->getType() == $type) { if (ip_match($result->getData(), $cloudflare_ips->toArray(), $match)) { - ray("Found match in Cloudflare IPs: $match"); $found_matching_ip = true; break; } if ($result->getData() === $ip) { - ray($host.' has IP address '.$result->getData()); - ray($result->getString()); $found_matching_ip = true; break; } @@ -977,7 +972,6 @@ function validate_dns_entry(string $fqdn, Server $server) } catch (\Exception) { } } - ray("Found match: $found_matching_ip"); return $found_matching_ip; } @@ -1331,7 +1325,6 @@ function parseServiceVolumes($serviceVolumes, $resource, $topLevelVolumes, $pull $isDirectory = (bool) data_get($volume, 'isDirectory', null) || (bool) data_get($volume, 'is_directory', null); if ((is_null($isDirectory) || ! $isDirectory) && is_null($content)) { // if isDirectory is not set (or false) & content is also not set, we assume it is a directory - ray('setting isDirectory to true'); $isDirectory = true; } } @@ -1483,6 +1476,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceNetworks = collect(data_get($service, 'networks', [])); $serviceVariables = collect(data_get($service, 'environment', [])); $serviceLabels = collect(data_get($service, 'labels', [])); + $serviceLabels = convertToKeyValueCollection($serviceLabels); $hasHostNetworkMode = data_get($service, 'network_mode') === 'host' ? true : false; if ($serviceLabels->count() > 0) { $removedLabels = collect([]); @@ -1499,7 +1493,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceLabels->push("$removedLabelName=$removedLabel"); } } - $containerName = "$serviceName-{$resource->uuid}"; // Decide if the service is a database @@ -1662,7 +1655,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } if (is_null($isDirectory) && is_null($content)) { // if isDirectory is not set & content is also not set, we assume it is a directory - ray('setting isDirectory to true'); $isDirectory = true; } } @@ -2013,7 +2005,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if ($shouldGenerateLabelsExactly) { switch ($resource->server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $resource->uuid, domains: $fqdns, is_force_https_enabled: true, @@ -2022,10 +2014,12 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - )); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + break; case ProxyTypes::CADDY->value: - $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( + $proxyLabels = fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, domains: $fqdns, @@ -2035,11 +2029,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - )); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + break; } } else { - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $resource->uuid, domains: $fqdns, is_force_https_enabled: true, @@ -2048,8 +2044,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - )); - $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( + ); + $proxyLabels = fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, domains: $fqdns, @@ -2059,7 +2055,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - )); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); } } } @@ -2208,6 +2205,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceVariables = collect(data_get($service, 'environment', [])); $serviceDependencies = collect(data_get($service, 'depends_on', [])); $serviceLabels = collect(data_get($service, 'labels', [])); + $serviceLabels = convertToKeyValueCollection($serviceLabels); $serviceBuildVariables = collect(data_get($service, 'build.args', [])); $serviceVariables = $serviceVariables->merge($serviceBuildVariables); if ($serviceLabels->count() > 0) { @@ -2529,9 +2527,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } } } - if ($collectedPorts->count() > 0) { - ray($collectedPorts->implode(',')); - } $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { return $value == $definedNetwork; }); @@ -2784,48 +2779,46 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if ($shouldGenerateLabelsExactly) { switch ($server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $serviceLabels = $serviceLabels->merge( - fqdnLabelsForTraefik( - uuid: $resource->uuid, - domains: $fqdns, - serviceLabels: $serviceLabels, - generate_unique_uuid: $resource->build_pack === 'dockercompose', - image: data_get($service, 'image'), - is_force_https_enabled: $resource->isForceHttpsEnabled(), - is_gzip_enabled: $resource->isGzipEnabled(), - is_stripprefix_enabled: $resource->isStripprefixEnabled(), - ) + $proxyLabels = fqdnLabelsForTraefik( + uuid: $resource->uuid, + domains: $fqdns, + serviceLabels: $serviceLabels, + generate_unique_uuid: $resource->build_pack === 'dockercompose', + image: data_get($service, 'image'), + is_force_https_enabled: $resource->isForceHttpsEnabled(), + is_gzip_enabled: $resource->isGzipEnabled(), + is_stripprefix_enabled: $resource->isStripprefixEnabled(), ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + break; case ProxyTypes::CADDY->value: - $serviceLabels = $serviceLabels->merge( - fqdnLabelsForCaddy( - network: $resource->destination->network, - uuid: $resource->uuid, - domains: $fqdns, - serviceLabels: $serviceLabels, - image: data_get($service, 'image'), - is_force_https_enabled: $resource->isForceHttpsEnabled(), - is_gzip_enabled: $resource->isGzipEnabled(), - is_stripprefix_enabled: $resource->isStripprefixEnabled(), - ) + $proxyLabels = fqdnLabelsForCaddy( + network: $resource->destination->network, + uuid: $resource->uuid, + domains: $fqdns, + serviceLabels: $serviceLabels, + image: data_get($service, 'image'), + is_force_https_enabled: $resource->isForceHttpsEnabled(), + is_gzip_enabled: $resource->isGzipEnabled(), + is_stripprefix_enabled: $resource->isStripprefixEnabled(), ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + break; } } else { - $serviceLabels = $serviceLabels->merge( - fqdnLabelsForTraefik( - uuid: $resource->uuid, - domains: $fqdns, - serviceLabels: $serviceLabels, - generate_unique_uuid: $resource->build_pack === 'dockercompose', - image: data_get($service, 'image'), - is_force_https_enabled: $resource->isForceHttpsEnabled(), - is_gzip_enabled: $resource->isGzipEnabled(), - is_stripprefix_enabled: $resource->isStripprefixEnabled(), - ) + $proxyLabels = fqdnLabelsForTraefik( + uuid: $resource->uuid, + domains: $fqdns, + serviceLabels: $serviceLabels, + generate_unique_uuid: $resource->build_pack === 'dockercompose', + image: data_get($service, 'image'), + is_force_https_enabled: $resource->isForceHttpsEnabled(), + is_gzip_enabled: $resource->isGzipEnabled(), + is_stripprefix_enabled: $resource->isStripprefixEnabled(), ); - $serviceLabels = $serviceLabels->merge( + $proxyLabels = fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, @@ -2835,8 +2828,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_force_https_enabled: $resource->isForceHttpsEnabled(), is_gzip_enabled: $resource->isGzipEnabled(), is_stripprefix_enabled: $resource->isStripprefixEnabled(), - ) - ); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); } } } @@ -2851,7 +2844,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal pull_request_id: $pull_request_id, type: 'application' ); - $serviceLabels = $serviceLabels->merge($defaultLabels); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($defaultLabels)); if ($server->isLogDrainEnabled()) { if ($resource instanceof Application && $resource->isLogDrainEnabled()) { @@ -2956,7 +2949,6 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int } $parsedServices = collect([]); - // ray()->clearAll(); $allMagicEnvironments = collect([]); foreach ($services as $serviceName => $service) { @@ -3016,7 +3008,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $environment = $environment->merge($buildArgs); // convert environment variables to one format - $environment = convertComposeEnvironmentToArray($environment); + $environment = convertToKeyValueCollection($environment); // Add Coolify defined environments $allEnvironments = $resource->environment_variables()->get(['key', 'value']); @@ -3192,12 +3184,13 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $use_network_mode = data_get($service, 'network_mode') !== null; $depends_on = collect(data_get($service, 'depends_on', [])); $labels = collect(data_get($service, 'labels', [])); + $labels = convertToKeyValueCollection($labels); $environment = collect(data_get($service, 'environment', [])); $ports = collect(data_get($service, 'ports', [])); $buildArgs = collect(data_get($service, 'build.args', [])); $environment = $environment->merge($buildArgs); - $environment = convertComposeEnvironmentToArray($environment); + $environment = convertToKeyValueCollection($environment); $coolifyEnvironments = collect([]); $isDatabase = isDatabaseImage(data_get_str($service, 'image')); @@ -3704,7 +3697,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int return $value; }); } - $serviceLabels = $labels->merge($defaultLabels); + $serviceLabels = $labels->merge(convertToKeyValueCollection($defaultLabels)); if ($serviceLabels->count() > 0) { if ($isApplication) { $isContainerLabelEscapeEnabled = data_get($resource, 'settings.is_container_label_escape_enabled'); @@ -3736,7 +3729,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int if ($shouldGenerateLabelsExactly) { switch ($server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $uuid, domains: $fqdns, is_force_https_enabled: true, @@ -3745,10 +3738,11 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image - )); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); break; case ProxyTypes::CADDY->value: - $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( + $proxyLabels = fqdnLabelsForCaddy( network: $network, uuid: $uuid, domains: $fqdns, @@ -3759,11 +3753,13 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int service_name: $serviceName, image: $image, predefinedPort: $predefinedPort - )); + ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + break; } } else { - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( + $proxyLabels = fqdnLabelsForTraefik( uuid: $uuid, domains: $fqdns, is_force_https_enabled: true, @@ -3772,8 +3768,8 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image - )); - $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( + ); + $proxyLabels = $proxyLabels->merge(fqdnLabelsForCaddy( network: $network, uuid: $uuid, domains: $fqdns, @@ -3785,6 +3781,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int image: $image, predefinedPort: $predefinedPort )); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); } } if ($isService) { @@ -3934,7 +3931,7 @@ function add_coolify_default_environment_variables(StandaloneRedis|StandalonePos } } -function convertComposeEnvironmentToArray($environment) +function convertToKeyValueCollection($environment) { $convertedServiceVariables = collect([]); if (isAssociativeArray($environment)) { diff --git a/config/chunk-upload.php b/config/chunk-upload.php index a0baf8139..e577eb858 100644 --- a/config/chunk-upload.php +++ b/config/chunk-upload.php @@ -1,4 +1,5 @@ [ 'timeline' => false, // Add the views to the timeline (Experimental) - 'data' => false, //true for all data, 'keys' for only names, false for no parameters. + 'data' => false, // true for all data, 'keys' for only names, false for no parameters. 'group' => 50, // Group duplicate views. Pass value to auto-group, or true/false to force 'exclude_paths' => [ // Add the paths which you don't want to appear in the views 'vendor/filament', // Exclude Filament components by default diff --git a/resources/views/livewire/project/service/edit-compose.blade.php b/resources/views/livewire/project/service/edit-compose.blade.php index beaccac91..513bd8a90 100644 --- a/resources/views/livewire/project/service/edit-compose.blade.php +++ b/resources/views/livewire/project/service/edit-compose.blade.php @@ -20,27 +20,27 @@
- -
-
- Switch - Textarea +
+ +
+
-
-
-
- Show Deployable Compose -
-
- Show Source - Compose -
+
+
+ Show Deployable Compose +
+
+ Show Source + Compose
- + + Validate + + Save
diff --git a/tests/Browser/LoginTest.php b/tests/Browser/LoginTest.php index 5e8d5c53e..d20e65294 100644 --- a/tests/Browser/LoginTest.php +++ b/tests/Browser/LoginTest.php @@ -16,7 +16,7 @@ class LoginTest extends DuskTestCase * * @throws Throwable */ - public function testLogin() + public function test_login() { $this->browse(callback: function (Browser $browser) { $browser->loginWithRootUser() diff --git a/tests/Browser/Project/ProjectAddNewTest.php b/tests/Browser/Project/ProjectAddNewTest.php index 0dae7603e..b03313e4b 100644 --- a/tests/Browser/Project/ProjectAddNewTest.php +++ b/tests/Browser/Project/ProjectAddNewTest.php @@ -16,7 +16,7 @@ class ProjectAddNewTest extends DuskTestCase * * @throws Throwable */ - public function testLogin() + public function test_login() { $this->browse(function (Browser $browser) { $browser->loginWithRootUser() diff --git a/tests/Browser/Project/ProjectSearchTest.php b/tests/Browser/Project/ProjectSearchTest.php index aedf17183..7bc6796d1 100644 --- a/tests/Browser/Project/ProjectSearchTest.php +++ b/tests/Browser/Project/ProjectSearchTest.php @@ -16,7 +16,7 @@ class ProjectSearchTest extends DuskTestCase * * @throws Throwable */ - public function testLogin() + public function test_login() { $this->browse(function (Browser $browser) { $browser->loginWithRootUser() diff --git a/tests/Browser/Project/ProjectTest.php b/tests/Browser/Project/ProjectTest.php index e4707da8a..0d360e460 100644 --- a/tests/Browser/Project/ProjectTest.php +++ b/tests/Browser/Project/ProjectTest.php @@ -16,7 +16,7 @@ class ProjectTest extends DuskTestCase * * @throws Throwable */ - public function testLogin() + public function test_login() { $this->browse(function (Browser $browser) { $browser->loginWithRootUser() diff --git a/tests/Feature/DockerComposeParseTest.php b/tests/Feature/DockerComposeParseTest.php index d21adac8e..9407d2470 100644 --- a/tests/Feature/DockerComposeParseTest.php +++ b/tests/Feature/DockerComposeParseTest.php @@ -358,7 +358,7 @@ use Symfony\Component\Yaml\Yaml; // expect($output)->toContain('Docker version'); // }); -// test('ConvertComposeEnvironmentToArray', function () { +// test('convertToKeyValueCollection', function () { // ray()->clearAll(); // $yaml = ' // services: @@ -374,9 +374,9 @@ use Symfony\Component\Yaml\Yaml; // - POSTGRES_DB: activepieces // '; // $parsedYaml = Yaml::parse($yaml); -// $output = convertComposeEnvironmentToArray($parsedYaml['services']['activepieces']['environment']); -// $output2 = convertComposeEnvironmentToArray($parsedYaml['services']['activepieces2']['environment']); -// $dboutput = convertComposeEnvironmentToArray($parsedYaml['services']['postgres']['environment']); +// $output = convertToKeyValueCollection($parsedYaml['services']['activepieces']['environment']); +// $output2 = convertToKeyValueCollection($parsedYaml['services']['activepieces2']['environment']); +// $dboutput = convertToKeyValueCollection($parsedYaml['services']['postgres']['environment']); // ray($output); // ray($output2); // ray($dboutput); diff --git a/tests/Pest.php b/tests/Pest.php index 0178e9648..236ac497e 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,4 +1,5 @@ Date: Thu, 27 Feb 2025 11:56:39 +0100 Subject: [PATCH 35/99] fix(notifications): Correct environment URL path in application notifications --- app/Notifications/Application/DeploymentSuccess.php | 2 +- app/Notifications/Application/StatusChanged.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Notifications/Application/DeploymentSuccess.php b/app/Notifications/Application/DeploymentSuccess.php index c6bbf43ac..9b59d9162 100644 --- a/app/Notifications/Application/DeploymentSuccess.php +++ b/app/Notifications/Application/DeploymentSuccess.php @@ -44,7 +44,7 @@ class DeploymentSuccess extends CustomEmailNotification if (str($this->fqdn)->explode(',')->count() > 1) { $this->fqdn = str($this->fqdn)->explode(',')->first(); } - $this->deployment_url = base_url()."/project/{$this->project_uuid}/environments/{$this->environment_uuid}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; + $this->deployment_url = base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; } public function via(object $notifiable): array diff --git a/app/Notifications/Application/StatusChanged.php b/app/Notifications/Application/StatusChanged.php index 34c5ed747..fab5487ef 100644 --- a/app/Notifications/Application/StatusChanged.php +++ b/app/Notifications/Application/StatusChanged.php @@ -34,7 +34,7 @@ class StatusChanged extends CustomEmailNotification if (str($this->fqdn)->explode(',')->count() > 1) { $this->fqdn = str($this->fqdn)->explode(',')->first(); } - $this->resource_url = base_url()."/project/{$this->project_uuid}/environments/{$this->environment_uuid}/application/{$this->resource->uuid}"; + $this->resource_url = base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/application/{$this->resource->uuid}"; } public function via(object $notifiable): array From 64f44f3f8bebd465f94cc0ed486a2db9f71d10e0 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Feb 2025 11:56:51 +0100 Subject: [PATCH 36/99] fix(config): Update default PostgreSQL host to coolify-db instead of postgres --- config/database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/database.php b/config/database.php index 6f4acbfd2..a40987de8 100644 --- a/config/database.php +++ b/config/database.php @@ -38,7 +38,7 @@ return [ 'pgsql' => [ 'driver' => 'pgsql', 'url' => env('DATABASE_URL'), - 'host' => env('DB_HOST', 'postgres'), + 'host' => env('DB_HOST', 'coolify-db'), 'port' => env('DB_PORT', '5432'), 'database' => env('DB_DATABASE', 'coolify'), 'username' => env('DB_USERNAME', 'coolify'), From e1c5ace342900373bcc7cdaef5cffc421f3443ae Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Feb 2025 12:17:12 +0100 Subject: [PATCH 37/99] fix(docker): Improve Docker compose file validation process - Increase UUID length for better uniqueness - Add server existence check before validation - Implement cleanup of temporary compose file in finally block --- bootstrap/helpers/docker.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 59318eec5..ebbdcd5da 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -834,9 +834,12 @@ function generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker function validateComposeFile(string $compose, int $server_id): string|Throwable { - $uuid = Str::random(10); + $uuid = Str::random(18); + $server = Server::ownedByCurrentTeam()->find($server_id); try { - $server = Server::ownedByCurrentTeam()->findOrFail($server_id); + if (! $server) { + throw new \Exception('Server not found'); + } $base64_compose = base64_encode($compose); instant_remote_process([ "echo {$base64_compose} | base64 -d | tee /tmp/{$uuid}.yml > /dev/null", @@ -848,6 +851,12 @@ function validateComposeFile(string $compose, int $server_id): string|Throwable return 'OK'; } catch (\Throwable $e) { return $e->getMessage(); + } finally { + if (filled($server)) { + instant_remote_process([ + "rm /tmp/{$uuid}.yml", + ], $server, throwError: false); + } } } From f98c58a0a3b3708cc2769496e4cbcb5423fa6ae8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Feb 2025 12:17:23 +0100 Subject: [PATCH 38/99] fix(ui): Restrict service retrieval to current team --- app/Livewire/Project/Service/EditCompose.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Livewire/Project/Service/EditCompose.php b/app/Livewire/Project/Service/EditCompose.php index 8ece12790..b5f208941 100644 --- a/app/Livewire/Project/Service/EditCompose.php +++ b/app/Livewire/Project/Service/EditCompose.php @@ -31,12 +31,12 @@ class EditCompose extends Component public function refreshEnvs() { - $this->service = Service::find($this->serviceId); + $this->service = Service::ownedByCurrentTeam()->find($this->serviceId); } public function mount() { - $this->service = Service::find($this->serviceId); + $this->service = Service::ownedByCurrentTeam()->find($this->serviceId); } public function validateCompose() From 73e0735aa220a9d843ca50d64fd9f3d0c872ff65 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Feb 2025 12:18:03 +0100 Subject: [PATCH 39/99] fix(core): Only validate custom compose files --- .../views/livewire/project/service/edit-compose.blade.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/resources/views/livewire/project/service/edit-compose.blade.php b/resources/views/livewire/project/service/edit-compose.blade.php index 513bd8a90..df0b857b5 100644 --- a/resources/views/livewire/project/service/edit-compose.blade.php +++ b/resources/views/livewire/project/service/edit-compose.blade.php @@ -37,9 +37,11 @@ Compose
- - Validate - + @if (blank($service->service_type)) + + Validate + + @endif Save From dea125f679ba0980997239d34a6afbb51935b571 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Feb 2025 12:56:37 +0100 Subject: [PATCH 40/99] refactor(notifications): Improve transactional email settings handling - Replace `! $type` checks with `blank($type)` for consistency - Modify email settings configuration to handle null/disabled states - Ensure proper fallback and configuration of email providers --- app/Http/Controllers/Controller.php | 2 +- app/Livewire/Help.php | 2 +- app/Notifications/Channels/EmailChannel.php | 4 +--- .../Channels/TransactionalEmailChannel.php | 2 +- .../TransactionalEmails/ResetPassword.php | 5 +++-- bootstrap/helpers/notifications.php | 16 ++++++++++------ 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 522683efa..14a2950af 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -54,7 +54,7 @@ class Controller extends BaseController 'email' => Str::lower($arrayOfRequest['email']), ]); $type = set_transanctional_email_settings(); - if (! $type) { + if (blank($type)) { return response()->json(['message' => 'Transactional emails are not active'], 400); } $request->validate([Fortify::email() => 'required|email']); diff --git a/app/Livewire/Help.php b/app/Livewire/Help.php index f51527fbe..913710588 100644 --- a/app/Livewire/Help.php +++ b/app/Livewire/Help.php @@ -36,7 +36,7 @@ class Help extends Component $type = set_transanctional_email_settings($settings); // Sending feedback through Cloud API - if ($type === false) { + if (blank($type)) { $url = 'https://app.coolify.io/api/feedback'; Http::post($url, [ 'content' => 'User: `'.auth()->user()?->email.'` with subject: `'.$this->subject.'` has the following problem: `'.$this->description.'`', diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php index 98536d346..b8589cd8e 100644 --- a/app/Notifications/Channels/EmailChannel.php +++ b/app/Notifications/Channels/EmailChannel.php @@ -50,11 +50,9 @@ class EmailChannel if ($emailSettings->use_instance_email_settings) { $type = set_transanctional_email_settings(); - if (! $type) { + if (blank($type)) { throw new Exception('No email settings found.'); } - config()->set('mail.default', $type); - return; } diff --git a/app/Notifications/Channels/TransactionalEmailChannel.php b/app/Notifications/Channels/TransactionalEmailChannel.php index 761780231..114d1f6ed 100644 --- a/app/Notifications/Channels/TransactionalEmailChannel.php +++ b/app/Notifications/Channels/TransactionalEmailChannel.php @@ -35,7 +35,7 @@ class TransactionalEmailChannel private function bootConfigs(): void { $type = set_transanctional_email_settings(); - if (! $type) { + if (blank($type)) { throw new Exception('No email settings found.'); } } diff --git a/app/Notifications/TransactionalEmails/ResetPassword.php b/app/Notifications/TransactionalEmails/ResetPassword.php index 3938a8da7..4593ddb0d 100644 --- a/app/Notifications/TransactionalEmails/ResetPassword.php +++ b/app/Notifications/TransactionalEmails/ResetPassword.php @@ -3,6 +3,7 @@ namespace App\Notifications\TransactionalEmails; use App\Models\InstanceSettings; +use Exception; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; @@ -35,8 +36,8 @@ class ResetPassword extends Notification public function via($notifiable) { $type = set_transanctional_email_settings(); - if (! $type) { - throw new \Exception('No email settings found.'); + if (blank($type)) { + throw new Exception('No email settings found.'); } return ['mail']; diff --git a/bootstrap/helpers/notifications.php b/bootstrap/helpers/notifications.php index 46f0ebca7..b0345df7e 100644 --- a/bootstrap/helpers/notifications.php +++ b/bootstrap/helpers/notifications.php @@ -28,7 +28,7 @@ function send_user_an_email(MailMessage $mail, string $email, ?string $cc = null { $settings = instanceSettings(); $type = set_transanctional_email_settings($settings); - if (! $type) { + if (blank($type)) { throw new Exception('No email settings found.'); } if ($cc) { @@ -54,15 +54,19 @@ function send_user_an_email(MailMessage $mail, string $email, ?string $cc = null } } -function set_transanctional_email_settings(?InstanceSettings $settings = null): ?string // +function set_transanctional_email_settings(?InstanceSettings $settings = null): ?string // returns null|resend|smtp and defaults to array based on mail.php config { if (! $settings) { $settings = instanceSettings(); } - config()->set('mail.from.address', data_get($settings, 'smtp_from_address')); - config()->set('mail.from.name', data_get($settings, 'smtp_from_name')); + if (! data_get($settings, 'smtp_enabled') && ! data_get($settings, 'resend_enabled')) { + return null; + } + if (data_get($settings, 'resend_enabled')) { config()->set('mail.default', 'resend'); + config()->set('mail.from.address', data_get($settings, 'smtp_from_address')); + config()->set('mail.from.name', data_get($settings, 'smtp_from_name')); config()->set('resend.api_key', data_get($settings, 'resend_api_key')); return 'resend'; @@ -76,6 +80,8 @@ function set_transanctional_email_settings(?InstanceSettings $settings = null): }; if (data_get($settings, 'smtp_enabled')) { + config()->set('mail.from.address', data_get($settings, 'smtp_from_address')); + config()->set('mail.from.name', data_get($settings, 'smtp_from_name')); config()->set('mail.default', 'smtp'); config()->set('mail.mailers.smtp', [ 'transport' => 'smtp', @@ -91,6 +97,4 @@ function set_transanctional_email_settings(?InstanceSettings $settings = null): return 'smtp'; } - - return null; } From 53dba895994409110801a0c9b55d47fcb86bdd69 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Feb 2025 12:56:44 +0100 Subject: [PATCH 41/99] fix(mail): Set default mailer to array when not specified --- config/mail.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/mail.php b/config/mail.php index 26af507d9..5b647944b 100644 --- a/config/mail.php +++ b/config/mail.php @@ -13,7 +13,7 @@ return [ | */ - 'default' => env('MAIL_MAILER', null), + 'default' => env('MAIL_MAILER', 'array'), /* |-------------------------------------------------------------------------- From 1e28cf56acb943ee8256379605cac2652a98b340 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Feb 2025 13:26:24 +0100 Subject: [PATCH 42/99] fix(ui): Correct redirect routes after task deletion --- app/Livewire/Project/Shared/ScheduledTask/Show.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Livewire/Project/Shared/ScheduledTask/Show.php b/app/Livewire/Project/Shared/ScheduledTask/Show.php index 171ba3bb2..6d9c6982a 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/Show.php +++ b/app/Livewire/Project/Shared/ScheduledTask/Show.php @@ -133,9 +133,9 @@ class Show extends Component $this->task->delete(); if ($this->type === 'application') { - return redirect()->route('project.application.configuration', $this->parameters, $this->task->name); + return redirect()->route('project.application.scheduled-tasks.show', $this->parameters); } else { - return redirect()->route('project.service.configuration', $this->parameters, $this->task->name); + return redirect()->route('project.service.scheduled-tasks.show', $this->parameters); } } catch (\Exception $e) { return handleError($e); From 3f62225ec348c53e1375fc43bb3fe2428a510c48 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Feb 2025 13:26:35 +0100 Subject: [PATCH 43/99] refactor(scheduled-tasks): Improve scheduled task creation and management --- .../Project/Shared/ScheduledTask/Add.php | 45 +++++++++++++++---- .../Project/Shared/ScheduledTask/All.php | 39 +++------------- .../shared/scheduled-task/all.blade.php | 4 +- 3 files changed, 46 insertions(+), 42 deletions(-) diff --git a/app/Livewire/Project/Shared/ScheduledTask/Add.php b/app/Livewire/Project/Shared/ScheduledTask/Add.php index adfd59217..8ab5f9f27 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/Add.php +++ b/app/Livewire/Project/Shared/ScheduledTask/Add.php @@ -2,15 +2,22 @@ namespace App\Livewire\Project\Shared\ScheduledTask; +use App\Models\ScheduledTask; use Illuminate\Support\Collection; +use Livewire\Attributes\Locked; use Livewire\Component; class Add extends Component { public $parameters; + #[Locked] + public string $id; + + #[Locked] public string $type; + #[Locked] public Collection $containerNames; public string $name; @@ -21,8 +28,6 @@ class Add extends Component public ?string $container = ''; - protected $listeners = ['clearScheduledTask' => 'clear']; - protected $rules = [ 'name' => 'required|string', 'command' => 'required|string', @@ -60,18 +65,42 @@ class Add extends Component $this->container = $this->subServiceName; } } - $this->dispatch('saveScheduledTask', [ - 'name' => $this->name, - 'command' => $this->command, - 'frequency' => $this->frequency, - 'container' => $this->container, - ]); + $this->saveScheduledTask(); $this->clear(); } catch (\Exception $e) { return handleError($e, $this); } } + public function saveScheduledTask() + { + try { + $task = new ScheduledTask(); + $task->name = $this->name; + $task->command = $this->command; + $task->frequency = $this->frequency; + $task->container = $this->container; + $task->team_id = currentTeam()->id; + + switch ($this->type) { + case 'application': + $task->application_id = $this->id; + break; + case 'standalone-postgresql': + $task->standalone_postgresql_id = $this->id; + break; + case 'service': + $task->service_id = $this->id; + break; + } + $task->save(); + $this->dispatch('refreshTasks'); + $this->dispatch('success', 'Scheduled task added.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function clear() { $this->name = ''; diff --git a/app/Livewire/Project/Shared/ScheduledTask/All.php b/app/Livewire/Project/Shared/ScheduledTask/All.php index 6ab8426f3..1782f3f27 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/All.php +++ b/app/Livewire/Project/Shared/ScheduledTask/All.php @@ -4,20 +4,22 @@ namespace App\Livewire\Project\Shared\ScheduledTask; use App\Models\ScheduledTask; use Illuminate\Support\Collection; +use Livewire\Attributes\Locked; +use Livewire\Attributes\On; use Livewire\Component; class All extends Component { + #[Locked] public $resource; + #[Locked] + public array $parameters; + public Collection $containerNames; public ?string $variables = null; - public array $parameters; - - protected $listeners = ['refreshTasks', 'saveScheduledTask' => 'submit']; - public function mount() { $this->parameters = get_route_parameters(); @@ -35,37 +37,10 @@ class All extends Component } } + #[On('refreshTasks')] public function refreshTasks() { $this->resource->refresh(); } - public function submit($data) - { - try { - $task = new ScheduledTask; - $task->name = $data['name']; - $task->command = $data['command']; - $task->frequency = $data['frequency']; - $task->container = $data['container']; - $task->team_id = currentTeam()->id; - - switch ($this->resource->type()) { - case 'application': - $task->application_id = $this->resource->id; - break; - case 'standalone-postgresql': - $task->standalone_postgresql_id = $this->resource->id; - break; - case 'service': - $task->service_id = $this->resource->id; - break; - } - $task->save(); - $this->refreshTasks(); - $this->dispatch('success', 'Scheduled task added.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } } diff --git a/resources/views/livewire/project/shared/scheduled-task/all.blade.php b/resources/views/livewire/project/shared/scheduled-task/all.blade.php index 034954810..296b60dc8 100644 --- a/resources/views/livewire/project/shared/scheduled-task/all.blade.php +++ b/resources/views/livewire/project/shared/scheduled-task/all.blade.php @@ -3,9 +3,9 @@

Scheduled Tasks

@if ($resource->type() == 'application') - + @elseif ($resource->type() == 'service') - + @endif
From cd1fc649e3a0cf4df9db2d046f07166e137ef789 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Feb 2025 13:54:10 +0100 Subject: [PATCH 44/99] feat(database): Add index to scheduled task executions for improved query performance --- ...add_index_to_scheduled_task_executions.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 database/migrations/2025_02_27_125249_add_index_to_scheduled_task_executions.php diff --git a/database/migrations/2025_02_27_125249_add_index_to_scheduled_task_executions.php b/database/migrations/2025_02_27_125249_add_index_to_scheduled_task_executions.php new file mode 100644 index 000000000..e8033cfdc --- /dev/null +++ b/database/migrations/2025_02_27_125249_add_index_to_scheduled_task_executions.php @@ -0,0 +1,28 @@ +index(['scheduled_task_id', 'created_at'], 'scheduled_task_executions_task_id_created_at_index'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('scheduled_task_executions', function (Blueprint $table) { + $table->dropIndex('scheduled_task_executions_task_id_created_at_index'); + }); + } +}; From 9c4395e6de8e41e0870c21c85dd6d532f5264074 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 27 Feb 2025 14:04:22 +0100 Subject: [PATCH 45/99] feat(database): Add index to scheduled database backup executions --- ...7_125249_add_index_to_scheduled_task_executions.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/database/migrations/2025_02_27_125249_add_index_to_scheduled_task_executions.php b/database/migrations/2025_02_27_125249_add_index_to_scheduled_task_executions.php index e8033cfdc..45c6b581d 100644 --- a/database/migrations/2025_02_27_125249_add_index_to_scheduled_task_executions.php +++ b/database/migrations/2025_02_27_125249_add_index_to_scheduled_task_executions.php @@ -14,6 +14,13 @@ return new class extends Migration Schema::table('scheduled_task_executions', function (Blueprint $table) { $table->index(['scheduled_task_id', 'created_at'], 'scheduled_task_executions_task_id_created_at_index'); }); + + Schema::table('scheduled_database_backup_executions', function (Blueprint $table) { + $table->index( + ['scheduled_database_backup_id', 'created_at'], + 'scheduled_db_backup_executions_backup_id_created_at_index' + ); + }); } /** @@ -24,5 +31,8 @@ return new class extends Migration Schema::table('scheduled_task_executions', function (Blueprint $table) { $table->dropIndex('scheduled_task_executions_task_id_created_at_index'); }); + Schema::table('scheduled_database_backup_executions', function (Blueprint $table) { + $table->dropIndex('scheduled_db_backup_executions_backup_id_created_at_index'); + }); } }; From 37553e79b7a3f8bb72f42efee410213ad08d3f52 Mon Sep 17 00:00:00 2001 From: janwiebe-jump <64576907+janwiebe-jump@users.noreply.github.com> Date: Thu, 27 Feb 2025 17:25:33 +0100 Subject: [PATCH 46/99] Gitea webhook sends action synchronized --- app/Http/Controllers/Webhook/Gitea.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Webhook/Gitea.php b/app/Http/Controllers/Webhook/Gitea.php index cc53f2034..b5ad5607e 100644 --- a/app/Http/Controllers/Webhook/Gitea.php +++ b/app/Http/Controllers/Webhook/Gitea.php @@ -152,7 +152,7 @@ class Gitea extends Controller } } if ($x_gitea_event === 'pull_request') { - if ($action === 'opened' || $action === 'synchronize' || $action === 'reopened') { + if ($action === 'opened' || $action === 'synchronized' || $action === 'reopened') { if ($application->isPRDeployable()) { $deployment_uuid = new Cuid2; $found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first(); From 2f826c56e84b82b2c09a755f1108b00bda794018 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 28 Feb 2025 11:23:08 +0100 Subject: [PATCH 47/99] fix(core): Adding a new server should not try to make the default docker network --- app/Models/Server.php | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/app/Models/Server.php b/app/Models/Server.php index f5cf84604..828500c40 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -17,6 +17,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Stringable; use OpenApi\Attributes as OA; @@ -24,6 +25,7 @@ use Spatie\SchemalessAttributes\Casts\SchemalessAttributes; use Spatie\SchemalessAttributes\SchemalessAttributesTrait; use Spatie\Url\Url; use Symfony\Component\Yaml\Yaml; +use Visus\Cuid2\Cuid2; #[OA\Schema( description: 'Server model', @@ -101,11 +103,13 @@ class Server extends BaseModel 'server_id' => $server->id, ]); } else { - StandaloneDocker::create([ + $standaloneDocker = new StandaloneDocker([ 'name' => 'coolify', + 'uuid' => (string) new Cuid2, 'network' => 'coolify', 'server_id' => $server->id, ]); + $standaloneDocker->saveQuietly(); } } if (! isset($server->proxy->redirect_enabled)) { @@ -705,22 +709,6 @@ $schema://$host { ]; } - public function getContainersWithSentinel(): Collection - { - $sentinel_found = instant_remote_process(['docker inspect coolify-sentinel'], $this, false); - $sentinel_found = json_decode($sentinel_found, true); - $status = data_get($sentinel_found, '0.State.Status', 'exited'); - if ($status === 'running') { - $containers = instant_remote_process(['docker exec coolify-sentinel sh -c "curl http://127.0.0.1:8888/api/containers"'], $this, false); - if (is_null($containers)) { - return collect([]); - } - $containers = data_get(json_decode($containers, true), 'containers', []); - - return collect($containers); - } - } - public function loadAllContainers(): Collection { if ($this->isFunctional()) { @@ -1036,7 +1024,7 @@ $schema://$host { $unreachableNotificationSent = (bool) $this->unreachable_notification_sent; $isReachable = (bool) $this->settings->is_reachable; - \Log::debug('Server reachability check', [ + Log::debug('Server reachability check', [ 'server_id' => $this->id, 'is_reachable' => $isReachable, 'notification_sent' => $unreachableNotificationSent, @@ -1048,7 +1036,7 @@ $schema://$host { $this->save(); if ($unreachableNotificationSent === true) { - \Log::debug('Server is now reachable, sending notification', [ + Log::debug('Server is now reachable, sending notification', [ 'server_id' => $this->id, ]); $this->sendReachableNotification(); @@ -1058,7 +1046,7 @@ $schema://$host { } $this->increment('unreachable_count'); - \Log::debug('Incremented unreachable count', [ + Log::debug('Incremented unreachable count', [ 'server_id' => $this->id, 'new_count' => $this->unreachable_count, ]); @@ -1066,7 +1054,7 @@ $schema://$host { if ($this->unreachable_count === 1) { $this->settings->is_reachable = true; $this->settings->save(); - \Log::debug('First unreachable attempt, marking as reachable', [ + Log::debug('First unreachable attempt, marking as reachable', [ 'server_id' => $this->id, ]); @@ -1077,7 +1065,7 @@ $schema://$host { $failedChecks = 0; for ($i = 0; $i < 3; $i++) { $status = $this->serverStatus(); - \Log::debug('Additional reachability check', [ + Log::debug('Additional reachability check', [ 'server_id' => $this->id, 'attempt' => $i + 1, 'status' => $status, @@ -1089,7 +1077,7 @@ $schema://$host { } if ($failedChecks === 3 && ! $unreachableNotificationSent) { - \Log::debug('Server confirmed unreachable after 3 attempts, sending notification', [ + Log::debug('Server confirmed unreachable after 3 attempts, sending notification', [ 'server_id' => $this->id, ]); $this->sendUnreachableNotification(); From fb3f5e0a3eb9639cfffed251a520a305c4d861e3 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 28 Feb 2025 11:23:54 +0100 Subject: [PATCH 48/99] fix(core): Clean up unnecessary files during application image build --- app/Jobs/ApplicationDeploymentJob.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index d0e88df44..21c7e4820 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -2021,6 +2021,8 @@ LABEL coolify.deploymentId={$this->deployment_uuid} COPY . . RUN rm -f /usr/share/nginx/html/nginx.conf RUN rm -f /usr/share/nginx/html/Dockerfile +RUN rm -f /usr/share/nginx/html/docker-compose.yaml +RUN rm -f /usr/share/nginx/html/.env COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); if (str($this->application->custom_nginx_configuration)->isNotEmpty()) { $nginx_config = base64_encode($this->application->custom_nginx_configuration); From 1c21652d5db98469606216bcadded147161abdcd Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 28 Feb 2025 12:44:20 +0100 Subject: [PATCH 49/99] fix(core): Improve label generation and merging for applications and services --- app/Jobs/ApplicationDeploymentJob.php | 1 + bootstrap/helpers/docker.php | 5 +++++ bootstrap/helpers/shared.php | 2 ++ 3 files changed, 8 insertions(+) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 21c7e4820..530136378 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -19,6 +19,7 @@ use App\Notifications\Application\DeploymentFailed; use App\Notifications\Application\DeploymentSuccess; use App\Traits\ExecuteRemoteCommand; use Carbon\Carbon; +use Exception; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeEncrypted; use Illuminate\Contracts\Queue\ShouldQueue; diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index ebbdcd5da..b8dfd023a 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -604,6 +604,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); $proxyLabels = fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, @@ -659,6 +660,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() ); + $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); $proxyLabels = fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, @@ -671,6 +673,9 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); } } + $labels = $labels->map(function ($value, $key) { + return "$key=$value"; + })->values(); return $labels->all(); } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index c3d7d0bfc..d4fce18bd 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -2045,6 +2045,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal service_name: $serviceName, image: data_get($service, 'image') ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); $proxyLabels = fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, @@ -2818,6 +2819,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_gzip_enabled: $resource->isGzipEnabled(), is_stripprefix_enabled: $resource->isStripprefixEnabled(), ); + $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); $proxyLabels = fqdnLabelsForCaddy( network: $resource->destination->network, From 98f892402035b1347186efd74b2c7bc2f81ab1db Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 28 Feb 2025 11:50:24 +0000 Subject: [PATCH 50/99] docs: update changelog --- CHANGELOG.md | 77 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed72adb84..6dd334f5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,15 +6,35 @@ All notable changes to this project will be documented in this file. ### 🚀 Features -- *(core)* Prevent using servers with existing resources as build servers -- *(ui)* Add textarea switching option in service compose editor +- *(ui)* Add wire:key to two-step confirmation settings +- *(database)* Add index to scheduled task executions for improved query performance +- *(database)* Add index to scheduled database backup executions ### 🐛 Bug Fixes -- *(service)* Update Fider service template healthcheck command -- *(core)* Improve server selection error handling in Docker component -- *(core)* Add server functionality check before dispatching container status -- *(ui)* Disable sticky scroll in Monaco editor +- *(core)* Production dockerfile +- *(ui)* Update storage configuration guidance link +- *(ui)* Set default SMTP encryption to starttls +- *(notifications)* Correct environment URL path in application notifications +- *(config)* Update default PostgreSQL host to coolify-db instead of postgres +- *(docker)* Improve Docker compose file validation process +- *(ui)* Restrict service retrieval to current team +- *(core)* Only validate custom compose files +- *(mail)* Set default mailer to array when not specified +- *(ui)* Correct redirect routes after task deletion +- *(core)* Adding a new server should not try to make the default docker network +- *(core)* Clean up unnecessary files during application image build +- *(core)* Improve label generation and merging for applications and services + +### 💼 Other + +- Bump all dependencies (#5216) + +### 🚜 Refactor + +- *(ui)* Simplify file storage modal confirmations +- *(notifications)* Improve transactional email settings handling +- *(scheduled-tasks)* Improve scheduled task creation and management ### 📚 Documentation @@ -22,42 +42,34 @@ All notable changes to this project will be documented in this file. ### ⚙️ Miscellaneous Tasks -- Bump Coolify version to 4.0.0-beta.395 +- Bump helper and realtime version + +## [4.0.0-beta.395] - 2025-02-22 + +### 📚 Documentation + +- Update changelog ## [4.0.0-beta.394] - 2025-02-17 -### 🐛 Bug Fixes - -- *(core)* Update service status refresh event handling -- *(ui)* Adjust polling intervals for database and service status checks - ### 📚 Documentation - Update changelog -### ⚙️ Miscellaneous Tasks - -- Bump Coolify version to 4.0.0-beta.394 - ## [4.0.0-beta.393] - 2025-02-15 -### 🚀 Features - -- *(core)* Add error logging and cron parsing to docker/server schedules - ### 📚 Documentation - Update changelog -### ⚙️ Miscellaneous Tasks - -- Bump Coolify version to 4.0.0-beta.393 - ## [4.0.0-beta.392] - 2025-02-13 ### 🚀 Features - *(ui)* Add top padding to pricing plans view +- *(core)* Add error logging and cron parsing to docker/server schedules +- *(core)* Prevent using servers with existing resources as build servers +- *(ui)* Add textarea switching option in service compose editor ### 🐛 Bug Fixes @@ -66,6 +78,16 @@ All notable changes to this project will be documented in this file. - *(deployment)* Improve log line rendering and formatting - *(s3-storage)* Optimize team admin notification query - *(core)* Improve connection testing with dynamic disk configuration for s3 backups +- *(core)* Update service status refresh event handling +- *(ui)* Adjust polling intervals for database and service status checks +- *(service)* Update Fider service template healthcheck command +- *(core)* Improve server selection error handling in Docker component +- *(core)* Add server functionality check before dispatching container status +- *(ui)* Disable sticky scroll in Monaco editor +- *(ui)* Add literal and multiline env support to services. +- *(services)* Owncloud docs link +- *(template)* Remove db-migration step from `infisical.yaml` (#5209) +- *(service)* Penpot (#5047) ### 🚜 Refactor @@ -79,6 +101,13 @@ All notable changes to this project will be documented in this file. ### ⚙️ Miscellaneous Tasks - Rollback Coolify version to 4.0.0-beta.392 +- Bump Coolify version to 4.0.0-beta.393 +- Bump Coolify version to 4.0.0-beta.394 +- Bump Coolify version to 4.0.0-beta.395 +- Bump Coolify version to 4.0.0-beta.396 +- *(services)* Update zipline to use new Database env var. (#5210) +- *(service)* Upgrade authentik service +- *(service)* Remove unused env from zipline ## [4.0.0-beta.391] - 2025-02-04 From 8292961a6ca7e4e272312e4a751bde5bd858c4e5 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 28 Feb 2025 13:41:17 +0100 Subject: [PATCH 51/99] version++ --- config/constants.php | 2 +- other/nightly/docker-compose.prod.yml | 2 +- other/nightly/versions.json | 4 ++-- versions.json | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config/constants.php b/config/constants.php index ffd870c7d..e7505de2e 100644 --- a/config/constants.php +++ b/config/constants.php @@ -2,7 +2,7 @@ return [ 'coolify' => [ - 'version' => '4.0.0-beta.396', + 'version' => '4.0.0-beta.397', 'helper_version' => '1.0.7', 'realtime_version' => '1.0.6', 'self_hosted' => env('SELF_HOSTED', true), diff --git a/other/nightly/docker-compose.prod.yml b/other/nightly/docker-compose.prod.yml index 2e46438bd..23a65cca6 100644 --- a/other/nightly/docker-compose.prod.yml +++ b/other/nightly/docker-compose.prod.yml @@ -61,7 +61,7 @@ services: retries: 10 timeout: 2s soketi: - image: 'ghcr.io/coollabsio/coolify-realtime:1.0.5' + image: 'ghcr.io/coollabsio/coolify-realtime:1.0.6' ports: - "${SOKETI_PORT:-6001}:6001" - "6002:6002" diff --git a/other/nightly/versions.json b/other/nightly/versions.json index fa0e454d7..8d1c91433 100644 --- a/other/nightly/versions.json +++ b/other/nightly/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.382" + "version": "4.0.0-beta.397" }, "nightly": { - "version": "4.0.0-beta.383" + "version": "4.0.0-beta.398" }, "helper": { "version": "1.0.7" diff --git a/versions.json b/versions.json index eb8e5c923..8d1c91433 100644 --- a/versions.json +++ b/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.396" + "version": "4.0.0-beta.397" }, "nightly": { - "version": "4.0.0-beta.397" + "version": "4.0.0-beta.398" }, "helper": { "version": "1.0.7" From 5ac43fd426925c3b877d12312edf7daee3eff1a8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 28 Feb 2025 14:41:54 +0100 Subject: [PATCH 52/99] fix(billing): Handle 'past_due' subscription status in Stripe processing --- app/Jobs/StripeProcessJob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Jobs/StripeProcessJob.php b/app/Jobs/StripeProcessJob.php index d61c738f4..803029772 100644 --- a/app/Jobs/StripeProcessJob.php +++ b/app/Jobs/StripeProcessJob.php @@ -217,7 +217,7 @@ class StripeProcessJob implements ShouldQueue 'stripe_plan_id' => $planId, 'stripe_cancel_at_period_end' => $cancelAtPeriodEnd, ]); - if ($status === 'paused' || $status === 'incomplete_expired') { + if ($status === 'paused' || $status === 'incomplete_expired' || $status === 'past_due') { if ($subscription->stripe_subscription_id === $subscriptionId) { $subscription->update([ 'stripe_invoice_paid' => false, From a402c28606d639b6f7d284447a3dc5a73182124e Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 28 Feb 2025 20:25:19 +0100 Subject: [PATCH 53/99] fix(revert): label parsing --- bootstrap/helpers/docker.php | 43 +++++-------- bootstrap/helpers/shared.php | 118 ++++++++++++++++------------------- 2 files changed, 69 insertions(+), 92 deletions(-) diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index b8dfd023a..80e19d80f 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -569,7 +569,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview if ($shouldGenerateLabelsExactly) { switch ($application->destination->server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $proxyLabels = fqdnLabelsForTraefik( + $labels = $labels->merge(fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, @@ -577,11 +577,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - ); - $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); + )); break; case ProxyTypes::CADDY->value: - $proxyLabels = fqdnLabelsForCaddy( + $labels = $labels->merge(fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -590,12 +589,11 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - ); - $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); + )); break; } } else { - $proxyLabels = fqdnLabelsForTraefik( + $labels = $labels->merge(fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, @@ -603,9 +601,8 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - ); - $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); - $proxyLabels = fqdnLabelsForCaddy( + )); + $labels = $labels->merge(fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -614,8 +611,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled(), redirect_direction: $application->redirect - ); - $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); + )); } } } else { @@ -628,18 +624,17 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview if ($shouldGenerateLabelsExactly) { switch ($application->destination->server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $proxyLabels = fqdnLabelsForTraefik( + $labels = $labels->merge(fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - ); - $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); + )); break; case ProxyTypes::CADDY->value: - $proxyLabels = fqdnLabelsForCaddy( + $labels = $labels->merge(fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -647,21 +642,19 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - ); - $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); + )); break; } } else { - $proxyLabels = fqdnLabelsForTraefik( + $labels = $labels->merge(fqdnLabelsForTraefik( uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - ); - $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); - $proxyLabels = fqdnLabelsForCaddy( + )); + $labels = $labels->merge(fqdnLabelsForCaddy( network: $application->destination->network, uuid: $appUuid, domains: $domains, @@ -669,13 +662,9 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview is_force_https_enabled: $application->isForceHttpsEnabled(), is_gzip_enabled: $application->isGzipEnabled(), is_stripprefix_enabled: $application->isStripprefixEnabled() - ); - $labels = $labels->merge(convertToKeyValueCollection($proxyLabels)); + )); } } - $labels = $labels->map(function ($value, $key) { - return "$key=$value"; - })->values(); return $labels->all(); } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index d4fce18bd..1e9089348 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1476,7 +1476,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceNetworks = collect(data_get($service, 'networks', [])); $serviceVariables = collect(data_get($service, 'environment', [])); $serviceLabels = collect(data_get($service, 'labels', [])); - $serviceLabels = convertToKeyValueCollection($serviceLabels); $hasHostNetworkMode = data_get($service, 'network_mode') === 'host' ? true : false; if ($serviceLabels->count() > 0) { $removedLabels = collect([]); @@ -2005,7 +2004,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if ($shouldGenerateLabelsExactly) { switch ($resource->server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $proxyLabels = fqdnLabelsForTraefik( + $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( uuid: $resource->uuid, domains: $fqdns, is_force_https_enabled: true, @@ -2014,12 +2013,10 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - ); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); - + )); break; case ProxyTypes::CADDY->value: - $proxyLabels = fqdnLabelsForCaddy( + $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, domains: $fqdns, @@ -2029,13 +2026,11 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - ); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); - + )); break; } } else { - $proxyLabels = fqdnLabelsForTraefik( + $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( uuid: $resource->uuid, domains: $fqdns, is_force_https_enabled: true, @@ -2044,9 +2039,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - ); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); - $proxyLabels = fqdnLabelsForCaddy( + )); + $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, domains: $fqdns, @@ -2056,8 +2050,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') - ); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + )); } } } @@ -2206,7 +2199,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceVariables = collect(data_get($service, 'environment', [])); $serviceDependencies = collect(data_get($service, 'depends_on', [])); $serviceLabels = collect(data_get($service, 'labels', [])); - $serviceLabels = convertToKeyValueCollection($serviceLabels); $serviceBuildVariables = collect(data_get($service, 'build.args', [])); $serviceVariables = $serviceVariables->merge($serviceBuildVariables); if ($serviceLabels->count() > 0) { @@ -2780,47 +2772,48 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if ($shouldGenerateLabelsExactly) { switch ($server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $proxyLabels = fqdnLabelsForTraefik( - uuid: $resource->uuid, - domains: $fqdns, - serviceLabels: $serviceLabels, - generate_unique_uuid: $resource->build_pack === 'dockercompose', - image: data_get($service, 'image'), - is_force_https_enabled: $resource->isForceHttpsEnabled(), - is_gzip_enabled: $resource->isGzipEnabled(), - is_stripprefix_enabled: $resource->isStripprefixEnabled(), + $serviceLabels = $serviceLabels->merge( + fqdnLabelsForTraefik( + uuid: $resource->uuid, + domains: $fqdns, + serviceLabels: $serviceLabels, + generate_unique_uuid: $resource->build_pack === 'dockercompose', + image: data_get($service, 'image'), + is_force_https_enabled: $resource->isForceHttpsEnabled(), + is_gzip_enabled: $resource->isGzipEnabled(), + is_stripprefix_enabled: $resource->isStripprefixEnabled(), + ) ); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); - break; case ProxyTypes::CADDY->value: - $proxyLabels = fqdnLabelsForCaddy( - network: $resource->destination->network, - uuid: $resource->uuid, - domains: $fqdns, - serviceLabels: $serviceLabels, - image: data_get($service, 'image'), - is_force_https_enabled: $resource->isForceHttpsEnabled(), - is_gzip_enabled: $resource->isGzipEnabled(), - is_stripprefix_enabled: $resource->isStripprefixEnabled(), + $serviceLabels = $serviceLabels->merge( + fqdnLabelsForCaddy( + network: $resource->destination->network, + uuid: $resource->uuid, + domains: $fqdns, + serviceLabels: $serviceLabels, + image: data_get($service, 'image'), + is_force_https_enabled: $resource->isForceHttpsEnabled(), + is_gzip_enabled: $resource->isGzipEnabled(), + is_stripprefix_enabled: $resource->isStripprefixEnabled(), + ) ); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); - break; } } else { - $proxyLabels = fqdnLabelsForTraefik( - uuid: $resource->uuid, - domains: $fqdns, - serviceLabels: $serviceLabels, - generate_unique_uuid: $resource->build_pack === 'dockercompose', - image: data_get($service, 'image'), - is_force_https_enabled: $resource->isForceHttpsEnabled(), - is_gzip_enabled: $resource->isGzipEnabled(), - is_stripprefix_enabled: $resource->isStripprefixEnabled(), + $serviceLabels = $serviceLabels->merge( + fqdnLabelsForTraefik( + uuid: $resource->uuid, + domains: $fqdns, + serviceLabels: $serviceLabels, + generate_unique_uuid: $resource->build_pack === 'dockercompose', + image: data_get($service, 'image'), + is_force_https_enabled: $resource->isForceHttpsEnabled(), + is_gzip_enabled: $resource->isGzipEnabled(), + is_stripprefix_enabled: $resource->isStripprefixEnabled(), + ) ); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); - $proxyLabels = + $serviceLabels = $serviceLabels->merge( fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, @@ -2830,8 +2823,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal is_force_https_enabled: $resource->isForceHttpsEnabled(), is_gzip_enabled: $resource->isGzipEnabled(), is_stripprefix_enabled: $resource->isStripprefixEnabled(), - ); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + ) + ); } } } @@ -2846,7 +2839,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal pull_request_id: $pull_request_id, type: 'application' ); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($defaultLabels)); + $serviceLabels = $serviceLabels->merge($defaultLabels); if ($server->isLogDrainEnabled()) { if ($resource instanceof Application && $resource->isLogDrainEnabled()) { @@ -3186,7 +3179,6 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $use_network_mode = data_get($service, 'network_mode') !== null; $depends_on = collect(data_get($service, 'depends_on', [])); $labels = collect(data_get($service, 'labels', [])); - $labels = convertToKeyValueCollection($labels); $environment = collect(data_get($service, 'environment', [])); $ports = collect(data_get($service, 'ports', [])); $buildArgs = collect(data_get($service, 'build.args', [])); @@ -3699,7 +3691,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int return $value; }); } - $serviceLabels = $labels->merge(convertToKeyValueCollection($defaultLabels)); + $serviceLabels = $labels->merge($defaultLabels); if ($serviceLabels->count() > 0) { if ($isApplication) { $isContainerLabelEscapeEnabled = data_get($resource, 'settings.is_container_label_escape_enabled'); @@ -3731,7 +3723,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int if ($shouldGenerateLabelsExactly) { switch ($server->proxyType()) { case ProxyTypes::TRAEFIK->value: - $proxyLabels = fqdnLabelsForTraefik( + $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( uuid: $uuid, domains: $fqdns, is_force_https_enabled: true, @@ -3740,11 +3732,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image - ); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); + )); break; case ProxyTypes::CADDY->value: - $proxyLabels = fqdnLabelsForCaddy( + $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( network: $network, uuid: $uuid, domains: $fqdns, @@ -3755,13 +3746,11 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int service_name: $serviceName, image: $image, predefinedPort: $predefinedPort - ); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); - + )); break; } } else { - $proxyLabels = fqdnLabelsForTraefik( + $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( uuid: $uuid, domains: $fqdns, is_force_https_enabled: true, @@ -3770,8 +3759,8 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image - ); - $proxyLabels = $proxyLabels->merge(fqdnLabelsForCaddy( + )); + $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( network: $network, uuid: $uuid, domains: $fqdns, @@ -3783,7 +3772,6 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int image: $image, predefinedPort: $predefinedPort )); - $serviceLabels = $serviceLabels->merge(convertToKeyValueCollection($proxyLabels)); } } if ($isService) { From f1b98f5ce9f22d24159fbefbac7089ede46e9444 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 28 Feb 2025 20:28:35 +0100 Subject: [PATCH 54/99] fix(helpers): Initialize command variable in parseCommandFromMagicEnvVariable --- bootstrap/helpers/shared.php | 1 + 1 file changed, 1 insertion(+) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 1e9089348..17ddcbda0 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -748,6 +748,7 @@ function parseCommandFromMagicEnvVariable(Str|string $key): Stringable { $value = str($key); $count = substr_count($value->value(), '_'); + $command = null; if ($count === 2) { if ($value->startsWith('SERVICE_FQDN') || $value->startsWith('SERVICE_URL')) { // SERVICE_FQDN_UMAMI From 717f0f228b3030070023cf333e1ce61868f30793 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 28 Feb 2025 19:29:19 +0000 Subject: [PATCH 55/99] docs: update changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dd334f5b..e2f1b1486 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. ## [unreleased] +### 🐛 Bug Fixes + +- *(billing)* Handle 'past_due' subscription status in Stripe processing +- *(revert)* Label parsing +- *(helpers)* Initialize command variable in parseCommandFromMagicEnvVariable + +## [4.0.0-beta.396] - 2025-02-28 + ### 🚀 Features - *(ui)* Add wire:key to two-step confirmation settings @@ -38,6 +46,7 @@ All notable changes to this project will be documented in this file. ### 📚 Documentation +- Update changelog - Update changelog ### ⚙️ Miscellaneous Tasks From ebcc6508af001b001c213c55dd4f162fa42511d3 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 1 Mar 2025 12:10:20 +0100 Subject: [PATCH 56/99] version: Bump Coolify to 4.0.0-beta.398 --- config/constants.php | 2 +- versions.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/constants.php b/config/constants.php index e7505de2e..8a515fa13 100644 --- a/config/constants.php +++ b/config/constants.php @@ -2,7 +2,7 @@ return [ 'coolify' => [ - 'version' => '4.0.0-beta.397', + 'version' => '4.0.0-beta.398', 'helper_version' => '1.0.7', 'realtime_version' => '1.0.6', 'self_hosted' => env('SELF_HOSTED', true), diff --git a/versions.json b/versions.json index 8d1c91433..c9fb62130 100644 --- a/versions.json +++ b/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.397" + "version": "4.0.0-beta.398" }, "nightly": { - "version": "4.0.0-beta.398" + "version": "4.0.0-beta.399" }, "helper": { "version": "1.0.7" From 31698032595dd94c838b1e3dc92423bcb25cc78e Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 1 Mar 2025 12:10:28 +0100 Subject: [PATCH 57/99] fix(billing): Restrict Stripe subscription status update to 'active' only --- app/Console/Commands/CloudCleanupSubscriptions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Console/Commands/CloudCleanupSubscriptions.php b/app/Console/Commands/CloudCleanupSubscriptions.php index 9dc6e24f5..ab676c927 100644 --- a/app/Console/Commands/CloudCleanupSubscriptions.php +++ b/app/Console/Commands/CloudCleanupSubscriptions.php @@ -50,7 +50,7 @@ class CloudCleanupSubscriptions extends Command } else { $subscription = $stripe->subscriptions->retrieve(data_get($team, 'subscription.stripe_subscription_id'), []); $status = data_get($subscription, 'status'); - if ($status === 'active' || $status === 'past_due') { + if ($status === 'active') { $team->subscription->update([ 'stripe_invoice_paid' => true, 'stripe_trial_already_ended' => false, From 07cbec7ddc7f251e32d456fe6d816376c3d7189c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 1 Mar 2025 12:43:12 +0100 Subject: [PATCH 58/99] feat(billing): Add Stripe past due subscription status tracking --- app/Models/Team.php | 10 +++++++ .../2025_03_01_112617_add_stripe_past_due.php | 28 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 database/migrations/2025_03_01_112617_add_stripe_past_due.php diff --git a/app/Models/Team.php b/app/Models/Team.php index 467cf45bc..6796b22ad 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -93,6 +93,15 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen return $servers >= $serverLimit; } + public function subscriptionPastOverDue() + { + if (isCloud()) { + return $this->subscription?->stripe_past_due; + } + + return false; + } + public function serverOverflow() { if ($this->serverLimit() < $this->servers->count()) { @@ -185,6 +194,7 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen 'stripe_cancel_at_period_end' => false, 'stripe_invoice_paid' => false, 'stripe_trial_already_ended' => false, + 'stripe_past_due' => false, ]); foreach ($this->servers as $server) { $server->settings()->update([ diff --git a/database/migrations/2025_03_01_112617_add_stripe_past_due.php b/database/migrations/2025_03_01_112617_add_stripe_past_due.php new file mode 100644 index 000000000..6edb4f698 --- /dev/null +++ b/database/migrations/2025_03_01_112617_add_stripe_past_due.php @@ -0,0 +1,28 @@ +boolean('stripe_past_due')->default(false); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('subscriptions', function (Blueprint $table) { + $table->dropColumn('stripe_past_due'); + }); + } +}; From 1909865a33c4bb862ea8c284243384e86e9ac43b Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 1 Mar 2025 12:43:21 +0100 Subject: [PATCH 59/99] refactor(billing): Enhance Stripe subscription status handling and notifications --- app/Jobs/StripeProcessJob.php | 43 +++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/app/Jobs/StripeProcessJob.php b/app/Jobs/StripeProcessJob.php index 803029772..f1c5bc1a8 100644 --- a/app/Jobs/StripeProcessJob.php +++ b/app/Jobs/StripeProcessJob.php @@ -73,19 +73,21 @@ class StripeProcessJob implements ShouldQueue } $subscription = Subscription::where('team_id', $teamId)->first(); if ($subscription) { - send_internal_notification('Old subscription activated for team: '.$teamId); + // send_internal_notification('Old subscription activated for team: '.$teamId); $subscription->update([ 'stripe_subscription_id' => $subscriptionId, 'stripe_customer_id' => $customerId, 'stripe_invoice_paid' => true, + 'stripe_past_due' => false, ]); } else { - send_internal_notification('New subscription for team: '.$teamId); + // send_internal_notification('New subscription for team: '.$teamId); Subscription::create([ 'team_id' => $teamId, 'stripe_subscription_id' => $subscriptionId, 'stripe_customer_id' => $customerId, 'stripe_invoice_paid' => true, + 'stripe_past_due' => false, ]); } break; @@ -100,6 +102,7 @@ class StripeProcessJob implements ShouldQueue if ($subscription) { $subscription->update([ 'stripe_invoice_paid' => true, + 'stripe_past_due' => false, ]); } else { throw new \RuntimeException("No subscription found for customer: {$customerId}"); @@ -119,9 +122,7 @@ class StripeProcessJob implements ShouldQueue } if (! $subscription->stripe_invoice_paid) { SubscriptionInvoiceFailedJob::dispatch($team); - send_internal_notification('Invoice payment failed: '.$customerId); - } else { - send_internal_notification('Invoice payment failed but already paid: '.$customerId); + // send_internal_notification('Invoice payment failed: '.$customerId); } break; case 'payment_intent.payment_failed': @@ -136,7 +137,7 @@ class StripeProcessJob implements ShouldQueue return; } - send_internal_notification('Subscription payment failed for customer: '.$customerId); + // send_internal_notification('Subscription payment failed for customer: '.$customerId); break; case 'customer.subscription.created': $customerId = data_get($data, 'customer'); @@ -158,7 +159,7 @@ class StripeProcessJob implements ShouldQueue } $subscription = Subscription::where('team_id', $teamId)->first(); if ($subscription) { - send_internal_notification("Subscription already exists for team: {$teamId}"); + // send_internal_notification("Subscription already exists for team: {$teamId}"); throw new \RuntimeException("Subscription already exists for team: {$teamId}"); } else { Subscription::create([ @@ -182,7 +183,7 @@ class StripeProcessJob implements ShouldQueue $subscription = Subscription::where('stripe_customer_id', $customerId)->first(); if (! $subscription) { if ($status === 'incomplete_expired') { - send_internal_notification('Subscription incomplete expired'); + // send_internal_notification('Subscription incomplete expired'); throw new \RuntimeException('Subscription incomplete expired'); } if ($teamId) { @@ -217,16 +218,40 @@ class StripeProcessJob implements ShouldQueue 'stripe_plan_id' => $planId, 'stripe_cancel_at_period_end' => $cancelAtPeriodEnd, ]); - if ($status === 'paused' || $status === 'incomplete_expired' || $status === 'past_due') { + if ($status === 'paused' || $status === 'incomplete_expired') { if ($subscription->stripe_subscription_id === $subscriptionId) { $subscription->update([ 'stripe_invoice_paid' => false, ]); } } + if ($status === 'past_due') { + if ($subscription->stripe_subscription_id === $subscriptionId) { + $subscription->update([ + 'stripe_past_due' => true, + ]); + send_internal_notification('Past Due: '.$customerId.'Subscription ID: '.$subscriptionId); + } + } + if ($status === 'unpaid') { + if ($subscription->stripe_subscription_id === $subscriptionId) { + $subscription->update([ + 'stripe_invoice_paid' => false, + ]); + send_internal_notification('Unpaid: '.$customerId.'Subscription ID: '.$subscriptionId); + } + $team = data_get($subscription, 'team'); + if ($team) { + $team->subscriptionEnded(); + } else { + send_internal_notification('Subscription unpaid but no team found in Coolify for customer: '.$customerId); + throw new \RuntimeException("No team found in Coolify for customer: {$customerId}"); + } + } if ($status === 'active') { if ($subscription->stripe_subscription_id === $subscriptionId) { $subscription->update([ + 'stripe_past_due' => false, 'stripe_invoice_paid' => true, ]); } From c30568855488860a0301be5381f34e7fb1ed33ea Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 1 Mar 2025 12:43:29 +0100 Subject: [PATCH 60/99] feat(ui): Add past due subscription warning banner --- resources/views/livewire/layout-popups.blade.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/resources/views/livewire/layout-popups.blade.php b/resources/views/livewire/layout-popups.blade.php index 53c8ab1d6..c639b4627 100644 --- a/resources/views/livewire/layout-popups.blade.php +++ b/resources/views/livewire/layout-popups.blade.php @@ -79,6 +79,16 @@ + @if (currentTeam()->subscriptionPastOverDue()) + +
WARNING: Your subscription is in over-due. If your latest + payment is not paid within a week, all automations will + be deactivated. Visit /subscription to check your subscription status or pay your + invoice (or check your email for the invoice). +
+
+ @endif @if (currentTeam()->serverOverflow())
WARNING: The number of active servers exceeds the limit From f28eefe603fab5becabd8821746304fa622b5802 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 1 Mar 2025 11:49:40 +0000 Subject: [PATCH 61/99] docs: update changelog --- CHANGELOG.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2f1b1486..fa6a28264 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,35 @@ All notable changes to this project will be documented in this file. ## [unreleased] +### 🚀 Features + +- *(billing)* Add Stripe past due subscription status tracking +- *(ui)* Add past due subscription warning banner + +### 🐛 Bug Fixes + +- *(billing)* Restrict Stripe subscription status update to 'active' only + +### 💼 Other + +- Bump Coolify to 4.0.0-beta.398 + +### 🚜 Refactor + +- *(billing)* Enhance Stripe subscription status handling and notifications + +## [4.0.0-beta.397] - 2025-02-28 + ### 🐛 Bug Fixes - *(billing)* Handle 'past_due' subscription status in Stripe processing - *(revert)* Label parsing - *(helpers)* Initialize command variable in parseCommandFromMagicEnvVariable +### 📚 Documentation + +- Update changelog + ## [4.0.0-beta.396] - 2025-02-28 ### 🚀 Features From e3b419257d1b5733ead1204647ea08d335f3f767 Mon Sep 17 00:00:00 2001 From: think <31487797+ThinkFar@users.noreply.github.com> Date: Sun, 2 Mar 2025 22:23:02 -0700 Subject: [PATCH 62/99] fix(ui): Correct grammatical error in 404 page --- resources/views/errors/404.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/errors/404.blade.php b/resources/views/errors/404.blade.php index 3b84bafd8..569488d19 100644 --- a/resources/views/errors/404.blade.php +++ b/resources/views/errors/404.blade.php @@ -2,7 +2,7 @@

404

-

How did you got here?

+

How did you get here?

Sorry, we couldn’t find the page you’re looking for.

From 1ef84f973634cecf3b619b4706adb39c1e1dd1d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 23:47:08 +0000 Subject: [PATCH 63/99] chore(deps): bump laravel/framework from 11.44.0 to 11.44.1 Bumps [laravel/framework](https://github.com/laravel/framework) from 11.44.0 to 11.44.1. - [Release notes](https://github.com/laravel/framework/releases) - [Changelog](https://github.com/laravel/framework/blob/12.x/CHANGELOG.md) - [Commits](https://github.com/laravel/framework/compare/v11.44.0...v11.44.1) --- updated-dependencies: - dependency-name: laravel/framework dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- composer.lock | 145 +++++++++++++++++++++++--------------------------- 1 file changed, 66 insertions(+), 79 deletions(-) diff --git a/composer.lock b/composer.lock index 65271cb1a..d070b919f 100644 --- a/composer.lock +++ b/composer.lock @@ -1079,16 +1079,16 @@ }, { "name": "brick/math", - "version": "0.12.1", + "version": "0.12.3", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "f510c0a40911935b77b86859eb5223d58d660df1" + "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", - "reference": "f510c0a40911935b77b86859eb5223d58d660df1", + "url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba", + "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba", "shasum": "" }, "require": { @@ -1097,7 +1097,7 @@ "require-dev": { "php-coveralls/php-coveralls": "^2.2", "phpunit/phpunit": "^10.1", - "vimeo/psalm": "5.16.0" + "vimeo/psalm": "6.8.8" }, "type": "library", "autoload": { @@ -1127,7 +1127,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.12.1" + "source": "https://github.com/brick/math/tree/0.12.3" }, "funding": [ { @@ -1135,7 +1135,7 @@ "type": "github" } ], - "time": "2023-11-29T23:19:16+00:00" + "time": "2025-02-28T13:11:00+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -2732,16 +2732,16 @@ }, { "name": "laravel/framework", - "version": "v11.44.0", + "version": "v11.44.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "e9a33da34815ac1ed46c7e4c477a775f4592f0a7" + "reference": "0883d4175f4e2b5c299e7087ad3c74f2ce195c6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/e9a33da34815ac1ed46c7e4c477a775f4592f0a7", - "reference": "e9a33da34815ac1ed46c7e4c477a775f4592f0a7", + "url": "https://api.github.com/repos/laravel/framework/zipball/0883d4175f4e2b5c299e7087ad3c74f2ce195c6d", + "reference": "0883d4175f4e2b5c299e7087ad3c74f2ce195c6d", "shasum": "" }, "require": { @@ -2849,7 +2849,7 @@ "league/flysystem-read-only": "^3.25.1", "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", - "orchestra/testbench-core": "^9.9.4", + "orchestra/testbench-core": "^9.11.2", "pda/pheanstalk": "^5.0.6", "php-http/discovery": "^1.15", "phpstan/phpstan": "^2.0", @@ -2943,7 +2943,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-02-24T13:08:54+00:00" + "time": "2025-03-05T15:34:10+00:00" }, { "name": "laravel/horizon", @@ -6944,16 +6944,16 @@ }, { "name": "ramsey/collection", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" + "reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", - "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "url": "https://api.github.com/repos/ramsey/collection/zipball/3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109", + "reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109", "shasum": "" }, "require": { @@ -6961,25 +6961,22 @@ }, "require-dev": { "captainhook/plugin-composer": "^5.3", - "ergebnis/composer-normalize": "^2.28.3", - "fakerphp/faker": "^1.21", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", "hamcrest/hamcrest-php": "^2.0", - "jangregor/phpstan-prophecy": "^1.0", - "mockery/mockery": "^1.5", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpcsstandards/phpcsutils": "^1.0.0-rc1", - "phpspec/prophecy-phpunit": "^2.0", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5", - "psalm/plugin-mockery": "^1.1", - "psalm/plugin-phpunit": "^0.18.4", - "ramsey/coding-standard": "^2.0.3", - "ramsey/conventional-commits": "^1.3", - "vimeo/psalm": "^5.4" + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" }, "type": "library", "extra": { @@ -7017,19 +7014,9 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/2.0.0" + "source": "https://github.com/ramsey/collection/tree/2.1.0" }, - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", - "type": "tidelift" - } - ], - "time": "2022-12-31T21:50:55+00:00" + "time": "2025-03-02T04:48:29+00:00" }, { "name": "ramsey/uuid", @@ -8887,16 +8874,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.2.3", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "959a74d044a6db21f4caa6d695648dcb5584cb49" + "reference": "aabf79938aa795350c07ce6464dd1985607d95d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/959a74d044a6db21f4caa6d695648dcb5584cb49", - "reference": "959a74d044a6db21f4caa6d695648dcb5584cb49", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/aabf79938aa795350c07ce6464dd1985607d95d5", + "reference": "aabf79938aa795350c07ce6464dd1985607d95d5", "shasum": "" }, "require": { @@ -8942,7 +8929,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.2.3" + "source": "https://github.com/symfony/error-handler/tree/v7.2.4" }, "funding": [ { @@ -8958,7 +8945,7 @@ "type": "tidelift" } ], - "time": "2025-01-07T09:39:55+00:00" + "time": "2025-02-02T20:27:07+00:00" }, { "name": "symfony/event-dispatcher", @@ -9260,16 +9247,16 @@ }, { "name": "symfony/http-kernel", - "version": "v7.2.3", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "caae9807f8e25a9b43ce8cc6fafab6cf91f0cc9b" + "reference": "9f1103734c5789798fefb90e91de4586039003ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/caae9807f8e25a9b43ce8cc6fafab6cf91f0cc9b", - "reference": "caae9807f8e25a9b43ce8cc6fafab6cf91f0cc9b", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/9f1103734c5789798fefb90e91de4586039003ed", + "reference": "9f1103734c5789798fefb90e91de4586039003ed", "shasum": "" }, "require": { @@ -9354,7 +9341,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.3" + "source": "https://github.com/symfony/http-kernel/tree/v7.2.4" }, "funding": [ { @@ -9370,7 +9357,7 @@ "type": "tidelift" } ], - "time": "2025-01-29T07:40:13+00:00" + "time": "2025-02-26T11:01:22+00:00" }, { "name": "symfony/mailer", @@ -9454,16 +9441,16 @@ }, { "name": "symfony/mime", - "version": "v7.2.3", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "2fc3b4bd67e4747e45195bc4c98bea4628476204" + "reference": "87ca22046b78c3feaff04b337f33b38510fd686b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/2fc3b4bd67e4747e45195bc4c98bea4628476204", - "reference": "2fc3b4bd67e4747e45195bc4c98bea4628476204", + "url": "https://api.github.com/repos/symfony/mime/zipball/87ca22046b78c3feaff04b337f33b38510fd686b", + "reference": "87ca22046b78c3feaff04b337f33b38510fd686b", "shasum": "" }, "require": { @@ -9518,7 +9505,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.2.3" + "source": "https://github.com/symfony/mime/tree/v7.2.4" }, "funding": [ { @@ -9534,7 +9521,7 @@ "type": "tidelift" } ], - "time": "2025-01-27T11:08:17+00:00" + "time": "2025-02-19T08:51:20+00:00" }, { "name": "symfony/options-resolver", @@ -10321,16 +10308,16 @@ }, { "name": "symfony/process", - "version": "v7.2.0", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" + "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", - "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "url": "https://api.github.com/repos/symfony/process/zipball/d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf", + "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf", "shasum": "" }, "require": { @@ -10362,7 +10349,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.2.0" + "source": "https://github.com/symfony/process/tree/v7.2.4" }, "funding": [ { @@ -10378,7 +10365,7 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:24:19+00:00" + "time": "2025-02-05T08:33:46+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -10778,16 +10765,16 @@ }, { "name": "symfony/translation", - "version": "v7.2.2", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "e2674a30132b7cc4d74540d6c2573aa363f05923" + "reference": "283856e6981286cc0d800b53bd5703e8e363f05a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/e2674a30132b7cc4d74540d6c2573aa363f05923", - "reference": "e2674a30132b7cc4d74540d6c2573aa363f05923", + "url": "https://api.github.com/repos/symfony/translation/zipball/283856e6981286cc0d800b53bd5703e8e363f05a", + "reference": "283856e6981286cc0d800b53bd5703e8e363f05a", "shasum": "" }, "require": { @@ -10853,7 +10840,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.2.2" + "source": "https://github.com/symfony/translation/tree/v7.2.4" }, "funding": [ { @@ -10869,7 +10856,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:18:10+00:00" + "time": "2025-02-13T10:27:23+00:00" }, { "name": "symfony/translation-contracts", @@ -15569,12 +15556,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.4" }, - "platform-dev": {}, - "plugin-api-version": "2.6.0" + "platform-dev": [], + "plugin-api-version": "2.3.0" } From 291e7d0a9cc0524cc83de690dd0a9969bf1c518c Mon Sep 17 00:00:00 2001 From: Manish Gupta <59428681+mguptahub@users.noreply.github.com> Date: Mon, 10 Mar 2025 11:04:28 +0530 Subject: [PATCH 64/99] updated version to v0.25.1 --- templates/compose/plane.yaml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/templates/compose/plane.yaml b/templates/compose/plane.yaml index c90e15a1a..f765015da 100644 --- a/templates/compose/plane.yaml +++ b/templates/compose/plane.yaml @@ -5,7 +5,7 @@ x-app-env: &app-env environment: - - APP_RELEASE=${APP_RELEASE:-v0.25.0} + - APP_RELEASE=${APP_RELEASE:-v0.25.1} - WEB_URL=${SERVICE_FQDN_PLANE} - DEBUG=${DEBUG:-0} - CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGIN:-http://localhost} @@ -55,7 +55,7 @@ services: - SERVICE_FQDN_PLANE - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880} - BUCKET_NAME=${BUCKET_NAME:-uploads} - image: makeplane/plane-proxy:${APP_RELEASE:-v0.25.0} + image: makeplane/plane-proxy:${APP_RELEASE:-v0.25.1} depends_on: - web - api @@ -67,7 +67,7 @@ services: retries: 15 web: - image: makeplane/plane-frontend:${APP_RELEASE:-v0.25.0} + image: makeplane/plane-frontend:${APP_RELEASE:-v0.25.1} command: node web/server.js web depends_on: - api @@ -78,7 +78,7 @@ services: timeout: 10s retries: 15 space: - image: makeplane/plane-space:${APP_RELEASE:-v0.25.0} + image: makeplane/plane-space:${APP_RELEASE:-v0.25.1} command: node space/server.js space depends_on: - api @@ -91,7 +91,7 @@ services: retries: 15 admin: - image: makeplane/plane-admin:${APP_RELEASE:-v0.25.0} + image: makeplane/plane-admin:${APP_RELEASE:-v0.25.1} command: node admin/server.js admin depends_on: - api @@ -104,7 +104,7 @@ services: live: <<: *app-env - image: makeplane/plane-live:${APP_RELEASE:-v0.25.0} + image: makeplane/plane-live:${APP_RELEASE:-v0.25.1} command: node live/dist/server.js live depends_on: - api @@ -117,7 +117,7 @@ services: api: <<: *app-env - image: makeplane/plane-backend:${APP_RELEASE:-v0.25.0} + image: makeplane/plane-backend:${APP_RELEASE:-v0.25.1} command: ./bin/docker-entrypoint-api.sh volumes: - logs_api:/code/plane/logs @@ -132,7 +132,7 @@ services: worker: <<: *app-env - image: makeplane/plane-backend:${APP_RELEASE:-v0.25.0} + image: makeplane/plane-backend:${APP_RELEASE:-v0.25.1} command: ./bin/docker-entrypoint-worker.sh volumes: - logs_worker:/code/plane/logs @@ -148,7 +148,7 @@ services: beat-worker: <<: *app-env - image: makeplane/plane-backend:${APP_RELEASE:-v0.25.0} + image: makeplane/plane-backend:${APP_RELEASE:-v0.25.1} command: ./bin/docker-entrypoint-beat.sh volumes: - logs_beat-worker:/code/plane/logs @@ -164,7 +164,7 @@ services: migrator: <<: *app-env - image: makeplane/plane-backend:${APP_RELEASE:-v0.25.0} + image: makeplane/plane-backend:${APP_RELEASE:-v0.25.1} restart: "no" command: ./bin/docker-entrypoint-migrator.sh volumes: From bc2e4a8049d6d61f9febf77fdba913806492baf1 Mon Sep 17 00:00:00 2001 From: Gergely Lonyai Date: Mon, 10 Mar 2025 10:58:52 +0100 Subject: [PATCH 65/99] Update install.sh --- scripts/install.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/install.sh b/scripts/install.sh index 1889ad355..2162c0bf4 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -336,13 +336,13 @@ if ! [ -x "$(command -v docker)" ]; then exit 1 fi ;; - "fedora") + "centos" | "fedora" | "rhel") if [ -x "$(command -v dnf5)" ]; then # dnf5 is available - dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/fedora/docker-ce.repo --overwrite >/dev/null 2>&1 + dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo --overwrite >/dev/null 2>&1 else # dnf5 is not available, use dnf - dnf config-manager --add-repo=https://download.docker.com/linux/fedora/docker-ce.repo >/dev/null 2>&1 + dnf config-manager --add-repo=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo >/dev/null 2>&1 fi dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 if ! [ -x "$(command -v docker)" ]; then From c9939a438bfec91c21b70d6cf9792eb6b49fd15f Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 10 Mar 2025 11:13:30 +0100 Subject: [PATCH 66/99] version: Bump Coolify to 4.0.0-beta.400 --- config/constants.php | 2 +- versions.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/constants.php b/config/constants.php index 8a515fa13..9d15da1da 100644 --- a/config/constants.php +++ b/config/constants.php @@ -2,7 +2,7 @@ return [ 'coolify' => [ - 'version' => '4.0.0-beta.398', + 'version' => '4.0.0-beta.399', 'helper_version' => '1.0.7', 'realtime_version' => '1.0.6', 'self_hosted' => env('SELF_HOSTED', true), diff --git a/versions.json b/versions.json index c9fb62130..2b75ca8d4 100644 --- a/versions.json +++ b/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.398" + "version": "4.0.0-beta.399" }, "nightly": { - "version": "4.0.0-beta.399" + "version": "4.0.0-beta.400" }, "helper": { "version": "1.0.7" From 96cf9abef8731d5077715ac7dafb1c0b617eaedf Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 10 Mar 2025 11:18:14 +0100 Subject: [PATCH 67/99] fix(api): docker compose based apps creationg through api --- .../Controllers/Api/ApplicationsController.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php index 4762a04b9..aef19af23 100644 --- a/app/Http/Controllers/Api/ApplicationsController.php +++ b/app/Http/Controllers/Api/ApplicationsController.php @@ -18,6 +18,7 @@ use App\Models\Service; use Illuminate\Http\Request; use Illuminate\Validation\Rule; use OpenApi\Attributes as OA; +use Spatie\Url\Url; use Symfony\Component\Yaml\Yaml; use Visus\Cuid2\Cuid2; @@ -811,6 +812,11 @@ class ApplicationsController extends Controller 'docker_compose_raw' => 'string|nullable', 'docker_compose_domains' => 'array|nullable', ]; + // ports_exposes is not required for dockercompose + if ($request->build_pack === 'dockercompose') { + $validationRules['ports_exposes'] = 'string'; + $request->offsetSet('ports_exposes', '80'); + } $validationRules = array_merge(sharedDataApplications(), $validationRules); $validator = customApiValidator($request->all(), $validationRules); if ($validator->fails()) { @@ -822,10 +828,6 @@ class ApplicationsController extends Controller if (! $request->has('name')) { $request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch)); } - if ($request->build_pack === 'dockercompose') { - $request->offsetSet('ports_exposes', '80'); - } - $return = $this->validateDataApplications($request, $server); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; @@ -848,7 +850,13 @@ class ApplicationsController extends Controller if ($dockerComposeDomainsJson->count() > 0) { $application->docker_compose_domains = $dockerComposeDomainsJson; } - + $repository_url_parsed = Url::fromString($request->git_repository); + $git_host = $repository_url_parsed->getHost(); + if ($git_host === 'github.com') { + $application->source_type = GithubApp::class; + $application->source_id = GithubApp::find(0)->id; + } + $application->git_repository = $repository_url_parsed->getSegment(1).'/'.$repository_url_parsed->getSegment(2); $application->fqdn = $fqdn; $application->destination_id = $destination->id; $application->destination_type = $destination->getMorphClass(); From c3d77e31b2d6cb0e470e891fd53046dcafe30409 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 10 Mar 2025 15:47:59 +0100 Subject: [PATCH 68/99] fix(database): Improve database type detection for Supabase Postgres images --- app/Models/ServiceDatabase.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/Models/ServiceDatabase.php b/app/Models/ServiceDatabase.php index 003687272..c2a0df8cd 100644 --- a/app/Models/ServiceDatabase.php +++ b/app/Models/ServiceDatabase.php @@ -78,11 +78,15 @@ class ServiceDatabase extends BaseModel public function databaseType() { $image = str($this->image)->before(':'); - if ($image->contains('postgres') || $image->contains('postgis')) { - $image = 'postgresql'; + if ($image->contains('supabase/postgres')) { + $finalImage = 'supabase/postgres'; + } elseif ($image->contains('postgres') || $image->contains('postgis')) { + $finalImage = 'postgresql'; + } else { + $finalImage = $image; } - return "standalone-$image"; + return "standalone-$finalImage"; } public function getServiceDatabaseUrl() From 1160b3312ec4827d329efc92a5d5550ddc60f1fb Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 11 Mar 2025 13:28:26 +0100 Subject: [PATCH 69/99] fix(seeder): Update GitHub app name in GithubAppSeeder --- database/seeders/GithubAppSeeder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/seeders/GithubAppSeeder.php b/database/seeders/GithubAppSeeder.php index 3cfb82e64..b34c00473 100644 --- a/database/seeders/GithubAppSeeder.php +++ b/database/seeders/GithubAppSeeder.php @@ -21,7 +21,7 @@ class GithubAppSeeder extends Seeder 'team_id' => 0, ]); GithubApp::create([ - 'name' => 'coolify-laravel-development-public', + 'name' => 'coolify-laravel-dev-public', 'uuid' => '69420', 'organization' => 'coollabsio', 'api_url' => 'https://api.github.com', From f73c74bd4409d94f5b07b25a93baaffabd0e21fa Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 11 Mar 2025 14:15:22 +0100 Subject: [PATCH 70/99] feat(github-source): Enhance GitHub App configuration with manual and private key support - Add support for manual GitHub App configuration - Introduce private key selection for GitHub Apps - Enable editing of previously disabled GitHub App fields - Add error handling for permission checks - Implement a manual GitHub App creation method --- app/Livewire/Source/Github/Change.php | 24 +- .../livewire/source/github/change.blade.php | 267 +++++++++--------- 2 files changed, 162 insertions(+), 129 deletions(-) diff --git a/app/Livewire/Source/Github/Change.php b/app/Livewire/Source/Github/Change.php index 20f52c322..e73c9dc73 100644 --- a/app/Livewire/Source/Github/Change.php +++ b/app/Livewire/Source/Github/Change.php @@ -37,6 +37,8 @@ class Change extends Component public $applications; + public $privateKeys; + protected $rules = [ 'github_app.name' => 'required|string', 'github_app.organization' => 'nullable|string', @@ -54,6 +56,7 @@ class Change extends Component 'github_app.metadata' => 'nullable|string', 'github_app.pull_requests' => 'nullable|string', 'github_app.administration' => 'nullable|string', + 'github_app.private_key_id' => 'required|int', ]; public function boot() @@ -65,9 +68,13 @@ class Change extends Component public function checkPermissions() { - GithubAppPermissionJob::dispatchSync($this->github_app); - $this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret'); - $this->dispatch('success', 'Github App permissions updated.'); + try { + GithubAppPermissionJob::dispatchSync($this->github_app); + $this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret'); + $this->dispatch('success', 'Github App permissions updated.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } } // public function check() @@ -109,6 +116,7 @@ class Change extends Component $github_app_uuid = request()->github_app_uuid; $this->github_app = GithubApp::ownedByCurrentTeam()->whereUuid($github_app_uuid)->firstOrFail(); $this->github_app->makeVisible(['client_secret', 'webhook_secret']); + $this->privateKeys = PrivateKey::ownedByCurrentTeam()->get(); $this->applications = $this->github_app->applications; $settings = instanceSettings(); @@ -243,6 +251,7 @@ class Change extends Component 'github_app.client_secret' => 'required|string', 'github_app.webhook_secret' => 'required|string', 'github_app.is_system_wide' => 'required|bool', + 'github_app.private_key_id' => 'required|int', ]); $this->github_app->save(); $this->dispatch('success', 'Github App updated.'); @@ -251,6 +260,15 @@ class Change extends Component } } + public function createGithubAppManually() + { + $this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret'); + $this->github_app->app_id = '1234567890'; + $this->github_app->installation_id = '1234567890'; + $this->github_app->save(); + $this->dispatch('success', 'Github App updated.'); + } + public function instantSave() { try { diff --git a/resources/views/livewire/source/github/change.blade.php b/resources/views/livewire/source/github/change.blade.php index 5a37fa47a..1b5493c58 100644 --- a/resources/views/livewire/source/github/change.blade.php +++ b/resources/views/livewire/source/github/change.blade.php @@ -27,6 +27,7 @@ confirmationText="{{ data_get($github_app, 'name') }}" :confirmWithPassword="false" step2ButtonText="Permanently Delete" /> @endif +
Your Private GitHub App for private repositories.
@@ -46,7 +47,7 @@
- + Sync Name @@ -57,7 +58,7 @@
-
@if (!isCloud()) @@ -68,27 +69,32 @@
@endif
- - + +
- @if ($github_app->html_url === 'https://github.com') - - - @else - - - @endif + +
- + + required />
- - - + + + +
+
+ + @if (blank($github_app->private_key_id)) + + @endif + @foreach ($privateKeys as $privateKey) + + @endforeach +

Permissions

@@ -182,120 +188,129 @@ shortConfirmationLabel="GitHub App Name" :confirmWithPassword="false" step2ButtonText="Permanently Delete" />
-
- - - - You must complete this step before you can use this source! -
-
-
- @if (!isCloud() || isDev()) -
- - @if ($ipv4) - - @endif - @if ($ipv6) - - @endif - @if ($fqdn) - - @endif - @if (config('app.url')) - - @endif - - - Register Now - -
- @else -
-

Register a GitHub App

- - Register Now - -
-
You need to register a GitHub App before using this source.
- @endif +
+

Manual Installation

+
+ If you want to fill the form manually, you can continue below. Only for advanced users. + + Continue + +
+

Automated Installation

+
+ + + + You must complete this step before you can use this source! +
+
+
+ @if (!isCloud() || isDev()) +
+ + @if ($ipv4) + + @endif + @if ($ipv6) + + @endif + @if ($fqdn) + + @endif + @if (config('app.url')) + + @endif + + + Register Now + +
+ @else +
+

Register a GitHub App

+ + Register Now + +
+
You need to register a GitHub App before using this source.
+ @endif -
- - - {{-- + + + {{-- --}} +
-
- + @endif
From 911957ff66d7053116e04c9b3f3bd38b6bb23594 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 11 Mar 2025 18:41:03 +0100 Subject: [PATCH 71/99] chore(supabase): Update Supabase service template and Postgres image version - Bump Supabase Postgres image from 15.6.1.146 to 15.8.1.048 --- templates/compose/supabase.yaml | 2 +- templates/service-templates.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/compose/supabase.yaml b/templates/compose/supabase.yaml index b60870f8a..9ec7c1dea 100644 --- a/templates/compose/supabase.yaml +++ b/templates/compose/supabase.yaml @@ -318,7 +318,7 @@ services: # NEXT_ANALYTICS_BACKEND_PROVIDER=bigquery - 'OPENAI_API_KEY=${OPENAI_API_KEY}' supabase-db: - image: supabase/postgres:15.6.1.146 + image: supabase/postgres:15.8.1.048 healthcheck: test: pg_isready -U postgres -h 127.0.0.1 interval: 5s diff --git a/templates/service-templates.json b/templates/service-templates.json index 112748c1a..d88ad79fa 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -2821,7 +2821,7 @@ "supabase": { "documentation": "https://supabase.io?utm_source=coolify.io", "slogan": "The open source Firebase alternative.", - "compose": "c2VydmljZXM6CiAgc3VwYWJhc2Uta29uZzoKICAgIGltYWdlOiAna29uZzoyLjguMScKICAgIGVudHJ5cG9pbnQ6ICdiYXNoIC1jICcnZXZhbCAiZWNobyBcIiQkKGNhdCB+L3RlbXAueW1sKVwiIiA+IH4va29uZy55bWwgJiYgL2RvY2tlci1lbnRyeXBvaW50LnNoIGtvbmcgZG9ja2VyLXN0YXJ0JycnCiAgICBkZXBlbmRzX29uOgogICAgICBzdXBhYmFzZS1hbmFseXRpY3M6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9TVVBBQkFTRUtPTkdfODAwMAogICAgICAtICdLT05HX1BPUlRfTUFQUz00NDM6ODAwMCcKICAgICAgLSAnSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfSldUfScKICAgICAgLSBLT05HX0RBVEFCQVNFPW9mZgogICAgICAtIEtPTkdfREVDTEFSQVRJVkVfQ09ORklHPS9ob21lL2tvbmcva29uZy55bWwKICAgICAgLSAnS09OR19ETlNfT1JERVI9TEFTVCxBLENOQU1FJwogICAgICAtICdLT05HX1BMVUdJTlM9cmVxdWVzdC10cmFuc2Zvcm1lcixjb3JzLGtleS1hdXRoLGFjbCxiYXNpYy1hdXRoJwogICAgICAtIEtPTkdfTkdJTlhfUFJPWFlfUFJPWFlfQlVGRkVSX1NJWkU9MTYwawogICAgICAtICdLT05HX05HSU5YX1BST1hZX1BST1hZX0JVRkZFUlM9NjQgMTYwaycKICAgICAgLSAnU1VQQUJBU0VfQU5PTl9LRVk9JHtTRVJWSUNFX1NVUEFCQVNFQU5PTl9LRVl9JwogICAgICAtICdTVVBBQkFTRV9TRVJWSUNFX0tFWT0ke1NFUlZJQ0VfU1VQQUJBU0VTRVJWSUNFX0tFWX0nCiAgICAgIC0gJ0RBU0hCT0FSRF9VU0VSTkFNRT0ke1NFUlZJQ0VfVVNFUl9BRE1JTn0nCiAgICAgIC0gJ0RBU0hCT0FSRF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfQURNSU59JwogICAgdm9sdW1lczoKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9hcGkva29uZy55bWwKICAgICAgICB0YXJnZXQ6IC9ob21lL2tvbmcvdGVtcC55bWwKICAgICAgICBjb250ZW50OiAiX2Zvcm1hdF92ZXJzaW9uOiAnMi4xJ1xuX3RyYW5zZm9ybTogdHJ1ZVxuXG4jIyNcbiMjIyBDb25zdW1lcnMgLyBVc2Vyc1xuIyMjXG5jb25zdW1lcnM6XG4gIC0gdXNlcm5hbWU6IERBU0hCT0FSRFxuICAtIHVzZXJuYW1lOiBhbm9uXG4gICAga2V5YXV0aF9jcmVkZW50aWFsczpcbiAgICAgIC0ga2V5OiAkU1VQQUJBU0VfQU5PTl9LRVlcbiAgLSB1c2VybmFtZTogc2VydmljZV9yb2xlXG4gICAga2V5YXV0aF9jcmVkZW50aWFsczpcbiAgICAgIC0ga2V5OiAkU1VQQUJBU0VfU0VSVklDRV9LRVlcblxuIyMjXG4jIyMgQWNjZXNzIENvbnRyb2wgTGlzdFxuIyMjXG5hY2xzOlxuICAtIGNvbnN1bWVyOiBhbm9uXG4gICAgZ3JvdXA6IGFub25cbiAgLSBjb25zdW1lcjogc2VydmljZV9yb2xlXG4gICAgZ3JvdXA6IGFkbWluXG5cbiMjI1xuIyMjIERhc2hib2FyZCBjcmVkZW50aWFsc1xuIyMjXG5iYXNpY2F1dGhfY3JlZGVudGlhbHM6XG4tIGNvbnN1bWVyOiBEQVNIQk9BUkRcbiAgdXNlcm5hbWU6ICREQVNIQk9BUkRfVVNFUk5BTUVcbiAgcGFzc3dvcmQ6ICREQVNIQk9BUkRfUEFTU1dPUkRcblxuXG4jIyNcbiMjIyBBUEkgUm91dGVzXG4jIyNcbnNlcnZpY2VzOlxuXG4gICMjIE9wZW4gQXV0aCByb3V0ZXNcbiAgLSBuYW1lOiBhdXRoLXYxLW9wZW5cbiAgICB1cmw6IGh0dHA6Ly9zdXBhYmFzZS1hdXRoOjk5OTkvdmVyaWZ5XG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiBhdXRoLXYxLW9wZW5cbiAgICAgICAgc3RyaXBfcGF0aDogdHJ1ZVxuICAgICAgICBwYXRoczpcbiAgICAgICAgICAtIC9hdXRoL3YxL3ZlcmlmeVxuICAgIHBsdWdpbnM6XG4gICAgICAtIG5hbWU6IGNvcnNcbiAgLSBuYW1lOiBhdXRoLXYxLW9wZW4tY2FsbGJhY2tcbiAgICB1cmw6IGh0dHA6Ly9zdXBhYmFzZS1hdXRoOjk5OTkvY2FsbGJhY2tcbiAgICByb3V0ZXM6XG4gICAgICAtIG5hbWU6IGF1dGgtdjEtb3Blbi1jYWxsYmFja1xuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL2F1dGgvdjEvY2FsbGJhY2tcbiAgICBwbHVnaW5zOlxuICAgICAgLSBuYW1lOiBjb3JzXG4gIC0gbmFtZTogYXV0aC12MS1vcGVuLWF1dGhvcml6ZVxuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLWF1dGg6OTk5OS9hdXRob3JpemVcbiAgICByb3V0ZXM6XG4gICAgICAtIG5hbWU6IGF1dGgtdjEtb3Blbi1hdXRob3JpemVcbiAgICAgICAgc3RyaXBfcGF0aDogdHJ1ZVxuICAgICAgICBwYXRoczpcbiAgICAgICAgICAtIC9hdXRoL3YxL2F1dGhvcml6ZVxuICAgIHBsdWdpbnM6XG4gICAgICAtIG5hbWU6IGNvcnNcblxuICAjIyBTZWN1cmUgQXV0aCByb3V0ZXNcbiAgLSBuYW1lOiBhdXRoLXYxXG4gICAgX2NvbW1lbnQ6ICdHb1RydWU6IC9hdXRoL3YxLyogLT4gaHR0cDovL3N1cGFiYXNlLWF1dGg6OTk5OS8qJ1xuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLWF1dGg6OTk5OS9cbiAgICByb3V0ZXM6XG4gICAgICAtIG5hbWU6IGF1dGgtdjEtYWxsXG4gICAgICAgIHN0cmlwX3BhdGg6IHRydWVcbiAgICAgICAgcGF0aHM6XG4gICAgICAgICAgLSAvYXV0aC92MS9cbiAgICBwbHVnaW5zOlxuICAgICAgLSBuYW1lOiBjb3JzXG4gICAgICAtIG5hbWU6IGtleS1hdXRoXG4gICAgICAgIGNvbmZpZzpcbiAgICAgICAgICBoaWRlX2NyZWRlbnRpYWxzOiBmYWxzZVxuICAgICAgLSBuYW1lOiBhY2xcbiAgICAgICAgY29uZmlnOlxuICAgICAgICAgIGhpZGVfZ3JvdXBzX2hlYWRlcjogdHJ1ZVxuICAgICAgICAgIGFsbG93OlxuICAgICAgICAgICAgLSBhZG1pblxuICAgICAgICAgICAgLSBhbm9uXG5cbiAgIyMgU2VjdXJlIFJFU1Qgcm91dGVzXG4gIC0gbmFtZTogcmVzdC12MVxuICAgIF9jb21tZW50OiAnUG9zdGdSRVNUOiAvcmVzdC92MS8qIC0+IGh0dHA6Ly9zdXBhYmFzZS1yZXN0OjMwMDAvKidcbiAgICB1cmw6IGh0dHA6Ly9zdXBhYmFzZS1yZXN0OjMwMDAvXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiByZXN0LXYxLWFsbFxuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL3Jlc3QvdjEvXG4gICAgcGx1Z2luczpcbiAgICAgIC0gbmFtZTogY29yc1xuICAgICAgLSBuYW1lOiBrZXktYXV0aFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9jcmVkZW50aWFsczogdHJ1ZVxuICAgICAgLSBuYW1lOiBhY2xcbiAgICAgICAgY29uZmlnOlxuICAgICAgICAgIGhpZGVfZ3JvdXBzX2hlYWRlcjogdHJ1ZVxuICAgICAgICAgIGFsbG93OlxuICAgICAgICAgICAgLSBhZG1pblxuICAgICAgICAgICAgLSBhbm9uXG5cbiAgIyMgU2VjdXJlIEdyYXBoUUwgcm91dGVzXG4gIC0gbmFtZTogZ3JhcGhxbC12MVxuICAgIF9jb21tZW50OiAnUG9zdGdSRVNUOiAvZ3JhcGhxbC92MS8qIC0+IGh0dHA6Ly9zdXBhYmFzZS1yZXN0OjMwMDAvcnBjL2dyYXBocWwnXG4gICAgdXJsOiBodHRwOi8vc3VwYWJhc2UtcmVzdDozMDAwL3JwYy9ncmFwaHFsXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiBncmFwaHFsLXYxLWFsbFxuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL2dyYXBocWwvdjFcbiAgICBwbHVnaW5zOlxuICAgICAgLSBuYW1lOiBjb3JzXG4gICAgICAtIG5hbWU6IGtleS1hdXRoXG4gICAgICAgIGNvbmZpZzpcbiAgICAgICAgICBoaWRlX2NyZWRlbnRpYWxzOiB0cnVlXG4gICAgICAtIG5hbWU6IHJlcXVlc3QtdHJhbnNmb3JtZXJcbiAgICAgICAgY29uZmlnOlxuICAgICAgICAgIGFkZDpcbiAgICAgICAgICAgIGhlYWRlcnM6XG4gICAgICAgICAgICAgIC0gQ29udGVudC1Qcm9maWxlOmdyYXBocWxfcHVibGljXG4gICAgICAtIG5hbWU6IGFjbFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9ncm91cHNfaGVhZGVyOiB0cnVlXG4gICAgICAgICAgYWxsb3c6XG4gICAgICAgICAgICAtIGFkbWluXG4gICAgICAgICAgICAtIGFub25cblxuICAjIyBTZWN1cmUgUmVhbHRpbWUgcm91dGVzXG4gIC0gbmFtZTogcmVhbHRpbWUtdjEtd3NcbiAgICBfY29tbWVudDogJ1JlYWx0aW1lOiAvcmVhbHRpbWUvdjEvKiAtPiB3czovL3JlYWx0aW1lOjQwMDAvc29ja2V0LyonXG4gICAgdXJsOiBodHRwOi8vcmVhbHRpbWUtZGV2OjQwMDAvc29ja2V0XG4gICAgcHJvdG9jb2w6IHdzXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiByZWFsdGltZS12MS13c1xuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL3JlYWx0aW1lL3YxL1xuICAgIHBsdWdpbnM6XG4gICAgICAtIG5hbWU6IGNvcnNcbiAgICAgIC0gbmFtZToga2V5LWF1dGhcbiAgICAgICAgY29uZmlnOlxuICAgICAgICAgIGhpZGVfY3JlZGVudGlhbHM6IGZhbHNlXG4gICAgICAtIG5hbWU6IGFjbFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9ncm91cHNfaGVhZGVyOiB0cnVlXG4gICAgICAgICAgYWxsb3c6XG4gICAgICAgICAgICAtIGFkbWluXG4gICAgICAgICAgICAtIGFub25cbiAgLSBuYW1lOiByZWFsdGltZS12MS1yZXN0XG4gICAgX2NvbW1lbnQ6ICdSZWFsdGltZTogL3JlYWx0aW1lL3YxLyogLT4gd3M6Ly9yZWFsdGltZTo0MDAwL3NvY2tldC8qJ1xuICAgIHVybDogaHR0cDovL3JlYWx0aW1lLWRldjo0MDAwL2FwaVxuICAgIHByb3RvY29sOiBodHRwXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiByZWFsdGltZS12MS1yZXN0XG4gICAgICAgIHN0cmlwX3BhdGg6IHRydWVcbiAgICAgICAgcGF0aHM6XG4gICAgICAgICAgLSAvcmVhbHRpbWUvdjEvYXBpXG4gICAgcGx1Z2luczpcbiAgICAgIC0gbmFtZTogY29yc1xuICAgICAgLSBuYW1lOiBrZXktYXV0aFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9jcmVkZW50aWFsczogZmFsc2VcbiAgICAgIC0gbmFtZTogYWNsXG4gICAgICAgIGNvbmZpZzpcbiAgICAgICAgICBoaWRlX2dyb3Vwc19oZWFkZXI6IHRydWVcbiAgICAgICAgICBhbGxvdzpcbiAgICAgICAgICAgIC0gYWRtaW5cbiAgICAgICAgICAgIC0gYW5vblxuXG4gICMjIFN0b3JhZ2Ugcm91dGVzOiB0aGUgc3RvcmFnZSBzZXJ2ZXIgbWFuYWdlcyBpdHMgb3duIGF1dGhcbiAgLSBuYW1lOiBzdG9yYWdlLXYxXG4gICAgX2NvbW1lbnQ6ICdTdG9yYWdlOiAvc3RvcmFnZS92MS8qIC0+IGh0dHA6Ly9zdXBhYmFzZS1zdG9yYWdlOjUwMDAvKidcbiAgICB1cmw6IGh0dHA6Ly9zdXBhYmFzZS1zdG9yYWdlOjUwMDAvXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiBzdG9yYWdlLXYxLWFsbFxuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL3N0b3JhZ2UvdjEvXG4gICAgcGx1Z2luczpcbiAgICAgIC0gbmFtZTogY29yc1xuXG4gICMjIEVkZ2UgRnVuY3Rpb25zIHJvdXRlc1xuICAtIG5hbWU6IGZ1bmN0aW9ucy12MVxuICAgIF9jb21tZW50OiAnRWRnZSBGdW5jdGlvbnM6IC9mdW5jdGlvbnMvdjEvKiAtPiBodHRwOi8vc3VwYWJhc2UtZWRnZS1mdW5jdGlvbnM6OTAwMC8qJ1xuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLWVkZ2UtZnVuY3Rpb25zOjkwMDAvXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiBmdW5jdGlvbnMtdjEtYWxsXG4gICAgICAgIHN0cmlwX3BhdGg6IHRydWVcbiAgICAgICAgcGF0aHM6XG4gICAgICAgICAgLSAvZnVuY3Rpb25zL3YxL1xuICAgIHBsdWdpbnM6XG4gICAgICAtIG5hbWU6IGNvcnNcblxuICAjIyBBbmFseXRpY3Mgcm91dGVzXG4gIC0gbmFtZTogYW5hbHl0aWNzLXYxXG4gICAgX2NvbW1lbnQ6ICdBbmFseXRpY3M6IC9hbmFseXRpY3MvdjEvKiAtPiBodHRwOi8vbG9nZmxhcmU6NDAwMC8qJ1xuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLWFuYWx5dGljczo0MDAwL1xuICAgIHJvdXRlczpcbiAgICAgIC0gbmFtZTogYW5hbHl0aWNzLXYxLWFsbFxuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL2FuYWx5dGljcy92MS9cblxuICAjIyBTZWN1cmUgRGF0YWJhc2Ugcm91dGVzXG4gIC0gbmFtZTogbWV0YVxuICAgIF9jb21tZW50OiAncGctbWV0YTogL3BnLyogLT4gaHR0cDovL3N1cGFiYXNlLW1ldGE6ODA4MC8qJ1xuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLW1ldGE6ODA4MC9cbiAgICByb3V0ZXM6XG4gICAgICAtIG5hbWU6IG1ldGEtYWxsXG4gICAgICAgIHN0cmlwX3BhdGg6IHRydWVcbiAgICAgICAgcGF0aHM6XG4gICAgICAgICAgLSAvcGcvXG4gICAgcGx1Z2luczpcbiAgICAgIC0gbmFtZToga2V5LWF1dGhcbiAgICAgICAgY29uZmlnOlxuICAgICAgICAgIGhpZGVfY3JlZGVudGlhbHM6IGZhbHNlXG4gICAgICAtIG5hbWU6IGFjbFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9ncm91cHNfaGVhZGVyOiB0cnVlXG4gICAgICAgICAgYWxsb3c6XG4gICAgICAgICAgICAtIGFkbWluXG5cbiAgIyMgUHJvdGVjdGVkIERhc2hib2FyZCAtIGNhdGNoIGFsbCByZW1haW5pbmcgcm91dGVzXG4gIC0gbmFtZTogZGFzaGJvYXJkXG4gICAgX2NvbW1lbnQ6ICdTdHVkaW86IC8qIC0+IGh0dHA6Ly9zdHVkaW86MzAwMC8qJ1xuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLXN0dWRpbzozMDAwL1xuICAgIHJvdXRlczpcbiAgICAgIC0gbmFtZTogZGFzaGJvYXJkLWFsbFxuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL1xuICAgIHBsdWdpbnM6XG4gICAgICAtIG5hbWU6IGNvcnNcbiAgICAgIC0gbmFtZTogYmFzaWMtYXV0aFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9jcmVkZW50aWFsczogdHJ1ZVxuIgogIHN1cGFiYXNlLXN0dWRpbzoKICAgIGltYWdlOiAnc3VwYWJhc2Uvc3R1ZGlvOjIwMjQxMjAyLTcxZTUyNDAnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gbm9kZQogICAgICAgIC0gJy1lJwogICAgICAgIC0gInJlcXVpcmUoJ2h0dHAnKS5nZXQoJ2h0dHA6Ly8xMjcuMC4wLjE6MzAwMC9hcGkvcHJvZmlsZScsIChyKSA9PiB7aWYgKHIuc3RhdHVzQ29kZSAhPT0gMjAwKSBwcm9jZXNzLmV4aXQoMSk7IGVsc2UgcHJvY2Vzcy5leGl0KDApOyB9KS5vbignZXJyb3InLCAoKSA9PiBwcm9jZXNzLmV4aXQoMSkpIgogICAgICB0aW1lb3V0OiA1cwogICAgICBpbnRlcnZhbDogNXMKICAgICAgcmV0cmllczogMwogICAgZGVwZW5kc19vbjoKICAgICAgc3VwYWJhc2UtYW5hbHl0aWNzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBIT1NUTkFNRT0wLjAuMC4wCiAgICAgIC0gJ1NUVURJT19QR19NRVRBX1VSTD1odHRwOi8vc3VwYWJhc2UtbWV0YTo4MDgwJwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdERUZBVUxUX09SR0FOSVpBVElPTl9OQU1FPSR7U1RVRElPX0RFRkFVTFRfT1JHQU5JWkFUSU9OOi1EZWZhdWx0IE9yZ2FuaXphdGlvbn0nCiAgICAgIC0gJ0RFRkFVTFRfUFJPSkVDVF9OQU1FPSR7U1RVRElPX0RFRkFVTFRfUFJPSkVDVDotRGVmYXVsdCBQcm9qZWN0fScKICAgICAgLSAnU1VQQUJBU0VfVVJMPWh0dHA6Ly9zdXBhYmFzZS1rb25nOjgwMDAnCiAgICAgIC0gJ1NVUEFCQVNFX1BVQkxJQ19VUkw9JHtTRVJWSUNFX0ZRRE5fU1VQQUJBU0VLT05HfScKICAgICAgLSAnU1VQQUJBU0VfQU5PTl9LRVk9JHtTRVJWSUNFX1NVUEFCQVNFQU5PTl9LRVl9JwogICAgICAtICdTVVBBQkFTRV9TRVJWSUNFX0tFWT0ke1NFUlZJQ0VfU1VQQUJBU0VTRVJWSUNFX0tFWX0nCiAgICAgIC0gJ0FVVEhfSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfSldUfScKICAgICAgLSAnTE9HRkxBUkVfQVBJX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfTE9HRkxBUkV9JwogICAgICAtICdMT0dGTEFSRV9VUkw9aHR0cDovL3N1cGFiYXNlLWFuYWx5dGljczo0MDAwJwogICAgICAtICdTVVBBQkFTRV9QVUJMSUNfQVBJPSR7U0VSVklDRV9GUUROX1NVUEFCQVNFS09OR30nCiAgICAgIC0gTkVYVF9QVUJMSUNfRU5BQkxFX0xPR1M9dHJ1ZQogICAgICAtIE5FWFRfQU5BTFlUSUNTX0JBQ0tFTkRfUFJPVklERVI9cG9zdGdyZXMKICAgICAgLSAnT1BFTkFJX0FQSV9LRVk9JHtPUEVOQUlfQVBJX0tFWX0nCiAgc3VwYWJhc2UtZGI6CiAgICBpbWFnZTogJ3N1cGFiYXNlL3Bvc3RncmVzOjE1LjYuMS4xNDYnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogJ3BnX2lzcmVhZHkgLVUgcG9zdGdyZXMgLWggMTI3LjAuMC4xJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogMTAKICAgIGRlcGVuZHNfb246CiAgICAgIHN1cGFiYXNlLXZlY3RvcjoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgY29tbWFuZDoKICAgICAgLSBwb3N0Z3JlcwogICAgICAtICctYycKICAgICAgLSBjb25maWdfZmlsZT0vZXRjL3Bvc3RncmVzcWwvcG9zdGdyZXNxbC5jb25mCiAgICAgIC0gJy1jJwogICAgICAtIGxvZ19taW5fbWVzc2FnZXM9ZmF0YWwKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX0hPU1Q9L3Zhci9ydW4vcG9zdGdyZXNxbAogICAgICAtICdQR1BPUlQ9JHtQT1NUR1JFU19QT1JUOi01NDMyfScKICAgICAgLSAnUE9TVEdSRVNfUE9SVD0ke1BPU1RHUkVTX1BPUlQ6LTU0MzJ9JwogICAgICAtICdQR1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BHREFUQUJBU0U9JHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc30nCiAgICAgIC0gJ0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX0pXVH0nCiAgICAgIC0gJ0pXVF9FWFA9JHtKV1RfRVhQSVJZOi0zNjAwfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3N1cGFiYXNlLWRiLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgICAtCiAgICAgICAgdHlwZTogYmluZAogICAgICAgIHNvdXJjZTogLi92b2x1bWVzL2RiL3JlYWx0aW1lLnNxbAogICAgICAgIHRhcmdldDogL2RvY2tlci1lbnRyeXBvaW50LWluaXRkYi5kL21pZ3JhdGlvbnMvOTktcmVhbHRpbWUuc3FsCiAgICAgICAgY29udGVudDogIlxcc2V0IHBndXNlciBgZWNobyBcInN1cGFiYXNlX2FkbWluXCJgXG5cbmNyZWF0ZSBzY2hlbWEgaWYgbm90IGV4aXN0cyBfcmVhbHRpbWU7XG5hbHRlciBzY2hlbWEgX3JlYWx0aW1lIG93bmVyIHRvIDpwZ3VzZXI7XG4iCiAgICAgIC0KICAgICAgICB0eXBlOiBiaW5kCiAgICAgICAgc291cmNlOiAuL3ZvbHVtZXMvZGIvX3N1cGFiYXNlLnNxbAogICAgICAgIHRhcmdldDogL2RvY2tlci1lbnRyeXBvaW50LWluaXRkYi5kL21pZ3JhdGlvbnMvOTctX3N1cGFiYXNlLnNxbAogICAgICAgIGNvbnRlbnQ6ICJcXHNldCBwZ3VzZXIgYGVjaG8gXCIkUE9TVEdSRVNfVVNFUlwiYFxuXG5DUkVBVEUgREFUQUJBU0UgX3N1cGFiYXNlIFdJVEggT1dORVIgOnBndXNlcjtcbiIKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9kYi9wb29sZXIuc3FsCiAgICAgICAgdGFyZ2V0OiAvZG9ja2VyLWVudHJ5cG9pbnQtaW5pdGRiLmQvbWlncmF0aW9ucy85OS1wb29sZXIuc3FsCiAgICAgICAgY29udGVudDogIlxcc2V0IHBndXNlciBgZWNobyBcInN1cGFiYXNlX2FkbWluXCJgXG5cXGMgX3N1cGFiYXNlXG5jcmVhdGUgc2NoZW1hIGlmIG5vdCBleGlzdHMgX3N1cGF2aXNvcjtcbmFsdGVyIHNjaGVtYSBfc3VwYXZpc29yIG93bmVyIHRvIDpwZ3VzZXI7XG5cXGMgcG9zdGdyZXNcbiIKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9kYi93ZWJob29rcy5zcWwKICAgICAgICB0YXJnZXQ6IC9kb2NrZXItZW50cnlwb2ludC1pbml0ZGIuZC9pbml0LXNjcmlwdHMvOTgtd2ViaG9va3Muc3FsCiAgICAgICAgY29udGVudDogIkJFR0lOO1xuLS0gQ3JlYXRlIHBnX25ldCBleHRlbnNpb25cbkNSRUFURSBFWFRFTlNJT04gSUYgTk9UIEVYSVNUUyBwZ19uZXQgU0NIRU1BIGV4dGVuc2lvbnM7XG4tLSBDcmVhdGUgc3VwYWJhc2VfZnVuY3Rpb25zIHNjaGVtYVxuQ1JFQVRFIFNDSEVNQSBzdXBhYmFzZV9mdW5jdGlvbnMgQVVUSE9SSVpBVElPTiBzdXBhYmFzZV9hZG1pbjtcbkdSQU5UIFVTQUdFIE9OIFNDSEVNQSBzdXBhYmFzZV9mdW5jdGlvbnMgVE8gcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbkFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBJTiBTQ0hFTUEgc3VwYWJhc2VfZnVuY3Rpb25zIEdSQU5UIEFMTCBPTiBUQUJMRVMgVE8gcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbkFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBJTiBTQ0hFTUEgc3VwYWJhc2VfZnVuY3Rpb25zIEdSQU5UIEFMTCBPTiBGVU5DVElPTlMgVE8gcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbkFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBJTiBTQ0hFTUEgc3VwYWJhc2VfZnVuY3Rpb25zIEdSQU5UIEFMTCBPTiBTRVFVRU5DRVMgVE8gcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbi0tIHN1cGFiYXNlX2Z1bmN0aW9ucy5taWdyYXRpb25zIGRlZmluaXRpb25cbkNSRUFURSBUQUJMRSBzdXBhYmFzZV9mdW5jdGlvbnMubWlncmF0aW9ucyAoXG4gIHZlcnNpb24gdGV4dCBQUklNQVJZIEtFWSxcbiAgaW5zZXJ0ZWRfYXQgdGltZXN0YW1wdHogTk9UIE5VTEwgREVGQVVMVCBOT1coKVxuKTtcbi0tIEluaXRpYWwgc3VwYWJhc2VfZnVuY3Rpb25zIG1pZ3JhdGlvblxuSU5TRVJUIElOVE8gc3VwYWJhc2VfZnVuY3Rpb25zLm1pZ3JhdGlvbnMgKHZlcnNpb24pIFZBTFVFUyAoJ2luaXRpYWwnKTtcbi0tIHN1cGFiYXNlX2Z1bmN0aW9ucy5ob29rcyBkZWZpbml0aW9uXG5DUkVBVEUgVEFCTEUgc3VwYWJhc2VfZnVuY3Rpb25zLmhvb2tzIChcbiAgaWQgYmlnc2VyaWFsIFBSSU1BUlkgS0VZLFxuICBob29rX3RhYmxlX2lkIGludGVnZXIgTk9UIE5VTEwsXG4gIGhvb2tfbmFtZSB0ZXh0IE5PVCBOVUxMLFxuICBjcmVhdGVkX2F0IHRpbWVzdGFtcHR6IE5PVCBOVUxMIERFRkFVTFQgTk9XKCksXG4gIHJlcXVlc3RfaWQgYmlnaW50XG4pO1xuQ1JFQVRFIElOREVYIHN1cGFiYXNlX2Z1bmN0aW9uc19ob29rc19yZXF1ZXN0X2lkX2lkeCBPTiBzdXBhYmFzZV9mdW5jdGlvbnMuaG9va3MgVVNJTkcgYnRyZWUgKHJlcXVlc3RfaWQpO1xuQ1JFQVRFIElOREVYIHN1cGFiYXNlX2Z1bmN0aW9uc19ob29rc19oX3RhYmxlX2lkX2hfbmFtZV9pZHggT04gc3VwYWJhc2VfZnVuY3Rpb25zLmhvb2tzIFVTSU5HIGJ0cmVlIChob29rX3RhYmxlX2lkLCBob29rX25hbWUpO1xuQ09NTUVOVCBPTiBUQUJMRSBzdXBhYmFzZV9mdW5jdGlvbnMuaG9va3MgSVMgJ1N1cGFiYXNlIEZ1bmN0aW9ucyBIb29rczogQXVkaXQgdHJhaWwgZm9yIHRyaWdnZXJlZCBob29rcy4nO1xuQ1JFQVRFIEZVTkNUSU9OIHN1cGFiYXNlX2Z1bmN0aW9ucy5odHRwX3JlcXVlc3QoKVxuICBSRVRVUk5TIHRyaWdnZXJcbiAgTEFOR1VBR0UgcGxwZ3NxbFxuICBBUyAkZnVuY3Rpb24kXG4gIERFQ0xBUkVcbiAgICByZXF1ZXN0X2lkIGJpZ2ludDtcbiAgICBwYXlsb2FkIGpzb25iO1xuICAgIHVybCB0ZXh0IDo9IFRHX0FSR1ZbMF06OnRleHQ7XG4gICAgbWV0aG9kIHRleHQgOj0gVEdfQVJHVlsxXTo6dGV4dDtcbiAgICBoZWFkZXJzIGpzb25iIERFRkFVTFQgJ3t9Jzo6anNvbmI7XG4gICAgcGFyYW1zIGpzb25iIERFRkFVTFQgJ3t9Jzo6anNvbmI7XG4gICAgdGltZW91dF9tcyBpbnRlZ2VyIERFRkFVTFQgMTAwMDtcbiAgQkVHSU5cbiAgICBJRiB1cmwgSVMgTlVMTCBPUiB1cmwgPSAnbnVsbCcgVEhFTlxuICAgICAgUkFJU0UgRVhDRVBUSU9OICd1cmwgYXJndW1lbnQgaXMgbWlzc2luZyc7XG4gICAgRU5EIElGO1xuXG4gICAgSUYgbWV0aG9kIElTIE5VTEwgT1IgbWV0aG9kID0gJ251bGwnIFRIRU5cbiAgICAgIFJBSVNFIEVYQ0VQVElPTiAnbWV0aG9kIGFyZ3VtZW50IGlzIG1pc3NpbmcnO1xuICAgIEVORCBJRjtcblxuICAgIElGIFRHX0FSR1ZbMl0gSVMgTlVMTCBPUiBUR19BUkdWWzJdID0gJ251bGwnIFRIRU5cbiAgICAgIGhlYWRlcnMgPSAne1wiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwifSc6Ompzb25iO1xuICAgIEVMU0VcbiAgICAgIGhlYWRlcnMgPSBUR19BUkdWWzJdOjpqc29uYjtcbiAgICBFTkQgSUY7XG5cbiAgICBJRiBUR19BUkdWWzNdIElTIE5VTEwgT1IgVEdfQVJHVlszXSA9ICdudWxsJyBUSEVOXG4gICAgICBwYXJhbXMgPSAne30nOjpqc29uYjtcbiAgICBFTFNFXG4gICAgICBwYXJhbXMgPSBUR19BUkdWWzNdOjpqc29uYjtcbiAgICBFTkQgSUY7XG5cbiAgICBJRiBUR19BUkdWWzRdIElTIE5VTEwgT1IgVEdfQVJHVls0XSA9ICdudWxsJyBUSEVOXG4gICAgICB0aW1lb3V0X21zID0gMTAwMDtcbiAgICBFTFNFXG4gICAgICB0aW1lb3V0X21zID0gVEdfQVJHVls0XTo6aW50ZWdlcjtcbiAgICBFTkQgSUY7XG5cbiAgICBDQVNFXG4gICAgICBXSEVOIG1ldGhvZCA9ICdHRVQnIFRIRU5cbiAgICAgICAgU0VMRUNUIGh0dHBfZ2V0IElOVE8gcmVxdWVzdF9pZCBGUk9NIG5ldC5odHRwX2dldChcbiAgICAgICAgICB1cmwsXG4gICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgIGhlYWRlcnMsXG4gICAgICAgICAgdGltZW91dF9tc1xuICAgICAgICApO1xuICAgICAgV0hFTiBtZXRob2QgPSAnUE9TVCcgVEhFTlxuICAgICAgICBwYXlsb2FkID0ganNvbmJfYnVpbGRfb2JqZWN0KFxuICAgICAgICAgICdvbGRfcmVjb3JkJywgT0xELFxuICAgICAgICAgICdyZWNvcmQnLCBORVcsXG4gICAgICAgICAgJ3R5cGUnLCBUR19PUCxcbiAgICAgICAgICAndGFibGUnLCBUR19UQUJMRV9OQU1FLFxuICAgICAgICAgICdzY2hlbWEnLCBUR19UQUJMRV9TQ0hFTUFcbiAgICAgICAgKTtcblxuICAgICAgICBTRUxFQ1QgaHR0cF9wb3N0IElOVE8gcmVxdWVzdF9pZCBGUk9NIG5ldC5odHRwX3Bvc3QoXG4gICAgICAgICAgdXJsLFxuICAgICAgICAgIHBheWxvYWQsXG4gICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgIGhlYWRlcnMsXG4gICAgICAgICAgdGltZW91dF9tc1xuICAgICAgICApO1xuICAgICAgRUxTRVxuICAgICAgICBSQUlTRSBFWENFUFRJT04gJ21ldGhvZCBhcmd1bWVudCAlIGlzIGludmFsaWQnLCBtZXRob2Q7XG4gICAgRU5EIENBU0U7XG5cbiAgICBJTlNFUlQgSU5UTyBzdXBhYmFzZV9mdW5jdGlvbnMuaG9va3NcbiAgICAgIChob29rX3RhYmxlX2lkLCBob29rX25hbWUsIHJlcXVlc3RfaWQpXG4gICAgVkFMVUVTXG4gICAgICAoVEdfUkVMSUQsIFRHX05BTUUsIHJlcXVlc3RfaWQpO1xuXG4gICAgUkVUVVJOIE5FVztcbiAgRU5EXG4kZnVuY3Rpb24kO1xuLS0gU3VwYWJhc2Ugc3VwZXIgYWRtaW5cbkRPXG4kJFxuQkVHSU5cbiAgSUYgTk9UIEVYSVNUUyAoXG4gICAgU0VMRUNUIDFcbiAgICBGUk9NIHBnX3JvbGVzXG4gICAgV0hFUkUgcm9sbmFtZSA9ICdzdXBhYmFzZV9mdW5jdGlvbnNfYWRtaW4nXG4gIClcbiAgVEhFTlxuICAgIENSRUFURSBVU0VSIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbiBOT0lOSEVSSVQgQ1JFQVRFUk9MRSBMT0dJTiBOT1JFUExJQ0FUSU9OO1xuICBFTkQgSUY7XG5FTkRcbiQkO1xuR1JBTlQgQUxMIFBSSVZJTEVHRVMgT04gU0NIRU1BIHN1cGFiYXNlX2Z1bmN0aW9ucyBUTyBzdXBhYmFzZV9mdW5jdGlvbnNfYWRtaW47XG5HUkFOVCBBTEwgUFJJVklMRUdFUyBPTiBBTEwgVEFCTEVTIElOIFNDSEVNQSBzdXBhYmFzZV9mdW5jdGlvbnMgVE8gc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluO1xuR1JBTlQgQUxMIFBSSVZJTEVHRVMgT04gQUxMIFNFUVVFTkNFUyBJTiBTQ0hFTUEgc3VwYWJhc2VfZnVuY3Rpb25zIFRPIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbjtcbkFMVEVSIFVTRVIgc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluIFNFVCBzZWFyY2hfcGF0aCA9IFwic3VwYWJhc2VfZnVuY3Rpb25zXCI7XG5BTFRFUiB0YWJsZSBcInN1cGFiYXNlX2Z1bmN0aW9uc1wiLm1pZ3JhdGlvbnMgT1dORVIgVE8gc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluO1xuQUxURVIgdGFibGUgXCJzdXBhYmFzZV9mdW5jdGlvbnNcIi5ob29rcyBPV05FUiBUTyBzdXBhYmFzZV9mdW5jdGlvbnNfYWRtaW47XG5BTFRFUiBmdW5jdGlvbiBcInN1cGFiYXNlX2Z1bmN0aW9uc1wiLmh0dHBfcmVxdWVzdCgpIE9XTkVSIFRPIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbjtcbkdSQU5UIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbiBUTyBwb3N0Z3Jlcztcbi0tIFJlbW92ZSB1bnVzZWQgc3VwYWJhc2VfcGdfbmV0X2FkbWluIHJvbGVcbkRPXG4kJFxuQkVHSU5cbiAgSUYgRVhJU1RTIChcbiAgICBTRUxFQ1QgMVxuICAgIEZST00gcGdfcm9sZXNcbiAgICBXSEVSRSByb2xuYW1lID0gJ3N1cGFiYXNlX3BnX25ldF9hZG1pbidcbiAgKVxuICBUSEVOXG4gICAgUkVBU1NJR04gT1dORUQgQlkgc3VwYWJhc2VfcGdfbmV0X2FkbWluIFRPIHN1cGFiYXNlX2FkbWluO1xuICAgIERST1AgT1dORUQgQlkgc3VwYWJhc2VfcGdfbmV0X2FkbWluO1xuICAgIERST1AgUk9MRSBzdXBhYmFzZV9wZ19uZXRfYWRtaW47XG4gIEVORCBJRjtcbkVORFxuJCQ7XG4tLSBwZ19uZXQgZ3JhbnRzIHdoZW4gZXh0ZW5zaW9uIGlzIGFscmVhZHkgZW5hYmxlZFxuRE9cbiQkXG5CRUdJTlxuICBJRiBFWElTVFMgKFxuICAgIFNFTEVDVCAxXG4gICAgRlJPTSBwZ19leHRlbnNpb25cbiAgICBXSEVSRSBleHRuYW1lID0gJ3BnX25ldCdcbiAgKVxuICBUSEVOXG4gICAgR1JBTlQgVVNBR0UgT04gU0NIRU1BIG5ldCBUTyBzdXBhYmFzZV9mdW5jdGlvbnNfYWRtaW4sIHBvc3RncmVzLCBhbm9uLCBhdXRoZW50aWNhdGVkLCBzZXJ2aWNlX3JvbGU7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfZ2V0KHVybCB0ZXh0LCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIFNFQ1VSSVRZIERFRklORVI7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfcG9zdCh1cmwgdGV4dCwgYm9keSBqc29uYiwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRUNVUklUWSBERUZJTkVSO1xuICAgIEFMVEVSIGZ1bmN0aW9uIG5ldC5odHRwX2dldCh1cmwgdGV4dCwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRVQgc2VhcmNoX3BhdGggPSBuZXQ7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfcG9zdCh1cmwgdGV4dCwgYm9keSBqc29uYiwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRVQgc2VhcmNoX3BhdGggPSBuZXQ7XG4gICAgUkVWT0tFIEFMTCBPTiBGVU5DVElPTiBuZXQuaHR0cF9nZXQodXJsIHRleHQsIHBhcmFtcyBqc29uYiwgaGVhZGVycyBqc29uYiwgdGltZW91dF9taWxsaXNlY29uZHMgaW50ZWdlcikgRlJPTSBQVUJMSUM7XG4gICAgUkVWT0tFIEFMTCBPTiBGVU5DVElPTiBuZXQuaHR0cF9wb3N0KHVybCB0ZXh0LCBib2R5IGpzb25iLCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIEZST00gUFVCTElDO1xuICAgIEdSQU5UIEVYRUNVVEUgT04gRlVOQ1RJT04gbmV0Lmh0dHBfZ2V0KHVybCB0ZXh0LCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIFRPIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbiwgcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbiAgICBHUkFOVCBFWEVDVVRFIE9OIEZVTkNUSU9OIG5ldC5odHRwX3Bvc3QodXJsIHRleHQsIGJvZHkganNvbmIsIHBhcmFtcyBqc29uYiwgaGVhZGVycyBqc29uYiwgdGltZW91dF9taWxsaXNlY29uZHMgaW50ZWdlcikgVE8gc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluLCBwb3N0Z3JlcywgYW5vbiwgYXV0aGVudGljYXRlZCwgc2VydmljZV9yb2xlO1xuICBFTkQgSUY7XG5FTkRcbiQkO1xuLS0gRXZlbnQgdHJpZ2dlciBmb3IgcGdfbmV0XG5DUkVBVEUgT1IgUkVQTEFDRSBGVU5DVElPTiBleHRlbnNpb25zLmdyYW50X3BnX25ldF9hY2Nlc3MoKVxuUkVUVVJOUyBldmVudF90cmlnZ2VyXG5MQU5HVUFHRSBwbHBnc3FsXG5BUyAkJFxuQkVHSU5cbiAgSUYgRVhJU1RTIChcbiAgICBTRUxFQ1QgMVxuICAgIEZST00gcGdfZXZlbnRfdHJpZ2dlcl9kZGxfY29tbWFuZHMoKSBBUyBldlxuICAgIEpPSU4gcGdfZXh0ZW5zaW9uIEFTIGV4dFxuICAgIE9OIGV2Lm9iamlkID0gZXh0Lm9pZFxuICAgIFdIRVJFIGV4dC5leHRuYW1lID0gJ3BnX25ldCdcbiAgKVxuICBUSEVOXG4gICAgR1JBTlQgVVNBR0UgT04gU0NIRU1BIG5ldCBUTyBzdXBhYmFzZV9mdW5jdGlvbnNfYWRtaW4sIHBvc3RncmVzLCBhbm9uLCBhdXRoZW50aWNhdGVkLCBzZXJ2aWNlX3JvbGU7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfZ2V0KHVybCB0ZXh0LCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIFNFQ1VSSVRZIERFRklORVI7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfcG9zdCh1cmwgdGV4dCwgYm9keSBqc29uYiwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRUNVUklUWSBERUZJTkVSO1xuICAgIEFMVEVSIGZ1bmN0aW9uIG5ldC5odHRwX2dldCh1cmwgdGV4dCwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRVQgc2VhcmNoX3BhdGggPSBuZXQ7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfcG9zdCh1cmwgdGV4dCwgYm9keSBqc29uYiwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRVQgc2VhcmNoX3BhdGggPSBuZXQ7XG4gICAgUkVWT0tFIEFMTCBPTiBGVU5DVElPTiBuZXQuaHR0cF9nZXQodXJsIHRleHQsIHBhcmFtcyBqc29uYiwgaGVhZGVycyBqc29uYiwgdGltZW91dF9taWxsaXNlY29uZHMgaW50ZWdlcikgRlJPTSBQVUJMSUM7XG4gICAgUkVWT0tFIEFMTCBPTiBGVU5DVElPTiBuZXQuaHR0cF9wb3N0KHVybCB0ZXh0LCBib2R5IGpzb25iLCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIEZST00gUFVCTElDO1xuICAgIEdSQU5UIEVYRUNVVEUgT04gRlVOQ1RJT04gbmV0Lmh0dHBfZ2V0KHVybCB0ZXh0LCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIFRPIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbiwgcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbiAgICBHUkFOVCBFWEVDVVRFIE9OIEZVTkNUSU9OIG5ldC5odHRwX3Bvc3QodXJsIHRleHQsIGJvZHkganNvbmIsIHBhcmFtcyBqc29uYiwgaGVhZGVycyBqc29uYiwgdGltZW91dF9taWxsaXNlY29uZHMgaW50ZWdlcikgVE8gc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluLCBwb3N0Z3JlcywgYW5vbiwgYXV0aGVudGljYXRlZCwgc2VydmljZV9yb2xlO1xuICBFTkQgSUY7XG5FTkQ7XG4kJDtcbkNPTU1FTlQgT04gRlVOQ1RJT04gZXh0ZW5zaW9ucy5ncmFudF9wZ19uZXRfYWNjZXNzIElTICdHcmFudHMgYWNjZXNzIHRvIHBnX25ldCc7XG5ET1xuJCRcbkJFR0lOXG4gIElGIE5PVCBFWElTVFMgKFxuICAgIFNFTEVDVCAxXG4gICAgRlJPTSBwZ19ldmVudF90cmlnZ2VyXG4gICAgV0hFUkUgZXZ0bmFtZSA9ICdpc3N1ZV9wZ19uZXRfYWNjZXNzJ1xuICApIFRIRU5cbiAgICBDUkVBVEUgRVZFTlQgVFJJR0dFUiBpc3N1ZV9wZ19uZXRfYWNjZXNzIE9OIGRkbF9jb21tYW5kX2VuZCBXSEVOIFRBRyBJTiAoJ0NSRUFURSBFWFRFTlNJT04nKVxuICAgIEVYRUNVVEUgUFJPQ0VEVVJFIGV4dGVuc2lvbnMuZ3JhbnRfcGdfbmV0X2FjY2VzcygpO1xuICBFTkQgSUY7XG5FTkRcbiQkO1xuSU5TRVJUIElOVE8gc3VwYWJhc2VfZnVuY3Rpb25zLm1pZ3JhdGlvbnMgKHZlcnNpb24pIFZBTFVFUyAoJzIwMjEwODA5MTgzNDIzX3VwZGF0ZV9ncmFudHMnKTtcbkFMVEVSIGZ1bmN0aW9uIHN1cGFiYXNlX2Z1bmN0aW9ucy5odHRwX3JlcXVlc3QoKSBTRUNVUklUWSBERUZJTkVSO1xuQUxURVIgZnVuY3Rpb24gc3VwYWJhc2VfZnVuY3Rpb25zLmh0dHBfcmVxdWVzdCgpIFNFVCBzZWFyY2hfcGF0aCA9IHN1cGFiYXNlX2Z1bmN0aW9ucztcblJFVk9LRSBBTEwgT04gRlVOQ1RJT04gc3VwYWJhc2VfZnVuY3Rpb25zLmh0dHBfcmVxdWVzdCgpIEZST00gUFVCTElDO1xuR1JBTlQgRVhFQ1VURSBPTiBGVU5DVElPTiBzdXBhYmFzZV9mdW5jdGlvbnMuaHR0cF9yZXF1ZXN0KCkgVE8gcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbkNPTU1JVDtcbiIKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9kYi9yb2xlcy5zcWwKICAgICAgICB0YXJnZXQ6IC9kb2NrZXItZW50cnlwb2ludC1pbml0ZGIuZC9pbml0LXNjcmlwdHMvOTktcm9sZXMuc3FsCiAgICAgICAgY29udGVudDogIi0tIE5PVEU6IGNoYW5nZSB0byB5b3VyIG93biBwYXNzd29yZHMgZm9yIHByb2R1Y3Rpb24gZW52aXJvbm1lbnRzXG4gXFxzZXQgcGdwYXNzIGBlY2hvIFwiJFBPU1RHUkVTX1BBU1NXT1JEXCJgXG5cbiBBTFRFUiBVU0VSIGF1dGhlbnRpY2F0b3IgV0lUSCBQQVNTV09SRCA6J3BncGFzcyc7XG4gQUxURVIgVVNFUiBwZ2JvdW5jZXIgV0lUSCBQQVNTV09SRCA6J3BncGFzcyc7XG4gQUxURVIgVVNFUiBzdXBhYmFzZV9hdXRoX2FkbWluIFdJVEggUEFTU1dPUkQgOidwZ3Bhc3MnO1xuIEFMVEVSIFVTRVIgc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluIFdJVEggUEFTU1dPUkQgOidwZ3Bhc3MnO1xuIEFMVEVSIFVTRVIgc3VwYWJhc2Vfc3RvcmFnZV9hZG1pbiBXSVRIIFBBU1NXT1JEIDoncGdwYXNzJztcbiIKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9kYi9qd3Quc3FsCiAgICAgICAgdGFyZ2V0OiAvZG9ja2VyLWVudHJ5cG9pbnQtaW5pdGRiLmQvaW5pdC1zY3JpcHRzLzk5LWp3dC5zcWwKICAgICAgICBjb250ZW50OiAiXFxzZXQgand0X3NlY3JldCBgZWNobyBcIiRKV1RfU0VDUkVUXCJgXG5cXHNldCBqd3RfZXhwIGBlY2hvIFwiJEpXVF9FWFBcImBcblxcc2V0IGRiX25hbWUgYGVjaG8gXCIke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc31cImBcblxuQUxURVIgREFUQUJBU0UgOmRiX25hbWUgU0VUIFwiYXBwLnNldHRpbmdzLmp3dF9zZWNyZXRcIiBUTyA6J2p3dF9zZWNyZXQnO1xuQUxURVIgREFUQUJBU0UgOmRiX25hbWUgU0VUIFwiYXBwLnNldHRpbmdzLmp3dF9leHBcIiBUTyA6J2p3dF9leHAnO1xuIgogICAgICAtCiAgICAgICAgdHlwZTogYmluZAogICAgICAgIHNvdXJjZTogLi92b2x1bWVzL2RiL2xvZ3Muc3FsCiAgICAgICAgdGFyZ2V0OiAvZG9ja2VyLWVudHJ5cG9pbnQtaW5pdGRiLmQvbWlncmF0aW9ucy85OS1sb2dzLnNxbAogICAgICAgIGNvbnRlbnQ6ICJcXHNldCBwZ3VzZXIgYGVjaG8gXCJzdXBhYmFzZV9hZG1pblwiYFxuXFxjIF9zdXBhYmFzZVxuY3JlYXRlIHNjaGVtYSBpZiBub3QgZXhpc3RzIF9hbmFseXRpY3M7XG5hbHRlciBzY2hlbWEgX2FuYWx5dGljcyBvd25lciB0byA6cGd1c2VyO1xuXFxjIHBvc3RncmVzXG4iCiAgICAgIC0gJ3N1cGFiYXNlLWRiLWNvbmZpZzovZXRjL3Bvc3RncmVzcWwtY3VzdG9tJwogIHN1cGFiYXNlLWFuYWx5dGljczoKICAgIGltYWdlOiAnc3VwYWJhc2UvbG9nZmxhcmU6MS40LjAnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gY3VybAogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6NDAwMC9oZWFsdGgnCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIGludGVydmFsOiA1cwogICAgICByZXRyaWVzOiAxMAogICAgZGVwZW5kc19vbjoKICAgICAgc3VwYWJhc2UtZGI6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIExPR0ZMQVJFX05PREVfSE9TVD0xMjcuMC4wLjEKICAgICAgLSBEQl9VU0VSTkFNRT1zdXBhYmFzZV9hZG1pbgogICAgICAtIERCX0RBVEFCQVNFPV9zdXBhYmFzZQogICAgICAtICdEQl9IT1NUTkFNRT0ke1BPU1RHUkVTX0hPU1ROQU1FOi1zdXBhYmFzZS1kYn0nCiAgICAgIC0gJ0RCX1BPUlQ9JHtQT1NUR1JFU19QT1JUOi01NDMyfScKICAgICAgLSAnREJfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSBEQl9TQ0hFTUE9X2FuYWx5dGljcwogICAgICAtICdMT0dGTEFSRV9BUElfS0VZPSR7U0VSVklDRV9QQVNTV09SRF9MT0dGTEFSRX0nCiAgICAgIC0gTE9HRkxBUkVfU0lOR0xFX1RFTkFOVD10cnVlCiAgICAgIC0gTE9HRkxBUkVfU0lOR0xFX1RFTkFOVF9NT0RFPXRydWUKICAgICAgLSBMT0dGTEFSRV9TVVBBQkFTRV9NT0RFPXRydWUKICAgICAgLSBMT0dGTEFSRV9NSU5fQ0xVU1RFUl9TSVpFPTEKICAgICAgLSAnUE9TVEdSRVNfQkFDS0VORF9VUkw9cG9zdGdyZXNxbDovL3N1cGFiYXNlX2FkbWluOiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU31AJHtQT1NUR1JFU19IT1NUTkFNRTotc3VwYWJhc2UtZGJ9OiR7UE9TVEdSRVNfUE9SVDotNTQzMn0vX3N1cGFiYXNlJwogICAgICAtIFBPU1RHUkVTX0JBQ0tFTkRfU0NIRU1BPV9hbmFseXRpY3MKICAgICAgLSBMT0dGTEFSRV9GRUFUVVJFX0ZMQUdfT1ZFUlJJREU9bXVsdGliYWNrZW5kPXRydWUKICBzdXBhYmFzZS12ZWN0b3I6CiAgICBpbWFnZTogJ3RpbWJlcmlvL3ZlY3RvcjowLjI4LjEtYWxwaW5lJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIHdnZXQKICAgICAgICAtICctLW5vLXZlcmJvc2UnCiAgICAgICAgLSAnLS10cmllcz0xJwogICAgICAgIC0gJy0tc3BpZGVyJwogICAgICAgIC0gJ2h0dHA6Ly9zdXBhYmFzZS12ZWN0b3I6OTAwMS9oZWFsdGgnCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIGludGVydmFsOiA1cwogICAgICByZXRyaWVzOiAzCiAgICB2b2x1bWVzOgogICAgICAtCiAgICAgICAgdHlwZTogYmluZAogICAgICAgIHNvdXJjZTogLi92b2x1bWVzL2xvZ3MvdmVjdG9yLnltbAogICAgICAgIHRhcmdldDogL2V0Yy92ZWN0b3IvdmVjdG9yLnltbAogICAgICAgIHJlYWRfb25seTogdHJ1ZQogICAgICAgIGNvbnRlbnQ6ICJhcGk6XG4gIGVuYWJsZWQ6IHRydWVcbiAgYWRkcmVzczogMC4wLjAuMDo5MDAxXG5cbnNvdXJjZXM6XG4gIGRvY2tlcl9ob3N0OlxuICAgIHR5cGU6IGRvY2tlcl9sb2dzXG4gICAgZXhjbHVkZV9jb250YWluZXJzOlxuICAgICAgLSBzdXBhYmFzZS12ZWN0b3JcblxudHJhbnNmb3JtczpcbiAgcHJvamVjdF9sb2dzOlxuICAgIHR5cGU6IHJlbWFwXG4gICAgaW5wdXRzOlxuICAgICAgLSBkb2NrZXJfaG9zdFxuICAgIHNvdXJjZTogfC1cbiAgICAgIC5wcm9qZWN0ID0gXCJkZWZhdWx0XCJcbiAgICAgIC5ldmVudF9tZXNzYWdlID0gZGVsKC5tZXNzYWdlKVxuICAgICAgLmFwcG5hbWUgPSBkZWwoLmNvbnRhaW5lcl9uYW1lKVxuICAgICAgZGVsKC5jb250YWluZXJfY3JlYXRlZF9hdClcbiAgICAgIGRlbCguY29udGFpbmVyX2lkKVxuICAgICAgZGVsKC5zb3VyY2VfdHlwZSlcbiAgICAgIGRlbCguc3RyZWFtKVxuICAgICAgZGVsKC5sYWJlbClcbiAgICAgIGRlbCguaW1hZ2UpXG4gICAgICBkZWwoLmhvc3QpXG4gICAgICBkZWwoLnN0cmVhbSlcbiAgcm91dGVyOlxuICAgIHR5cGU6IHJvdXRlXG4gICAgaW5wdXRzOlxuICAgICAgLSBwcm9qZWN0X2xvZ3NcbiAgICByb3V0ZTpcbiAgICAgIGtvbmc6ICdzdGFydHNfd2l0aChzdHJpbmchKC5hcHBuYW1lKSwgXCJzdXBhYmFzZS1rb25nXCIpJ1xuICAgICAgYXV0aDogJ3N0YXJ0c193aXRoKHN0cmluZyEoLmFwcG5hbWUpLCBcInN1cGFiYXNlLWF1dGhcIiknXG4gICAgICByZXN0OiAnc3RhcnRzX3dpdGgoc3RyaW5nISguYXBwbmFtZSksIFwic3VwYWJhc2UtcmVzdFwiKSdcbiAgICAgIHJlYWx0aW1lOiAnc3RhcnRzX3dpdGgoc3RyaW5nISguYXBwbmFtZSksIFwicmVhbHRpbWUtZGV2XCIpJ1xuICAgICAgc3RvcmFnZTogJ3N0YXJ0c193aXRoKHN0cmluZyEoLmFwcG5hbWUpLCBcInN1cGFiYXNlLXN0b3JhZ2VcIiknXG4gICAgICBmdW5jdGlvbnM6ICdzdGFydHNfd2l0aChzdHJpbmchKC5hcHBuYW1lKSwgXCJzdXBhYmFzZS1mdW5jdGlvbnNcIiknXG4gICAgICBkYjogJ3N0YXJ0c193aXRoKHN0cmluZyEoLmFwcG5hbWUpLCBcInN1cGFiYXNlLWRiXCIpJ1xuICAjIElnbm9yZXMgbm9uIG5naW54IGVycm9ycyBzaW5jZSB0aGV5IGFyZSByZWxhdGVkIHdpdGgga29uZyBib290aW5nIHVwXG4gIGtvbmdfbG9nczpcbiAgICB0eXBlOiByZW1hcFxuICAgIGlucHV0czpcbiAgICAgIC0gcm91dGVyLmtvbmdcbiAgICBzb3VyY2U6IHwtXG4gICAgICByZXEsIGVyciA9IHBhcnNlX25naW54X2xvZyguZXZlbnRfbWVzc2FnZSwgXCJjb21iaW5lZFwiKVxuICAgICAgaWYgZXJyID09IG51bGwge1xuICAgICAgICAgIC50aW1lc3RhbXAgPSByZXEudGltZXN0YW1wXG4gICAgICAgICAgLm1ldGFkYXRhLnJlcXVlc3QuaGVhZGVycy5yZWZlcmVyID0gcmVxLnJlZmVyZXJcbiAgICAgICAgICAubWV0YWRhdGEucmVxdWVzdC5oZWFkZXJzLnVzZXJfYWdlbnQgPSByZXEuYWdlbnRcbiAgICAgICAgICAubWV0YWRhdGEucmVxdWVzdC5oZWFkZXJzLmNmX2Nvbm5lY3RpbmdfaXAgPSByZXEuY2xpZW50XG4gICAgICAgICAgLm1ldGFkYXRhLnJlcXVlc3QubWV0aG9kID0gcmVxLm1ldGhvZFxuICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0LnBhdGggPSByZXEucGF0aFxuICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0LnByb3RvY29sID0gcmVxLnByb3RvY29sXG4gICAgICAgICAgLm1ldGFkYXRhLnJlc3BvbnNlLnN0YXR1c19jb2RlID0gcmVxLnN0YXR1c1xuICAgICAgfVxuICAgICAgaWYgZXJyICE9IG51bGwge1xuICAgICAgICBhYm9ydFxuICAgICAgfVxuICAjIElnbm9yZXMgbm9uIG5naW54IGVycm9ycyBzaW5jZSB0aGV5IGFyZSByZWxhdGVkIHdpdGgga29uZyBib290aW5nIHVwXG4gIGtvbmdfZXJyOlxuICAgIHR5cGU6IHJlbWFwXG4gICAgaW5wdXRzOlxuICAgICAgLSByb3V0ZXIua29uZ1xuICAgIHNvdXJjZTogfC1cbiAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0Lm1ldGhvZCA9IFwiR0VUXCJcbiAgICAgIC5tZXRhZGF0YS5yZXNwb25zZS5zdGF0dXNfY29kZSA9IDIwMFxuICAgICAgcGFyc2VkLCBlcnIgPSBwYXJzZV9uZ2lueF9sb2coLmV2ZW50X21lc3NhZ2UsIFwiZXJyb3JcIilcbiAgICAgIGlmIGVyciA9PSBudWxsIHtcbiAgICAgICAgICAudGltZXN0YW1wID0gcGFyc2VkLnRpbWVzdGFtcFxuICAgICAgICAgIC5zZXZlcml0eSA9IHBhcnNlZC5zZXZlcml0eVxuICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0Lmhvc3QgPSBwYXJzZWQuaG9zdFxuICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0LmhlYWRlcnMuY2ZfY29ubmVjdGluZ19pcCA9IHBhcnNlZC5jbGllbnRcbiAgICAgICAgICB1cmwsIGVyciA9IHNwbGl0KHBhcnNlZC5yZXF1ZXN0LCBcIiBcIilcbiAgICAgICAgICBpZiBlcnIgPT0gbnVsbCB7XG4gICAgICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0Lm1ldGhvZCA9IHVybFswXVxuICAgICAgICAgICAgICAubWV0YWRhdGEucmVxdWVzdC5wYXRoID0gdXJsWzFdXG4gICAgICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0LnByb3RvY29sID0gdXJsWzJdXG4gICAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgZXJyICE9IG51bGwge1xuICAgICAgICBhYm9ydFxuICAgICAgfVxuICAjIEdvdHJ1ZSBsb2dzIGFyZSBzdHJ1Y3R1cmVkIGpzb24gc3RyaW5ncyB3aGljaCBmcm9udGVuZCBwYXJzZXMgZGlyZWN0bHkuIEJ1dCB3ZSBrZWVwIG1ldGFkYXRhIGZvciBjb25zaXN0ZW5jeS5cbiAgYXV0aF9sb2dzOlxuICAgIHR5cGU6IHJlbWFwXG4gICAgaW5wdXRzOlxuICAgICAgLSByb3V0ZXIuYXV0aFxuICAgIHNvdXJjZTogfC1cbiAgICAgIHBhcnNlZCwgZXJyID0gcGFyc2VfanNvbiguZXZlbnRfbWVzc2FnZSlcbiAgICAgIGlmIGVyciA9PSBudWxsIHtcbiAgICAgICAgICAubWV0YWRhdGEudGltZXN0YW1wID0gcGFyc2VkLnRpbWVcbiAgICAgICAgICAubWV0YWRhdGEgPSBtZXJnZSEoLm1ldGFkYXRhLCBwYXJzZWQpXG4gICAgICB9XG4gICMgUG9zdGdSRVNUIGxvZ3MgYXJlIHN0cnVjdHVyZWQgc28gd2Ugc2VwYXJhdGUgdGltZXN0YW1wIGZyb20gbWVzc2FnZSB1c2luZyByZWdleFxuICByZXN0X2xvZ3M6XG4gICAgdHlwZTogcmVtYXBcbiAgICBpbnB1dHM6XG4gICAgICAtIHJvdXRlci5yZXN0XG4gICAgc291cmNlOiB8LVxuICAgICAgcGFyc2VkLCBlcnIgPSBwYXJzZV9yZWdleCguZXZlbnRfbWVzc2FnZSwgcideKD9QPHRpbWU+LiopOiAoP1A8bXNnPi4qKSQnKVxuICAgICAgaWYgZXJyID09IG51bGwge1xuICAgICAgICAgIC5ldmVudF9tZXNzYWdlID0gcGFyc2VkLm1zZ1xuICAgICAgICAgIC50aW1lc3RhbXAgPSB0b190aW1lc3RhbXAhKHBhcnNlZC50aW1lKVxuICAgICAgICAgIC5tZXRhZGF0YS5ob3N0ID0gLnByb2plY3RcbiAgICAgIH1cbiAgIyBSZWFsdGltZSBsb2dzIGFyZSBzdHJ1Y3R1cmVkIHNvIHdlIHBhcnNlIHRoZSBzZXZlcml0eSBsZXZlbCB1c2luZyByZWdleCAoaWdub3JlIHRpbWUgYmVjYXVzZSBpdCBoYXMgbm8gZGF0ZSlcbiAgcmVhbHRpbWVfbG9nczpcbiAgICB0eXBlOiByZW1hcFxuICAgIGlucHV0czpcbiAgICAgIC0gcm91dGVyLnJlYWx0aW1lXG4gICAgc291cmNlOiB8LVxuICAgICAgLm1ldGFkYXRhLnByb2plY3QgPSBkZWwoLnByb2plY3QpXG4gICAgICAubWV0YWRhdGEuZXh0ZXJuYWxfaWQgPSAubWV0YWRhdGEucHJvamVjdFxuICAgICAgcGFyc2VkLCBlcnIgPSBwYXJzZV9yZWdleCguZXZlbnRfbWVzc2FnZSwgcideKD9QPHRpbWU+XFxkKzpcXGQrOlxcZCtcXC5cXGQrKSBcXFsoP1A8bGV2ZWw+XFx3KylcXF0gKD9QPG1zZz4uKikkJylcbiAgICAgIGlmIGVyciA9PSBudWxsIHtcbiAgICAgICAgICAuZXZlbnRfbWVzc2FnZSA9IHBhcnNlZC5tc2dcbiAgICAgICAgICAubWV0YWRhdGEubGV2ZWwgPSBwYXJzZWQubGV2ZWxcbiAgICAgIH1cbiAgIyBTdG9yYWdlIGxvZ3MgbWF5IGNvbnRhaW4ganNvbiBvYmplY3RzIHNvIHdlIHBhcnNlIHRoZW0gZm9yIGNvbXBsZXRlbmVzc1xuICBzdG9yYWdlX2xvZ3M6XG4gICAgdHlwZTogcmVtYXBcbiAgICBpbnB1dHM6XG4gICAgICAtIHJvdXRlci5zdG9yYWdlXG4gICAgc291cmNlOiB8LVxuICAgICAgLm1ldGFkYXRhLnByb2plY3QgPSBkZWwoLnByb2plY3QpXG4gICAgICAubWV0YWRhdGEudGVuYW50SWQgPSAubWV0YWRhdGEucHJvamVjdFxuICAgICAgcGFyc2VkLCBlcnIgPSBwYXJzZV9qc29uKC5ldmVudF9tZXNzYWdlKVxuICAgICAgaWYgZXJyID09IG51bGwge1xuICAgICAgICAgIC5ldmVudF9tZXNzYWdlID0gcGFyc2VkLm1zZ1xuICAgICAgICAgIC5tZXRhZGF0YS5sZXZlbCA9IHBhcnNlZC5sZXZlbFxuICAgICAgICAgIC5tZXRhZGF0YS50aW1lc3RhbXAgPSBwYXJzZWQudGltZVxuICAgICAgICAgIC5tZXRhZGF0YS5jb250ZXh0WzBdLmhvc3QgPSBwYXJzZWQuaG9zdG5hbWVcbiAgICAgICAgICAubWV0YWRhdGEuY29udGV4dFswXS5waWQgPSBwYXJzZWQucGlkXG4gICAgICB9XG4gICMgUG9zdGdyZXMgbG9ncyBzb21lIG1lc3NhZ2VzIHRvIHN0ZGVyciB3aGljaCB3ZSBtYXAgdG8gd2FybmluZyBzZXZlcml0eSBsZXZlbFxuICBkYl9sb2dzOlxuICAgIHR5cGU6IHJlbWFwXG4gICAgaW5wdXRzOlxuICAgICAgLSByb3V0ZXIuZGJcbiAgICBzb3VyY2U6IHwtXG4gICAgICAubWV0YWRhdGEuaG9zdCA9IFwiZGItZGVmYXVsdFwiXG4gICAgICAubWV0YWRhdGEucGFyc2VkLnRpbWVzdGFtcCA9IC50aW1lc3RhbXBcblxuICAgICAgcGFyc2VkLCBlcnIgPSBwYXJzZV9yZWdleCguZXZlbnRfbWVzc2FnZSwgcicuKig/UDxsZXZlbD5JTkZPfE5PVElDRXxXQVJOSU5HfEVSUk9SfExPR3xGQVRBTHxQQU5JQz8pOi4qJywgbnVtZXJpY19ncm91cHM6IHRydWUpXG5cbiAgICAgIGlmIGVyciAhPSBudWxsIHx8IHBhcnNlZCA9PSBudWxsIHtcbiAgICAgICAgLm1ldGFkYXRhLnBhcnNlZC5lcnJvcl9zZXZlcml0eSA9IFwiaW5mb1wiXG4gICAgICB9XG4gICAgICBpZiBwYXJzZWQgIT0gbnVsbCB7XG4gICAgICAubWV0YWRhdGEucGFyc2VkLmVycm9yX3NldmVyaXR5ID0gcGFyc2VkLmxldmVsXG4gICAgICB9XG4gICAgICBpZiAubWV0YWRhdGEucGFyc2VkLmVycm9yX3NldmVyaXR5ID09IFwiaW5mb1wiIHtcbiAgICAgICAgICAubWV0YWRhdGEucGFyc2VkLmVycm9yX3NldmVyaXR5ID0gXCJsb2dcIlxuICAgICAgfVxuICAgICAgLm1ldGFkYXRhLnBhcnNlZC5lcnJvcl9zZXZlcml0eSA9IHVwY2FzZSEoLm1ldGFkYXRhLnBhcnNlZC5lcnJvcl9zZXZlcml0eSlcblxuc2lua3M6XG4gIGxvZ2ZsYXJlX2F1dGg6XG4gICAgdHlwZTogJ2h0dHAnXG4gICAgaW5wdXRzOlxuICAgICAgLSBhdXRoX2xvZ3NcbiAgICBlbmNvZGluZzpcbiAgICAgIGNvZGVjOiAnanNvbidcbiAgICBtZXRob2Q6ICdwb3N0J1xuICAgIHJlcXVlc3Q6XG4gICAgICByZXRyeV9tYXhfZHVyYXRpb25fc2VjczogMTBcbiAgICB1cmk6ICdodHRwOi8vc3VwYWJhc2UtYW5hbHl0aWNzOjQwMDAvYXBpL2xvZ3M/c291cmNlX25hbWU9Z290cnVlLmxvZ3MucHJvZCZhcGlfa2V5PSR7TE9HRkxBUkVfQVBJX0tFWT9MT0dGTEFSRV9BUElfS0VZIGlzIHJlcXVpcmVkfSdcbiAgbG9nZmxhcmVfcmVhbHRpbWU6XG4gICAgdHlwZTogJ2h0dHAnXG4gICAgaW5wdXRzOlxuICAgICAgLSByZWFsdGltZV9sb2dzXG4gICAgZW5jb2Rpbmc6XG4gICAgICBjb2RlYzogJ2pzb24nXG4gICAgbWV0aG9kOiAncG9zdCdcbiAgICByZXF1ZXN0OlxuICAgICAgcmV0cnlfbWF4X2R1cmF0aW9uX3NlY3M6IDEwXG4gICAgdXJpOiAnaHR0cDovL3N1cGFiYXNlLWFuYWx5dGljczo0MDAwL2FwaS9sb2dzP3NvdXJjZV9uYW1lPXJlYWx0aW1lLmxvZ3MucHJvZCZhcGlfa2V5PSR7TE9HRkxBUkVfQVBJX0tFWT9MT0dGTEFSRV9BUElfS0VZIGlzIHJlcXVpcmVkfSdcbiAgbG9nZmxhcmVfcmVzdDpcbiAgICB0eXBlOiAnaHR0cCdcbiAgICBpbnB1dHM6XG4gICAgICAtIHJlc3RfbG9nc1xuICAgIGVuY29kaW5nOlxuICAgICAgY29kZWM6ICdqc29uJ1xuICAgIG1ldGhvZDogJ3Bvc3QnXG4gICAgcmVxdWVzdDpcbiAgICAgIHJldHJ5X21heF9kdXJhdGlvbl9zZWNzOiAxMFxuICAgIHVyaTogJ2h0dHA6Ly9zdXBhYmFzZS1hbmFseXRpY3M6NDAwMC9hcGkvbG9ncz9zb3VyY2VfbmFtZT1wb3N0Z1JFU1QubG9ncy5wcm9kJmFwaV9rZXk9JHtMT0dGTEFSRV9BUElfS0VZP0xPR0ZMQVJFX0FQSV9LRVkgaXMgcmVxdWlyZWR9J1xuICBsb2dmbGFyZV9kYjpcbiAgICB0eXBlOiAnaHR0cCdcbiAgICBpbnB1dHM6XG4gICAgICAtIGRiX2xvZ3NcbiAgICBlbmNvZGluZzpcbiAgICAgIGNvZGVjOiAnanNvbidcbiAgICBtZXRob2Q6ICdwb3N0J1xuICAgIHJlcXVlc3Q6XG4gICAgICByZXRyeV9tYXhfZHVyYXRpb25fc2VjczogMTBcbiAgICAjIFdlIG11c3Qgcm91dGUgdGhlIHNpbmsgdGhyb3VnaCBrb25nIGJlY2F1c2UgaW5nZXN0aW5nIGxvZ3MgYmVmb3JlIGxvZ2ZsYXJlIGlzIGZ1bGx5IGluaXRpYWxpc2VkIHdpbGxcbiAgICAjIGxlYWQgdG8gYnJva2VuIHF1ZXJpZXMgZnJvbSBzdHVkaW8uIFRoaXMgd29ya3MgYnkgdGhlIGFzc3VtcHRpb24gdGhhdCBjb250YWluZXJzIGFyZSBzdGFydGVkIGluIHRoZVxuICAgICMgZm9sbG93aW5nIG9yZGVyOiB2ZWN0b3IgPiBkYiA+IGxvZ2ZsYXJlID4ga29uZ1xuICAgIHVyaTogJ2h0dHA6Ly9zdXBhYmFzZS1rb25nOjgwMDAvYW5hbHl0aWNzL3YxL2FwaS9sb2dzP3NvdXJjZV9uYW1lPXBvc3RncmVzLmxvZ3MmYXBpX2tleT0ke0xPR0ZMQVJFX0FQSV9LRVk/TE9HRkxBUkVfQVBJX0tFWSBpcyByZXF1aXJlZH0nXG4gIGxvZ2ZsYXJlX2Z1bmN0aW9uczpcbiAgICB0eXBlOiAnaHR0cCdcbiAgICBpbnB1dHM6XG4gICAgICAtIHJvdXRlci5mdW5jdGlvbnNcbiAgICBlbmNvZGluZzpcbiAgICAgIGNvZGVjOiAnanNvbidcbiAgICBtZXRob2Q6ICdwb3N0J1xuICAgIHJlcXVlc3Q6XG4gICAgICByZXRyeV9tYXhfZHVyYXRpb25fc2VjczogMTBcbiAgICB1cmk6ICdodHRwOi8vc3VwYWJhc2UtYW5hbHl0aWNzOjQwMDAvYXBpL2xvZ3M/c291cmNlX25hbWU9ZGVuby1yZWxheS1sb2dzJmFwaV9rZXk9JHtMT0dGTEFSRV9BUElfS0VZP0xPR0ZMQVJFX0FQSV9LRVkgaXMgcmVxdWlyZWR9J1xuICBsb2dmbGFyZV9zdG9yYWdlOlxuICAgIHR5cGU6ICdodHRwJ1xuICAgIGlucHV0czpcbiAgICAgIC0gc3RvcmFnZV9sb2dzXG4gICAgZW5jb2Rpbmc6XG4gICAgICBjb2RlYzogJ2pzb24nXG4gICAgbWV0aG9kOiAncG9zdCdcbiAgICByZXF1ZXN0OlxuICAgICAgcmV0cnlfbWF4X2R1cmF0aW9uX3NlY3M6IDEwXG4gICAgdXJpOiAnaHR0cDovL3N1cGFiYXNlLWFuYWx5dGljczo0MDAwL2FwaS9sb2dzP3NvdXJjZV9uYW1lPXN0b3JhZ2UubG9ncy5wcm9kLjImYXBpX2tleT0ke0xPR0ZMQVJFX0FQSV9LRVk/TE9HRkxBUkVfQVBJX0tFWSBpcyByZXF1aXJlZH0nXG4gIGxvZ2ZsYXJlX2tvbmc6XG4gICAgdHlwZTogJ2h0dHAnXG4gICAgaW5wdXRzOlxuICAgICAgLSBrb25nX2xvZ3NcbiAgICAgIC0ga29uZ19lcnJcbiAgICBlbmNvZGluZzpcbiAgICAgIGNvZGVjOiAnanNvbidcbiAgICBtZXRob2Q6ICdwb3N0J1xuICAgIHJlcXVlc3Q6XG4gICAgICByZXRyeV9tYXhfZHVyYXRpb25fc2VjczogMTBcbiAgICB1cmk6ICdodHRwOi8vc3VwYWJhc2UtYW5hbHl0aWNzOjQwMDAvYXBpL2xvZ3M/c291cmNlX25hbWU9Y2xvdWRmbGFyZS5sb2dzLnByb2QmYXBpX2tleT0ke0xPR0ZMQVJFX0FQSV9LRVk/TE9HRkxBUkVfQVBJX0tFWSBpcyByZXF1aXJlZH0nXG4iCiAgICAgIC0gJy92YXIvcnVuL2RvY2tlci5zb2NrOi92YXIvcnVuL2RvY2tlci5zb2NrOnJvJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ0xPR0ZMQVJFX0FQSV9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX0xPR0ZMQVJFfScKICAgIGNvbW1hbmQ6CiAgICAgIC0gJy0tY29uZmlnJwogICAgICAtIGV0Yy92ZWN0b3IvdmVjdG9yLnltbAogIHN1cGFiYXNlLXJlc3Q6CiAgICBpbWFnZTogJ3Bvc3RncmVzdC9wb3N0Z3Jlc3Q6djEyLjIuMCcKICAgIGRlcGVuZHNfb246CiAgICAgIHN1cGFiYXNlLWRiOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICAgIHN1cGFiYXNlLWFuYWx5dGljczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BHUlNUX0RCX1VSST1wb3N0Z3JlczovL2F1dGhlbnRpY2F0b3I6JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfUAke1BPU1RHUkVTX0hPU1ROQU1FOi1zdXBhYmFzZS1kYn06JHtQT1NUR1JFU19QT1JUOi01NDMyfS8ke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc30nCiAgICAgIC0gJ1BHUlNUX0RCX1NDSEVNQVM9JHtQR1JTVF9EQl9TQ0hFTUFTOi1wdWJsaWMsc3RvcmFnZSxncmFwaHFsX3B1YmxpY30nCiAgICAgIC0gUEdSU1RfREJfQU5PTl9ST0xFPWFub24KICAgICAgLSAnUEdSU1RfSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfSldUfScKICAgICAgLSBQR1JTVF9EQl9VU0VfTEVHQUNZX0dVQ1M9ZmFsc2UKICAgICAgLSAnUEdSU1RfQVBQX1NFVFRJTkdTX0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX0pXVH0nCiAgICAgIC0gJ1BHUlNUX0FQUF9TRVRUSU5HU19KV1RfRVhQPSR7SldUX0VYUElSWTotMzYwMH0nCiAgICBjb21tYW5kOiBwb3N0Z3Jlc3QKICAgIGV4Y2x1ZGVfZnJvbV9oYzogdHJ1ZQogIHN1cGFiYXNlLWF1dGg6CiAgICBpbWFnZTogJ3N1cGFiYXNlL2dvdHJ1ZTp2Mi4xNjQuMCcKICAgIGRlcGVuZHNfb246CiAgICAgIHN1cGFiYXNlLWRiOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICAgIHN1cGFiYXNlLWFuYWx5dGljczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIHdnZXQKICAgICAgICAtICctLW5vLXZlcmJvc2UnCiAgICAgICAgLSAnLS10cmllcz0xJwogICAgICAgIC0gJy0tc3BpZGVyJwogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6OTk5OS9oZWFsdGgnCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIGludGVydmFsOiA1cwogICAgICByZXRyaWVzOiAzCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBHT1RSVUVfQVBJX0hPU1Q9MC4wLjAuMAogICAgICAtIEdPVFJVRV9BUElfUE9SVD05OTk5CiAgICAgIC0gJ0FQSV9FWFRFUk5BTF9VUkw9JHtBUElfRVhURVJOQUxfVVJMOi1odHRwOi8vc3VwYWJhc2Uta29uZzo4MDAwfScKICAgICAgLSBHT1RSVUVfREJfRFJJVkVSPXBvc3RncmVzCiAgICAgIC0gJ0dPVFJVRV9EQl9EQVRBQkFTRV9VUkw9cG9zdGdyZXM6Ly9zdXBhYmFzZV9hdXRoX2FkbWluOiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU31AJHtQT1NUR1JFU19IT1NUTkFNRTotc3VwYWJhc2UtZGJ9OiR7UE9TVEdSRVNfUE9SVDotNTQzMn0vJHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtICdHT1RSVUVfU0lURV9VUkw9JHtTRVJWSUNFX0ZRRE5fU1VQQUJBU0VLT05HfScKICAgICAgLSAnR09UUlVFX1VSSV9BTExPV19MSVNUPSR7QURESVRJT05BTF9SRURJUkVDVF9VUkxTfScKICAgICAgLSAnR09UUlVFX0RJU0FCTEVfU0lHTlVQPSR7RElTQUJMRV9TSUdOVVA6LWZhbHNlfScKICAgICAgLSBHT1RSVUVfSldUX0FETUlOX1JPTEVTPXNlcnZpY2Vfcm9sZQogICAgICAtIEdPVFJVRV9KV1RfQVVEPWF1dGhlbnRpY2F0ZWQKICAgICAgLSBHT1RSVUVfSldUX0RFRkFVTFRfR1JPVVBfTkFNRT1hdXRoZW50aWNhdGVkCiAgICAgIC0gJ0dPVFJVRV9KV1RfRVhQPSR7SldUX0VYUElSWTotMzYwMH0nCiAgICAgIC0gJ0dPVFJVRV9KV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF9KV1R9JwogICAgICAtICdHT1RSVUVfRVhURVJOQUxfRU1BSUxfRU5BQkxFRD0ke0VOQUJMRV9FTUFJTF9TSUdOVVA6LXRydWV9JwogICAgICAtICdHT1RSVUVfRVhURVJOQUxfQU5PTllNT1VTX1VTRVJTX0VOQUJMRUQ9JHtFTkFCTEVfQU5PTllNT1VTX1VTRVJTOi1mYWxzZX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfQVVUT0NPTkZJUk09JHtFTkFCTEVfRU1BSUxfQVVUT0NPTkZJUk06LWZhbHNlfScKICAgICAgLSAnR09UUlVFX1NNVFBfQURNSU5fRU1BSUw9JHtTTVRQX0FETUlOX0VNQUlMfScKICAgICAgLSAnR09UUlVFX1NNVFBfSE9TVD0ke1NNVFBfSE9TVH0nCiAgICAgIC0gJ0dPVFJVRV9TTVRQX1BPUlQ9JHtTTVRQX1BPUlQ6LTU4N30nCiAgICAgIC0gJ0dPVFJVRV9TTVRQX1VTRVI9JHtTTVRQX1VTRVJ9JwogICAgICAtICdHT1RSVUVfU01UUF9QQVNTPSR7U01UUF9QQVNTfScKICAgICAgLSAnR09UUlVFX1NNVFBfU0VOREVSX05BTUU9JHtTTVRQX1NFTkRFUl9OQU1FfScKICAgICAgLSAnR09UUlVFX01BSUxFUl9VUkxQQVRIU19JTlZJVEU9JHtNQUlMRVJfVVJMUEFUSFNfSU5WSVRFOi0vYXV0aC92MS92ZXJpZnl9JwogICAgICAtICdHT1RSVUVfTUFJTEVSX1VSTFBBVEhTX0NPTkZJUk1BVElPTj0ke01BSUxFUl9VUkxQQVRIU19DT05GSVJNQVRJT046LS9hdXRoL3YxL3ZlcmlmeX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfVVJMUEFUSFNfUkVDT1ZFUlk9JHtNQUlMRVJfVVJMUEFUSFNfUkVDT1ZFUlk6LS9hdXRoL3YxL3ZlcmlmeX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfVVJMUEFUSFNfRU1BSUxfQ0hBTkdFPSR7TUFJTEVSX1VSTFBBVEhTX0VNQUlMX0NIQU5HRTotL2F1dGgvdjEvdmVyaWZ5fScKICAgICAgLSAnR09UUlVFX01BSUxFUl9URU1QTEFURVNfSU5WSVRFPSR7TUFJTEVSX1RFTVBMQVRFU19JTlZJVEV9JwogICAgICAtICdHT1RSVUVfTUFJTEVSX1RFTVBMQVRFU19DT05GSVJNQVRJT049JHtNQUlMRVJfVEVNUExBVEVTX0NPTkZJUk1BVElPTn0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfVEVNUExBVEVTX1JFQ09WRVJZPSR7TUFJTEVSX1RFTVBMQVRFU19SRUNPVkVSWX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfVEVNUExBVEVTX01BR0lDX0xJTks9JHtNQUlMRVJfVEVNUExBVEVTX01BR0lDX0xJTkt9JwogICAgICAtICdHT1RSVUVfTUFJTEVSX1RFTVBMQVRFU19FTUFJTF9DSEFOR0U9JHtNQUlMRVJfVEVNUExBVEVTX0VNQUlMX0NIQU5HRX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfU1VCSkVDVFNfQ09ORklSTUFUSU9OPSR7TUFJTEVSX1NVQkpFQ1RTX0NPTkZJUk1BVElPTn0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfU1VCSkVDVFNfUkVDT1ZFUlk9JHtNQUlMRVJfU1VCSkVDVFNfUkVDT1ZFUll9JwogICAgICAtICdHT1RSVUVfTUFJTEVSX1NVQkpFQ1RTX01BR0lDX0xJTks9JHtNQUlMRVJfU1VCSkVDVFNfTUFHSUNfTElOS30nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfU1VCSkVDVFNfRU1BSUxfQ0hBTkdFPSR7TUFJTEVSX1NVQkpFQ1RTX0VNQUlMX0NIQU5HRX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfU1VCSkVDVFNfSU5WSVRFPSR7TUFJTEVSX1NVQkpFQ1RTX0lOVklURX0nCiAgICAgIC0gJ0dPVFJVRV9FWFRFUk5BTF9QSE9ORV9FTkFCTEVEPSR7RU5BQkxFX1BIT05FX1NJR05VUDotdHJ1ZX0nCiAgICAgIC0gJ0dPVFJVRV9TTVNfQVVUT0NPTkZJUk09JHtFTkFCTEVfUEhPTkVfQVVUT0NPTkZJUk06LXRydWV9JwogIHJlYWx0aW1lLWRldjoKICAgIGltYWdlOiAnc3VwYWJhc2UvcmVhbHRpbWU6djIuMzMuNzAnCiAgICBjb250YWluZXJfbmFtZTogcmVhbHRpbWUtZGV2LnN1cGFiYXNlLXJlYWx0aW1lCiAgICBkZXBlbmRzX29uOgogICAgICBzdXBhYmFzZS1kYjoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBzdXBhYmFzZS1hbmFseXRpY3M6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLXNTZkwnCiAgICAgICAgLSAnLS1oZWFkJwogICAgICAgIC0gJy1vJwogICAgICAgIC0gL2Rldi9udWxsCiAgICAgICAgLSAnLUgnCiAgICAgICAgLSAnQXV0aG9yaXphdGlvbjogQmVhcmVyICR7U0VSVklDRV9TVVBBQkFTRUFOT05fS0VZfScKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjQwMDAvYXBpL3RlbmFudHMvcmVhbHRpbWUtZGV2L2hlYWx0aCcKICAgICAgdGltZW91dDogNXMKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHJldHJpZXM6IDMKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPUlQ9NDAwMAogICAgICAtICdEQl9IT1NUPSR7UE9TVEdSRVNfSE9TVE5BTUU6LXN1cGFiYXNlLWRifScKICAgICAgLSAnREJfUE9SVD0ke1BPU1RHUkVTX1BPUlQ6LTU0MzJ9JwogICAgICAtIERCX1VTRVI9c3VwYWJhc2VfYWRtaW4KICAgICAgLSAnREJfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnREJfTkFNRT0ke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc30nCiAgICAgIC0gJ0RCX0FGVEVSX0NPTk5FQ1RfUVVFUlk9U0VUIHNlYXJjaF9wYXRoIFRPIF9yZWFsdGltZScKICAgICAgLSBEQl9FTkNfS0VZPXN1cGFiYXNlcmVhbHRpbWUKICAgICAgLSAnQVBJX0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX0pXVH0nCiAgICAgIC0gRkxZX0FMTE9DX0lEPWZseTEyMwogICAgICAtIEZMWV9BUFBfTkFNRT1yZWFsdGltZQogICAgICAtICdTRUNSRVRfS0VZX0JBU0U9JHtTRUNSRVRfUEFTU1dPUkRfUkVBTFRJTUV9JwogICAgICAtICdFUkxfQUZMQUdTPS1wcm90b19kaXN0IGluZXRfdGNwJwogICAgICAtIEVOQUJMRV9UQUlMU0NBTEU9ZmFsc2UKICAgICAgLSAiRE5TX05PREVTPScnIgogICAgICAtIFJMSU1JVF9OT0ZJTEU9MTAwMDAKICAgICAgLSBBUFBfTkFNRT1yZWFsdGltZQogICAgICAtIFNFRURfU0VMRl9IT1NUPXRydWUKICAgICAgLSBMT0dfTEVWRUw9ZXJyb3IKICAgICAgLSBSVU5fSkFOSVRPUj10cnVlCiAgICAgIC0gSkFOSVRPUl9JTlRFUlZBTD02MDAwMAogICAgY29tbWFuZDogInNoIC1jIFwiL2FwcC9iaW4vbWlncmF0ZSAmJiAvYXBwL2Jpbi9yZWFsdGltZSBldmFsICdSZWFsdGltZS5SZWxlYXNlLnNlZWRzKFJlYWx0aW1lLlJlcG8pJyAmJiAvYXBwL2Jpbi9zZXJ2ZXJcIlxuIgogIHN1cGFiYXNlLW1pbmlvOgogICAgaW1hZ2U6IG1pbmlvL21pbmlvCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgY29tbWFuZDogJ3NlcnZlciAtLWNvbnNvbGUtYWRkcmVzcyAiOjkwMDEiIC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6ICdzbGVlcCA1ICYmIGV4aXQgMCcKICAgICAgaW50ZXJ2YWw6IDJzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiA1CiAgICB2b2x1bWVzOgogICAgICAtICcuL3ZvbHVtZXMvc3RvcmFnZTovZGF0YScKICBtaW5pby1jcmVhdGVidWNrZXQ6CiAgICBpbWFnZTogbWluaW8vbWMKICAgIHJlc3RhcnQ6ICdubycKICAgIGVudmlyb25tZW50OgogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBkZXBlbmRzX29uOgogICAgICBzdXBhYmFzZS1taW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW50cnlwb2ludDoKICAgICAgLSAvZW50cnlwb2ludC5zaAogICAgdm9sdW1lczoKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vZW50cnlwb2ludC5zaAogICAgICAgIHRhcmdldDogL2VudHJ5cG9pbnQuc2gKICAgICAgICBjb250ZW50OiAiIyEvYmluL3NoXG4vdXNyL2Jpbi9tYyBhbGlhcyBzZXQgc3VwYWJhc2UtbWluaW8gaHR0cDovL3N1cGFiYXNlLW1pbmlvOjkwMDAgJHtNSU5JT19ST09UX1VTRVJ9ICR7TUlOSU9fUk9PVF9QQVNTV09SRH07XG4vdXNyL2Jpbi9tYyBtYiAtLWlnbm9yZS1leGlzdGluZyBzdXBhYmFzZS1taW5pby9zdHViO1xuZXhpdCAwXG4iCiAgc3VwYWJhc2Utc3RvcmFnZToKICAgIGltYWdlOiAnc3VwYWJhc2Uvc3RvcmFnZS1hcGk6djEuMTQuNicKICAgIGRlcGVuZHNfb246CiAgICAgIHN1cGFiYXNlLWRiOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICAgIHN1cGFiYXNlLXJlc3Q6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgICAgaW1ncHJveHk6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSB3Z2V0CiAgICAgICAgLSAnLS1uby12ZXJib3NlJwogICAgICAgIC0gJy0tdHJpZXM9MScKICAgICAgICAtICctLXNwaWRlcicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjUwMDAvc3RhdHVzJwogICAgICB0aW1lb3V0OiA1cwogICAgICBpbnRlcnZhbDogNXMKICAgICAgcmV0cmllczogMwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVkVSX1BPUlQ9NTAwMAogICAgICAtIFNFUlZFUl9SRUdJT049bG9jYWwKICAgICAgLSBNVUxUSV9URU5BTlQ9ZmFsc2UKICAgICAgLSAnQVVUSF9KV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF9KV1R9JwogICAgICAtICdEQVRBQkFTRV9VUkw9cG9zdGdyZXM6Ly9zdXBhYmFzZV9zdG9yYWdlX2FkbWluOiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU31AJHtQT1NUR1JFU19IT1NUTkFNRTotc3VwYWJhc2UtZGJ9OiR7UE9TVEdSRVNfUE9SVDotNTQzMn0vJHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtIERCX0lOU1RBTExfUk9MRVM9ZmFsc2UKICAgICAgLSBTVE9SQUdFX0JBQ0tFTkQ9czMKICAgICAgLSBTVE9SQUdFX1MzX0JVQ0tFVD1zdHViCiAgICAgIC0gJ1NUT1JBR0VfUzNfRU5EUE9JTlQ9aHR0cDovL3N1cGFiYXNlLW1pbmlvOjkwMDAnCiAgICAgIC0gU1RPUkFHRV9TM19GT1JDRV9QQVRIX1NUWUxFPXRydWUKICAgICAgLSBTVE9SQUdFX1MzX1JFR0lPTj11cy1lYXN0LTEKICAgICAgLSAnQVdTX0FDQ0VTU19LRVlfSUQ9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdBV1NfU0VDUkVUX0FDQ0VTU19LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfScKICAgICAgLSBVUExPQURfRklMRV9TSVpFX0xJTUlUPTUyNDI4ODAwMAogICAgICAtIFVQTE9BRF9GSUxFX1NJWkVfTElNSVRfU1RBTkRBUkQ9NTI0Mjg4MDAwCiAgICAgIC0gVVBMT0FEX1NJR05FRF9VUkxfRVhQSVJBVElPTl9USU1FPTEyMAogICAgICAtIFRVU19VUkxfUEFUSD11cGxvYWQvcmVzdW1hYmxlCiAgICAgIC0gVFVTX01BWF9TSVpFPTM2MDAwMDAKICAgICAgLSBFTkFCTEVfSU1BR0VfVFJBTlNGT1JNQVRJT049dHJ1ZQogICAgICAtICdJTUdQUk9YWV9VUkw9aHR0cDovL2ltZ3Byb3h5OjgwODAnCiAgICAgIC0gSU1HUFJPWFlfUkVRVUVTVF9USU1FT1VUPTE1CiAgICAgIC0gREFUQUJBU0VfU0VBUkNIX1BBVEg9c3RvcmFnZQogICAgICAtIE5PREVfRU5WPXByb2R1Y3Rpb24KICAgICAgLSBSRVFVRVNUX0FMTE9XX1hfRk9SV0FSREVEX1BBVEg9dHJ1ZQogICAgdm9sdW1lczoKICAgICAgLSAnLi92b2x1bWVzL3N0b3JhZ2U6L3Zhci9saWIvc3RvcmFnZScKICBpbWdwcm94eToKICAgIGltYWdlOiAnZGFydGhzaW0vaW1ncHJveHk6djMuOC4wJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGltZ3Byb3h5CiAgICAgICAgLSBoZWFsdGgKICAgICAgdGltZW91dDogNXMKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHJldHJpZXM6IDMKICAgIGVudmlyb25tZW50OgogICAgICAtIElNR1BST1hZX0xPQ0FMX0ZJTEVTWVNURU1fUk9PVD0vCiAgICAgIC0gSU1HUFJPWFlfVVNFX0VUQUc9dHJ1ZQogICAgICAtICdJTUdQUk9YWV9FTkFCTEVfV0VCUF9ERVRFQ1RJT049JHtJTUdQUk9YWV9FTkFCTEVfV0VCUF9ERVRFQ1RJT046LXRydWV9JwogICAgdm9sdW1lczoKICAgICAgLSAnLi92b2x1bWVzL3N0b3JhZ2U6L3Zhci9saWIvc3RvcmFnZScKICBzdXBhYmFzZS1tZXRhOgogICAgaW1hZ2U6ICdzdXBhYmFzZS9wb3N0Z3Jlcy1tZXRhOnYwLjg0LjInCiAgICBkZXBlbmRzX29uOgogICAgICBzdXBhYmFzZS1kYjoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBzdXBhYmFzZS1hbmFseXRpY3M6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIFBHX01FVEFfUE9SVD04MDgwCiAgICAgIC0gJ1BHX01FVEFfREJfSE9TVD0ke1BPU1RHUkVTX0hPU1ROQU1FOi1zdXBhYmFzZS1kYn0nCiAgICAgIC0gJ1BHX01FVEFfREJfUE9SVD0ke1BPU1RHUkVTX1BPUlQ6LTU0MzJ9JwogICAgICAtICdQR19NRVRBX0RCX05BTUU9JHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtIFBHX01FVEFfREJfVVNFUj1zdXBhYmFzZV9hZG1pbgogICAgICAtICdQR19NRVRBX0RCX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgc3VwYWJhc2UtZWRnZS1mdW5jdGlvbnM6CiAgICBpbWFnZTogJ3N1cGFiYXNlL2VkZ2UtcnVudGltZTp2MS42NS4zJwogICAgZGVwZW5kc19vbjoKICAgICAgc3VwYWJhc2UtYW5hbHl0aWNzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gZWNobwogICAgICAgIC0gJ0VkZ2UgRnVuY3Rpb25zIGlzIGhlYWx0aHknCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIGludGVydmFsOiA1cwogICAgICByZXRyaWVzOiAzCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfSldUfScKICAgICAgLSAnU1VQQUJBU0VfVVJMPSR7U0VSVklDRV9GUUROX1NVUEFCQVNFS09OR30nCiAgICAgIC0gJ1NVUEFCQVNFX0FOT05fS0VZPSR7U0VSVklDRV9TVVBBQkFTRUFOT05fS0VZfScKICAgICAgLSAnU1VQQUJBU0VfU0VSVklDRV9ST0xFX0tFWT0ke1NFUlZJQ0VfU1VQQUJBU0VTRVJWSUNFX0tFWX0nCiAgICAgIC0gJ1NVUEFCQVNFX0RCX1VSTD1wb3N0Z3Jlc3FsOi8vcG9zdGdyZXM6JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfUAke1BPU1RHUkVTX0hPU1ROQU1FOi1zdXBhYmFzZS1kYn06JHtQT1NUR1JFU19QT1JUOi01NDMyfS8ke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc30nCiAgICAgIC0gJ1ZFUklGWV9KV1Q9JHtGVU5DVElPTlNfVkVSSUZZX0pXVDotZmFsc2V9JwogICAgdm9sdW1lczoKICAgICAgLSAnLi92b2x1bWVzL2Z1bmN0aW9uczovaG9tZS9kZW5vL2Z1bmN0aW9ucycKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9mdW5jdGlvbnMvbWFpbi9pbmRleC50cwogICAgICAgIHRhcmdldDogL2hvbWUvZGVuby9mdW5jdGlvbnMvbWFpbi9pbmRleC50cwogICAgICAgIGNvbnRlbnQ6ICJpbXBvcnQgeyBzZXJ2ZSB9IGZyb20gJ2h0dHBzOi8vZGVuby5sYW5kL3N0ZEAwLjEzMS4wL2h0dHAvc2VydmVyLnRzJ1xuaW1wb3J0ICogYXMgam9zZSBmcm9tICdodHRwczovL2Rlbm8ubGFuZC94L2pvc2VAdjQuMTQuNC9pbmRleC50cydcblxuY29uc29sZS5sb2coJ21haW4gZnVuY3Rpb24gc3RhcnRlZCcpXG5cbmNvbnN0IEpXVF9TRUNSRVQgPSBEZW5vLmVudi5nZXQoJ0pXVF9TRUNSRVQnKVxuY29uc3QgVkVSSUZZX0pXVCA9IERlbm8uZW52LmdldCgnVkVSSUZZX0pXVCcpID09PSAndHJ1ZSdcblxuZnVuY3Rpb24gZ2V0QXV0aFRva2VuKHJlcTogUmVxdWVzdCkge1xuICBjb25zdCBhdXRoSGVhZGVyID0gcmVxLmhlYWRlcnMuZ2V0KCdhdXRob3JpemF0aW9uJylcbiAgaWYgKCFhdXRoSGVhZGVyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIGF1dGhvcml6YXRpb24gaGVhZGVyJylcbiAgfVxuICBjb25zdCBbYmVhcmVyLCB0b2tlbl0gPSBhdXRoSGVhZGVyLnNwbGl0KCcgJylcbiAgaWYgKGJlYXJlciAhPT0gJ0JlYXJlcicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEF1dGggaGVhZGVyIGlzIG5vdCAnQmVhcmVyIHt0b2tlbn0nYClcbiAgfVxuICByZXR1cm4gdG9rZW5cbn1cblxuYXN5bmMgZnVuY3Rpb24gdmVyaWZ5SldUKGp3dDogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGNvbnN0IGVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKVxuICBjb25zdCBzZWNyZXRLZXkgPSBlbmNvZGVyLmVuY29kZShKV1RfU0VDUkVUKVxuICB0cnkge1xuICAgIGF3YWl0IGpvc2Uuand0VmVyaWZ5KGp3dCwgc2VjcmV0S2V5KVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBjb25zb2xlLmVycm9yKGVycilcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuICByZXR1cm4gdHJ1ZVxufVxuXG5zZXJ2ZShhc3luYyAocmVxOiBSZXF1ZXN0KSA9PiB7XG4gIGlmIChyZXEubWV0aG9kICE9PSAnT1BUSU9OUycgJiYgVkVSSUZZX0pXVCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB0b2tlbiA9IGdldEF1dGhUb2tlbihyZXEpXG4gICAgICBjb25zdCBpc1ZhbGlkSldUID0gYXdhaXQgdmVyaWZ5SldUKHRva2VuKVxuXG4gICAgICBpZiAoIWlzVmFsaWRKV1QpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBSZXNwb25zZShKU09OLnN0cmluZ2lmeSh7IG1zZzogJ0ludmFsaWQgSldUJyB9KSwge1xuICAgICAgICAgIHN0YXR1czogNDAxLFxuICAgICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgICB9KVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZSlcbiAgICAgIHJldHVybiBuZXcgUmVzcG9uc2UoSlNPTi5zdHJpbmdpZnkoeyBtc2c6IGUudG9TdHJpbmcoKSB9KSwge1xuICAgICAgICBzdGF0dXM6IDQwMSxcbiAgICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHVybCA9IG5ldyBVUkwocmVxLnVybClcbiAgY29uc3QgeyBwYXRobmFtZSB9ID0gdXJsXG4gIGNvbnN0IHBhdGhfcGFydHMgPSBwYXRobmFtZS5zcGxpdCgnLycpXG4gIGNvbnN0IHNlcnZpY2VfbmFtZSA9IHBhdGhfcGFydHNbMV1cblxuICBpZiAoIXNlcnZpY2VfbmFtZSB8fCBzZXJ2aWNlX25hbWUgPT09ICcnKSB7XG4gICAgY29uc3QgZXJyb3IgPSB7IG1zZzogJ21pc3NpbmcgZnVuY3Rpb24gbmFtZSBpbiByZXF1ZXN0JyB9XG4gICAgcmV0dXJuIG5ldyBSZXNwb25zZShKU09OLnN0cmluZ2lmeShlcnJvciksIHtcbiAgICAgIHN0YXR1czogNDAwLFxuICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sXG4gICAgfSlcbiAgfVxuXG4gIGNvbnN0IHNlcnZpY2VQYXRoID0gYC9ob21lL2Rlbm8vZnVuY3Rpb25zLyR7c2VydmljZV9uYW1lfWBcbiAgY29uc29sZS5lcnJvcihgc2VydmluZyB0aGUgcmVxdWVzdCB3aXRoICR7c2VydmljZVBhdGh9YClcblxuICBjb25zdCBtZW1vcnlMaW1pdE1iID0gMTUwXG4gIGNvbnN0IHdvcmtlclRpbWVvdXRNcyA9IDEgKiA2MCAqIDEwMDBcbiAgY29uc3Qgbm9Nb2R1bGVDYWNoZSA9IGZhbHNlXG4gIGNvbnN0IGltcG9ydE1hcFBhdGggPSBudWxsXG4gIGNvbnN0IGVudlZhcnNPYmogPSBEZW5vLmVudi50b09iamVjdCgpXG4gIGNvbnN0IGVudlZhcnMgPSBPYmplY3Qua2V5cyhlbnZWYXJzT2JqKS5tYXAoKGspID0+IFtrLCBlbnZWYXJzT2JqW2tdXSlcblxuICB0cnkge1xuICAgIGNvbnN0IHdvcmtlciA9IGF3YWl0IEVkZ2VSdW50aW1lLnVzZXJXb3JrZXJzLmNyZWF0ZSh7XG4gICAgICBzZXJ2aWNlUGF0aCxcbiAgICAgIG1lbW9yeUxpbWl0TWIsXG4gICAgICB3b3JrZXJUaW1lb3V0TXMsXG4gICAgICBub01vZHVsZUNhY2hlLFxuICAgICAgaW1wb3J0TWFwUGF0aCxcbiAgICAgIGVudlZhcnMsXG4gICAgfSlcbiAgICByZXR1cm4gYXdhaXQgd29ya2VyLmZldGNoKHJlcSlcbiAgfSBjYXRjaCAoZSkge1xuICAgIGNvbnN0IGVycm9yID0geyBtc2c6IGUudG9TdHJpbmcoKSB9XG4gICAgcmV0dXJuIG5ldyBSZXNwb25zZShKU09OLnN0cmluZ2lmeShlcnJvciksIHtcbiAgICAgIHN0YXR1czogNTAwLFxuICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sXG4gICAgfSlcbiAgfVxufSlcbiIKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9mdW5jdGlvbnMvaGVsbG8vaW5kZXgudHMKICAgICAgICB0YXJnZXQ6IC9ob21lL2Rlbm8vZnVuY3Rpb25zL2hlbGxvL2luZGV4LnRzCiAgICAgICAgY29udGVudDogIi8vIEZvbGxvdyB0aGlzIHNldHVwIGd1aWRlIHRvIGludGVncmF0ZSB0aGUgRGVubyBsYW5ndWFnZSBzZXJ2ZXIgd2l0aCB5b3VyIGVkaXRvcjpcbi8vIGh0dHBzOi8vZGVuby5sYW5kL21hbnVhbC9nZXR0aW5nX3N0YXJ0ZWQvc2V0dXBfeW91cl9lbnZpcm9ubWVudFxuLy8gVGhpcyBlbmFibGVzIGF1dG9jb21wbGV0ZSwgZ28gdG8gZGVmaW5pdGlvbiwgZXRjLlxuXG5pbXBvcnQgeyBzZXJ2ZSB9IGZyb20gXCJodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xNzcuMS9odHRwL3NlcnZlci50c1wiXG5cbnNlcnZlKGFzeW5jICgpID0+IHtcbiAgcmV0dXJuIG5ldyBSZXNwb25zZShcbiAgICBgXCJIZWxsbyBmcm9tIEVkZ2UgRnVuY3Rpb25zIVwiYCxcbiAgICB7IGhlYWRlcnM6IHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIgfSB9LFxuICApXG59KVxuXG4vLyBUbyBpbnZva2U6XG4vLyBjdXJsICdodHRwOi8vbG9jYWxob3N0OjxLT05HX0hUVFBfUE9SVD4vZnVuY3Rpb25zL3YxL2hlbGxvJyBcXFxuLy8gICAtLWhlYWRlciAnQXV0aG9yaXphdGlvbjogQmVhcmVyIDxhbm9uL3NlcnZpY2Vfcm9sZSBBUEkga2V5PidcbiIKICAgIGNvbW1hbmQ6CiAgICAgIC0gc3RhcnQKICAgICAgLSAnLS1tYWluLXNlcnZpY2UnCiAgICAgIC0gL2hvbWUvZGVuby9mdW5jdGlvbnMvbWFpbgogIHN1cGFiYXNlLXN1cGF2aXNvcjoKICAgIGltYWdlOiAnc3VwYWJhc2Uvc3VwYXZpc29yOjEuMS41NicKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLXNTZkwnCiAgICAgICAgLSAnLW8nCiAgICAgICAgLSAvZGV2L251bGwKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjQwMDAvYXBpL2hlYWx0aCcKICAgICAgdGltZW91dDogNXMKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHJldHJpZXM6IDEwCiAgICBkZXBlbmRzX29uOgogICAgICBzdXBhYmFzZS1kYjoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBzdXBhYmFzZS1hbmFseXRpY3M6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPT0xFUl9URU5BTlRfSUQ9ZGV2X3RlbmFudAogICAgICAtIFBPT0xFUl9QT09MX01PREU9dHJhbnNhY3Rpb24KICAgICAgLSAnUE9PTEVSX0RFRkFVTFRfUE9PTF9TSVpFPSR7UE9PTEVSX0RFRkFVTFRfUE9PTF9TSVpFOi0yMH0nCiAgICAgIC0gJ1BPT0xFUl9NQVhfQ0xJRU5UX0NPTk49JHtQT09MRVJfTUFYX0NMSUVOVF9DT05OOi0xMDB9JwogICAgICAtIFBPUlQ9NDAwMAogICAgICAtICdQT1NUR1JFU19QT1JUPSR7UE9TVEdSRVNfUE9SVDotNTQzMn0nCiAgICAgIC0gJ1BPU1RHUkVTX0hPU1ROQU1FPSR7UE9TVEdSRVNfSE9TVE5BTUU6LXN1cGFiYXNlLWRifScKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdEQVRBQkFTRV9VUkw9ZWN0bzovL3N1cGFiYXNlX2FkbWluOiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU31AJHtQT1NUR1JFU19IT1NUTkFNRTotc3VwYWJhc2UtZGJ9OiR7UE9TVEdSRVNfUE9SVDotNTQzMn0vX3N1cGFiYXNlJwogICAgICAtIENMVVNURVJfUE9TVEdSRVM9dHJ1ZQogICAgICAtICdTRUNSRVRfS0VZX0JBU0U9JHtTRVJWSUNFX1BBU1NXT1JEX1NVUEFWSVNPUlNFQ1JFVH0nCiAgICAgIC0gJ1ZBVUxUX0VOQ19LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX1ZBVUxURU5DfScKICAgICAgLSAnQVBJX0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX0pXVH0nCiAgICAgIC0gJ01FVFJJQ1NfSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfSldUfScKICAgICAgLSBSRUdJT049bG9jYWwKICAgICAgLSAnRVJMX0FGTEFHUz0tcHJvdG9fZGlzdCBpbmV0X3RjcCcKICAgIGNvbW1hbmQ6CiAgICAgIC0gL2Jpbi9zaAogICAgICAtICctYycKICAgICAgLSAnL2FwcC9iaW4vbWlncmF0ZSAmJiAvYXBwL2Jpbi9zdXBhdmlzb3IgZXZhbCAiJCQoY2F0IC9ldGMvcG9vbGVyL3Bvb2xlci5leHMpIiAmJiAvYXBwL2Jpbi9zZXJ2ZXInCiAgICB2b2x1bWVzOgogICAgICAtCiAgICAgICAgdHlwZTogYmluZAogICAgICAgIHNvdXJjZTogLi92b2x1bWVzL3Bvb2xlci9wb29sZXIuZXhzCiAgICAgICAgdGFyZ2V0OiAvZXRjL3Bvb2xlci9wb29sZXIuZXhzCiAgICAgICAgY29udGVudDogIns6b2ssIF99ID0gQXBwbGljYXRpb24uZW5zdXJlX2FsbF9zdGFydGVkKDpzdXBhdmlzb3IpXG57Om9rLCB2ZXJzaW9ufSA9XG4gICAgY2FzZSBTdXBhdmlzb3IuUmVwby5xdWVyeSEoXCJzZWxlY3QgdmVyc2lvbigpXCIpIGRvXG4gICAgJXtyb3dzOiBbW3Zlcl1dfSAtPiBTdXBhdmlzb3IuSGVscGVycy5wYXJzZV9wZ192ZXJzaW9uKHZlcilcbiAgICBfIC0+IG5pbFxuICAgIGVuZFxucGFyYW1zID0gJXtcbiAgICBcImV4dGVybmFsX2lkXCIgPT4gU3lzdGVtLmdldF9lbnYoXCJQT09MRVJfVEVOQU5UX0lEXCIpLFxuICAgIFwiZGJfaG9zdFwiID0+IFN5c3RlbS5nZXRfZW52KFwiUE9TVEdSRVNfSE9TVE5BTUVcIiksXG4gICAgXCJkYl9wb3J0XCIgPT4gU3lzdGVtLmdldF9lbnYoXCJQT1NUR1JFU19QT1JUXCIpIHw+IFN0cmluZy50b19pbnRlZ2VyKCksXG4gICAgXCJkYl9kYXRhYmFzZVwiID0+IFN5c3RlbS5nZXRfZW52KFwiUE9TVEdSRVNfREJcIiksXG4gICAgXCJyZXF1aXJlX3VzZXJcIiA9PiBmYWxzZSxcbiAgICBcImF1dGhfcXVlcnlcIiA9PiBcIlNFTEVDVCAqIEZST00gcGdib3VuY2VyLmdldF9hdXRoKCQxKVwiLFxuICAgIFwiZGVmYXVsdF9tYXhfY2xpZW50c1wiID0+IFN5c3RlbS5nZXRfZW52KFwiUE9PTEVSX01BWF9DTElFTlRfQ09OTlwiKSxcbiAgICBcImRlZmF1bHRfcG9vbF9zaXplXCIgPT4gU3lzdGVtLmdldF9lbnYoXCJQT09MRVJfREVGQVVMVF9QT09MX1NJWkVcIiksXG4gICAgXCJkZWZhdWx0X3BhcmFtZXRlcl9zdGF0dXNcIiA9PiAle1wic2VydmVyX3ZlcnNpb25cIiA9PiB2ZXJzaW9ufSxcbiAgICBcInVzZXJzXCIgPT4gWyV7XG4gICAgXCJkYl91c2VyXCIgPT4gXCJwZ2JvdW5jZXJcIixcbiAgICBcImRiX3Bhc3N3b3JkXCIgPT4gU3lzdGVtLmdldF9lbnYoXCJQT1NUR1JFU19QQVNTV09SRFwiKSxcbiAgICBcIm1vZGVfdHlwZVwiID0+IFN5c3RlbS5nZXRfZW52KFwiUE9PTEVSX1BPT0xfTU9ERVwiKSxcbiAgICBcInBvb2xfc2l6ZVwiID0+IFN5c3RlbS5nZXRfZW52KFwiUE9PTEVSX0RFRkFVTFRfUE9PTF9TSVpFXCIpLFxuICAgIFwiaXNfbWFuYWdlclwiID0+IHRydWVcbiAgICB9XVxufVxuXG50ZW5hbnQgPSBTdXBhdmlzb3IuVGVuYW50cy5nZXRfdGVuYW50X2J5X2V4dGVybmFsX2lkKHBhcmFtc1tcImV4dGVybmFsX2lkXCJdKVxuXG5pZiB0ZW5hbnQgZG9cbiAgezpvaywgX30gPSBTdXBhdmlzb3IuVGVuYW50cy51cGRhdGVfdGVuYW50KHRlbmFudCwgcGFyYW1zKVxuZWxzZVxuICB7Om9rLCBffSA9IFN1cGF2aXNvci5UZW5hbnRzLmNyZWF0ZV90ZW5hbnQocGFyYW1zKVxuZW5kXG4iCg==", + "compose": "c2VydmljZXM6CiAgc3VwYWJhc2Uta29uZzoKICAgIGltYWdlOiAna29uZzoyLjguMScKICAgIGVudHJ5cG9pbnQ6ICdiYXNoIC1jICcnZXZhbCAiZWNobyBcIiQkKGNhdCB+L3RlbXAueW1sKVwiIiA+IH4va29uZy55bWwgJiYgL2RvY2tlci1lbnRyeXBvaW50LnNoIGtvbmcgZG9ja2VyLXN0YXJ0JycnCiAgICBkZXBlbmRzX29uOgogICAgICBzdXBhYmFzZS1hbmFseXRpY3M6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9TVVBBQkFTRUtPTkdfODAwMAogICAgICAtICdLT05HX1BPUlRfTUFQUz00NDM6ODAwMCcKICAgICAgLSAnSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfSldUfScKICAgICAgLSBLT05HX0RBVEFCQVNFPW9mZgogICAgICAtIEtPTkdfREVDTEFSQVRJVkVfQ09ORklHPS9ob21lL2tvbmcva29uZy55bWwKICAgICAgLSAnS09OR19ETlNfT1JERVI9TEFTVCxBLENOQU1FJwogICAgICAtICdLT05HX1BMVUdJTlM9cmVxdWVzdC10cmFuc2Zvcm1lcixjb3JzLGtleS1hdXRoLGFjbCxiYXNpYy1hdXRoJwogICAgICAtIEtPTkdfTkdJTlhfUFJPWFlfUFJPWFlfQlVGRkVSX1NJWkU9MTYwawogICAgICAtICdLT05HX05HSU5YX1BST1hZX1BST1hZX0JVRkZFUlM9NjQgMTYwaycKICAgICAgLSAnU1VQQUJBU0VfQU5PTl9LRVk9JHtTRVJWSUNFX1NVUEFCQVNFQU5PTl9LRVl9JwogICAgICAtICdTVVBBQkFTRV9TRVJWSUNFX0tFWT0ke1NFUlZJQ0VfU1VQQUJBU0VTRVJWSUNFX0tFWX0nCiAgICAgIC0gJ0RBU0hCT0FSRF9VU0VSTkFNRT0ke1NFUlZJQ0VfVVNFUl9BRE1JTn0nCiAgICAgIC0gJ0RBU0hCT0FSRF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfQURNSU59JwogICAgdm9sdW1lczoKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9hcGkva29uZy55bWwKICAgICAgICB0YXJnZXQ6IC9ob21lL2tvbmcvdGVtcC55bWwKICAgICAgICBjb250ZW50OiAiX2Zvcm1hdF92ZXJzaW9uOiAnMi4xJ1xuX3RyYW5zZm9ybTogdHJ1ZVxuXG4jIyNcbiMjIyBDb25zdW1lcnMgLyBVc2Vyc1xuIyMjXG5jb25zdW1lcnM6XG4gIC0gdXNlcm5hbWU6IERBU0hCT0FSRFxuICAtIHVzZXJuYW1lOiBhbm9uXG4gICAga2V5YXV0aF9jcmVkZW50aWFsczpcbiAgICAgIC0ga2V5OiAkU1VQQUJBU0VfQU5PTl9LRVlcbiAgLSB1c2VybmFtZTogc2VydmljZV9yb2xlXG4gICAga2V5YXV0aF9jcmVkZW50aWFsczpcbiAgICAgIC0ga2V5OiAkU1VQQUJBU0VfU0VSVklDRV9LRVlcblxuIyMjXG4jIyMgQWNjZXNzIENvbnRyb2wgTGlzdFxuIyMjXG5hY2xzOlxuICAtIGNvbnN1bWVyOiBhbm9uXG4gICAgZ3JvdXA6IGFub25cbiAgLSBjb25zdW1lcjogc2VydmljZV9yb2xlXG4gICAgZ3JvdXA6IGFkbWluXG5cbiMjI1xuIyMjIERhc2hib2FyZCBjcmVkZW50aWFsc1xuIyMjXG5iYXNpY2F1dGhfY3JlZGVudGlhbHM6XG4tIGNvbnN1bWVyOiBEQVNIQk9BUkRcbiAgdXNlcm5hbWU6ICREQVNIQk9BUkRfVVNFUk5BTUVcbiAgcGFzc3dvcmQ6ICREQVNIQk9BUkRfUEFTU1dPUkRcblxuXG4jIyNcbiMjIyBBUEkgUm91dGVzXG4jIyNcbnNlcnZpY2VzOlxuXG4gICMjIE9wZW4gQXV0aCByb3V0ZXNcbiAgLSBuYW1lOiBhdXRoLXYxLW9wZW5cbiAgICB1cmw6IGh0dHA6Ly9zdXBhYmFzZS1hdXRoOjk5OTkvdmVyaWZ5XG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiBhdXRoLXYxLW9wZW5cbiAgICAgICAgc3RyaXBfcGF0aDogdHJ1ZVxuICAgICAgICBwYXRoczpcbiAgICAgICAgICAtIC9hdXRoL3YxL3ZlcmlmeVxuICAgIHBsdWdpbnM6XG4gICAgICAtIG5hbWU6IGNvcnNcbiAgLSBuYW1lOiBhdXRoLXYxLW9wZW4tY2FsbGJhY2tcbiAgICB1cmw6IGh0dHA6Ly9zdXBhYmFzZS1hdXRoOjk5OTkvY2FsbGJhY2tcbiAgICByb3V0ZXM6XG4gICAgICAtIG5hbWU6IGF1dGgtdjEtb3Blbi1jYWxsYmFja1xuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL2F1dGgvdjEvY2FsbGJhY2tcbiAgICBwbHVnaW5zOlxuICAgICAgLSBuYW1lOiBjb3JzXG4gIC0gbmFtZTogYXV0aC12MS1vcGVuLWF1dGhvcml6ZVxuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLWF1dGg6OTk5OS9hdXRob3JpemVcbiAgICByb3V0ZXM6XG4gICAgICAtIG5hbWU6IGF1dGgtdjEtb3Blbi1hdXRob3JpemVcbiAgICAgICAgc3RyaXBfcGF0aDogdHJ1ZVxuICAgICAgICBwYXRoczpcbiAgICAgICAgICAtIC9hdXRoL3YxL2F1dGhvcml6ZVxuICAgIHBsdWdpbnM6XG4gICAgICAtIG5hbWU6IGNvcnNcblxuICAjIyBTZWN1cmUgQXV0aCByb3V0ZXNcbiAgLSBuYW1lOiBhdXRoLXYxXG4gICAgX2NvbW1lbnQ6ICdHb1RydWU6IC9hdXRoL3YxLyogLT4gaHR0cDovL3N1cGFiYXNlLWF1dGg6OTk5OS8qJ1xuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLWF1dGg6OTk5OS9cbiAgICByb3V0ZXM6XG4gICAgICAtIG5hbWU6IGF1dGgtdjEtYWxsXG4gICAgICAgIHN0cmlwX3BhdGg6IHRydWVcbiAgICAgICAgcGF0aHM6XG4gICAgICAgICAgLSAvYXV0aC92MS9cbiAgICBwbHVnaW5zOlxuICAgICAgLSBuYW1lOiBjb3JzXG4gICAgICAtIG5hbWU6IGtleS1hdXRoXG4gICAgICAgIGNvbmZpZzpcbiAgICAgICAgICBoaWRlX2NyZWRlbnRpYWxzOiBmYWxzZVxuICAgICAgLSBuYW1lOiBhY2xcbiAgICAgICAgY29uZmlnOlxuICAgICAgICAgIGhpZGVfZ3JvdXBzX2hlYWRlcjogdHJ1ZVxuICAgICAgICAgIGFsbG93OlxuICAgICAgICAgICAgLSBhZG1pblxuICAgICAgICAgICAgLSBhbm9uXG5cbiAgIyMgU2VjdXJlIFJFU1Qgcm91dGVzXG4gIC0gbmFtZTogcmVzdC12MVxuICAgIF9jb21tZW50OiAnUG9zdGdSRVNUOiAvcmVzdC92MS8qIC0+IGh0dHA6Ly9zdXBhYmFzZS1yZXN0OjMwMDAvKidcbiAgICB1cmw6IGh0dHA6Ly9zdXBhYmFzZS1yZXN0OjMwMDAvXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiByZXN0LXYxLWFsbFxuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL3Jlc3QvdjEvXG4gICAgcGx1Z2luczpcbiAgICAgIC0gbmFtZTogY29yc1xuICAgICAgLSBuYW1lOiBrZXktYXV0aFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9jcmVkZW50aWFsczogdHJ1ZVxuICAgICAgLSBuYW1lOiBhY2xcbiAgICAgICAgY29uZmlnOlxuICAgICAgICAgIGhpZGVfZ3JvdXBzX2hlYWRlcjogdHJ1ZVxuICAgICAgICAgIGFsbG93OlxuICAgICAgICAgICAgLSBhZG1pblxuICAgICAgICAgICAgLSBhbm9uXG5cbiAgIyMgU2VjdXJlIEdyYXBoUUwgcm91dGVzXG4gIC0gbmFtZTogZ3JhcGhxbC12MVxuICAgIF9jb21tZW50OiAnUG9zdGdSRVNUOiAvZ3JhcGhxbC92MS8qIC0+IGh0dHA6Ly9zdXBhYmFzZS1yZXN0OjMwMDAvcnBjL2dyYXBocWwnXG4gICAgdXJsOiBodHRwOi8vc3VwYWJhc2UtcmVzdDozMDAwL3JwYy9ncmFwaHFsXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiBncmFwaHFsLXYxLWFsbFxuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL2dyYXBocWwvdjFcbiAgICBwbHVnaW5zOlxuICAgICAgLSBuYW1lOiBjb3JzXG4gICAgICAtIG5hbWU6IGtleS1hdXRoXG4gICAgICAgIGNvbmZpZzpcbiAgICAgICAgICBoaWRlX2NyZWRlbnRpYWxzOiB0cnVlXG4gICAgICAtIG5hbWU6IHJlcXVlc3QtdHJhbnNmb3JtZXJcbiAgICAgICAgY29uZmlnOlxuICAgICAgICAgIGFkZDpcbiAgICAgICAgICAgIGhlYWRlcnM6XG4gICAgICAgICAgICAgIC0gQ29udGVudC1Qcm9maWxlOmdyYXBocWxfcHVibGljXG4gICAgICAtIG5hbWU6IGFjbFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9ncm91cHNfaGVhZGVyOiB0cnVlXG4gICAgICAgICAgYWxsb3c6XG4gICAgICAgICAgICAtIGFkbWluXG4gICAgICAgICAgICAtIGFub25cblxuICAjIyBTZWN1cmUgUmVhbHRpbWUgcm91dGVzXG4gIC0gbmFtZTogcmVhbHRpbWUtdjEtd3NcbiAgICBfY29tbWVudDogJ1JlYWx0aW1lOiAvcmVhbHRpbWUvdjEvKiAtPiB3czovL3JlYWx0aW1lOjQwMDAvc29ja2V0LyonXG4gICAgdXJsOiBodHRwOi8vcmVhbHRpbWUtZGV2OjQwMDAvc29ja2V0XG4gICAgcHJvdG9jb2w6IHdzXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiByZWFsdGltZS12MS13c1xuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL3JlYWx0aW1lL3YxL1xuICAgIHBsdWdpbnM6XG4gICAgICAtIG5hbWU6IGNvcnNcbiAgICAgIC0gbmFtZToga2V5LWF1dGhcbiAgICAgICAgY29uZmlnOlxuICAgICAgICAgIGhpZGVfY3JlZGVudGlhbHM6IGZhbHNlXG4gICAgICAtIG5hbWU6IGFjbFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9ncm91cHNfaGVhZGVyOiB0cnVlXG4gICAgICAgICAgYWxsb3c6XG4gICAgICAgICAgICAtIGFkbWluXG4gICAgICAgICAgICAtIGFub25cbiAgLSBuYW1lOiByZWFsdGltZS12MS1yZXN0XG4gICAgX2NvbW1lbnQ6ICdSZWFsdGltZTogL3JlYWx0aW1lL3YxLyogLT4gd3M6Ly9yZWFsdGltZTo0MDAwL3NvY2tldC8qJ1xuICAgIHVybDogaHR0cDovL3JlYWx0aW1lLWRldjo0MDAwL2FwaVxuICAgIHByb3RvY29sOiBodHRwXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiByZWFsdGltZS12MS1yZXN0XG4gICAgICAgIHN0cmlwX3BhdGg6IHRydWVcbiAgICAgICAgcGF0aHM6XG4gICAgICAgICAgLSAvcmVhbHRpbWUvdjEvYXBpXG4gICAgcGx1Z2luczpcbiAgICAgIC0gbmFtZTogY29yc1xuICAgICAgLSBuYW1lOiBrZXktYXV0aFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9jcmVkZW50aWFsczogZmFsc2VcbiAgICAgIC0gbmFtZTogYWNsXG4gICAgICAgIGNvbmZpZzpcbiAgICAgICAgICBoaWRlX2dyb3Vwc19oZWFkZXI6IHRydWVcbiAgICAgICAgICBhbGxvdzpcbiAgICAgICAgICAgIC0gYWRtaW5cbiAgICAgICAgICAgIC0gYW5vblxuXG4gICMjIFN0b3JhZ2Ugcm91dGVzOiB0aGUgc3RvcmFnZSBzZXJ2ZXIgbWFuYWdlcyBpdHMgb3duIGF1dGhcbiAgLSBuYW1lOiBzdG9yYWdlLXYxXG4gICAgX2NvbW1lbnQ6ICdTdG9yYWdlOiAvc3RvcmFnZS92MS8qIC0+IGh0dHA6Ly9zdXBhYmFzZS1zdG9yYWdlOjUwMDAvKidcbiAgICB1cmw6IGh0dHA6Ly9zdXBhYmFzZS1zdG9yYWdlOjUwMDAvXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiBzdG9yYWdlLXYxLWFsbFxuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL3N0b3JhZ2UvdjEvXG4gICAgcGx1Z2luczpcbiAgICAgIC0gbmFtZTogY29yc1xuXG4gICMjIEVkZ2UgRnVuY3Rpb25zIHJvdXRlc1xuICAtIG5hbWU6IGZ1bmN0aW9ucy12MVxuICAgIF9jb21tZW50OiAnRWRnZSBGdW5jdGlvbnM6IC9mdW5jdGlvbnMvdjEvKiAtPiBodHRwOi8vc3VwYWJhc2UtZWRnZS1mdW5jdGlvbnM6OTAwMC8qJ1xuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLWVkZ2UtZnVuY3Rpb25zOjkwMDAvXG4gICAgcm91dGVzOlxuICAgICAgLSBuYW1lOiBmdW5jdGlvbnMtdjEtYWxsXG4gICAgICAgIHN0cmlwX3BhdGg6IHRydWVcbiAgICAgICAgcGF0aHM6XG4gICAgICAgICAgLSAvZnVuY3Rpb25zL3YxL1xuICAgIHBsdWdpbnM6XG4gICAgICAtIG5hbWU6IGNvcnNcblxuICAjIyBBbmFseXRpY3Mgcm91dGVzXG4gIC0gbmFtZTogYW5hbHl0aWNzLXYxXG4gICAgX2NvbW1lbnQ6ICdBbmFseXRpY3M6IC9hbmFseXRpY3MvdjEvKiAtPiBodHRwOi8vbG9nZmxhcmU6NDAwMC8qJ1xuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLWFuYWx5dGljczo0MDAwL1xuICAgIHJvdXRlczpcbiAgICAgIC0gbmFtZTogYW5hbHl0aWNzLXYxLWFsbFxuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL2FuYWx5dGljcy92MS9cblxuICAjIyBTZWN1cmUgRGF0YWJhc2Ugcm91dGVzXG4gIC0gbmFtZTogbWV0YVxuICAgIF9jb21tZW50OiAncGctbWV0YTogL3BnLyogLT4gaHR0cDovL3N1cGFiYXNlLW1ldGE6ODA4MC8qJ1xuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLW1ldGE6ODA4MC9cbiAgICByb3V0ZXM6XG4gICAgICAtIG5hbWU6IG1ldGEtYWxsXG4gICAgICAgIHN0cmlwX3BhdGg6IHRydWVcbiAgICAgICAgcGF0aHM6XG4gICAgICAgICAgLSAvcGcvXG4gICAgcGx1Z2luczpcbiAgICAgIC0gbmFtZToga2V5LWF1dGhcbiAgICAgICAgY29uZmlnOlxuICAgICAgICAgIGhpZGVfY3JlZGVudGlhbHM6IGZhbHNlXG4gICAgICAtIG5hbWU6IGFjbFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9ncm91cHNfaGVhZGVyOiB0cnVlXG4gICAgICAgICAgYWxsb3c6XG4gICAgICAgICAgICAtIGFkbWluXG5cbiAgIyMgUHJvdGVjdGVkIERhc2hib2FyZCAtIGNhdGNoIGFsbCByZW1haW5pbmcgcm91dGVzXG4gIC0gbmFtZTogZGFzaGJvYXJkXG4gICAgX2NvbW1lbnQ6ICdTdHVkaW86IC8qIC0+IGh0dHA6Ly9zdHVkaW86MzAwMC8qJ1xuICAgIHVybDogaHR0cDovL3N1cGFiYXNlLXN0dWRpbzozMDAwL1xuICAgIHJvdXRlczpcbiAgICAgIC0gbmFtZTogZGFzaGJvYXJkLWFsbFxuICAgICAgICBzdHJpcF9wYXRoOiB0cnVlXG4gICAgICAgIHBhdGhzOlxuICAgICAgICAgIC0gL1xuICAgIHBsdWdpbnM6XG4gICAgICAtIG5hbWU6IGNvcnNcbiAgICAgIC0gbmFtZTogYmFzaWMtYXV0aFxuICAgICAgICBjb25maWc6XG4gICAgICAgICAgaGlkZV9jcmVkZW50aWFsczogdHJ1ZVxuIgogIHN1cGFiYXNlLXN0dWRpbzoKICAgIGltYWdlOiAnc3VwYWJhc2Uvc3R1ZGlvOjIwMjQxMjAyLTcxZTUyNDAnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gbm9kZQogICAgICAgIC0gJy1lJwogICAgICAgIC0gInJlcXVpcmUoJ2h0dHAnKS5nZXQoJ2h0dHA6Ly8xMjcuMC4wLjE6MzAwMC9hcGkvcHJvZmlsZScsIChyKSA9PiB7aWYgKHIuc3RhdHVzQ29kZSAhPT0gMjAwKSBwcm9jZXNzLmV4aXQoMSk7IGVsc2UgcHJvY2Vzcy5leGl0KDApOyB9KS5vbignZXJyb3InLCAoKSA9PiBwcm9jZXNzLmV4aXQoMSkpIgogICAgICB0aW1lb3V0OiA1cwogICAgICBpbnRlcnZhbDogNXMKICAgICAgcmV0cmllczogMwogICAgZGVwZW5kc19vbjoKICAgICAgc3VwYWJhc2UtYW5hbHl0aWNzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBIT1NUTkFNRT0wLjAuMC4wCiAgICAgIC0gJ1NUVURJT19QR19NRVRBX1VSTD1odHRwOi8vc3VwYWJhc2UtbWV0YTo4MDgwJwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdERUZBVUxUX09SR0FOSVpBVElPTl9OQU1FPSR7U1RVRElPX0RFRkFVTFRfT1JHQU5JWkFUSU9OOi1EZWZhdWx0IE9yZ2FuaXphdGlvbn0nCiAgICAgIC0gJ0RFRkFVTFRfUFJPSkVDVF9OQU1FPSR7U1RVRElPX0RFRkFVTFRfUFJPSkVDVDotRGVmYXVsdCBQcm9qZWN0fScKICAgICAgLSAnU1VQQUJBU0VfVVJMPWh0dHA6Ly9zdXBhYmFzZS1rb25nOjgwMDAnCiAgICAgIC0gJ1NVUEFCQVNFX1BVQkxJQ19VUkw9JHtTRVJWSUNFX0ZRRE5fU1VQQUJBU0VLT05HfScKICAgICAgLSAnU1VQQUJBU0VfQU5PTl9LRVk9JHtTRVJWSUNFX1NVUEFCQVNFQU5PTl9LRVl9JwogICAgICAtICdTVVBBQkFTRV9TRVJWSUNFX0tFWT0ke1NFUlZJQ0VfU1VQQUJBU0VTRVJWSUNFX0tFWX0nCiAgICAgIC0gJ0FVVEhfSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfSldUfScKICAgICAgLSAnTE9HRkxBUkVfQVBJX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfTE9HRkxBUkV9JwogICAgICAtICdMT0dGTEFSRV9VUkw9aHR0cDovL3N1cGFiYXNlLWFuYWx5dGljczo0MDAwJwogICAgICAtICdTVVBBQkFTRV9QVUJMSUNfQVBJPSR7U0VSVklDRV9GUUROX1NVUEFCQVNFS09OR30nCiAgICAgIC0gTkVYVF9QVUJMSUNfRU5BQkxFX0xPR1M9dHJ1ZQogICAgICAtIE5FWFRfQU5BTFlUSUNTX0JBQ0tFTkRfUFJPVklERVI9cG9zdGdyZXMKICAgICAgLSAnT1BFTkFJX0FQSV9LRVk9JHtPUEVOQUlfQVBJX0tFWX0nCiAgc3VwYWJhc2UtZGI6CiAgICBpbWFnZTogJ3N1cGFiYXNlL3Bvc3RncmVzOjE1LjguMS4wNDgnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogJ3BnX2lzcmVhZHkgLVUgcG9zdGdyZXMgLWggMTI3LjAuMC4xJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogMTAKICAgIGRlcGVuZHNfb246CiAgICAgIHN1cGFiYXNlLXZlY3RvcjoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgY29tbWFuZDoKICAgICAgLSBwb3N0Z3JlcwogICAgICAtICctYycKICAgICAgLSBjb25maWdfZmlsZT0vZXRjL3Bvc3RncmVzcWwvcG9zdGdyZXNxbC5jb25mCiAgICAgIC0gJy1jJwogICAgICAtIGxvZ19taW5fbWVzc2FnZXM9ZmF0YWwKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX0hPU1Q9L3Zhci9ydW4vcG9zdGdyZXNxbAogICAgICAtICdQR1BPUlQ9JHtQT1NUR1JFU19QT1JUOi01NDMyfScKICAgICAgLSAnUE9TVEdSRVNfUE9SVD0ke1BPU1RHUkVTX1BPUlQ6LTU0MzJ9JwogICAgICAtICdQR1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BHREFUQUJBU0U9JHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc30nCiAgICAgIC0gJ0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX0pXVH0nCiAgICAgIC0gJ0pXVF9FWFA9JHtKV1RfRVhQSVJZOi0zNjAwfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3N1cGFiYXNlLWRiLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgICAtCiAgICAgICAgdHlwZTogYmluZAogICAgICAgIHNvdXJjZTogLi92b2x1bWVzL2RiL3JlYWx0aW1lLnNxbAogICAgICAgIHRhcmdldDogL2RvY2tlci1lbnRyeXBvaW50LWluaXRkYi5kL21pZ3JhdGlvbnMvOTktcmVhbHRpbWUuc3FsCiAgICAgICAgY29udGVudDogIlxcc2V0IHBndXNlciBgZWNobyBcInN1cGFiYXNlX2FkbWluXCJgXG5cbmNyZWF0ZSBzY2hlbWEgaWYgbm90IGV4aXN0cyBfcmVhbHRpbWU7XG5hbHRlciBzY2hlbWEgX3JlYWx0aW1lIG93bmVyIHRvIDpwZ3VzZXI7XG4iCiAgICAgIC0KICAgICAgICB0eXBlOiBiaW5kCiAgICAgICAgc291cmNlOiAuL3ZvbHVtZXMvZGIvX3N1cGFiYXNlLnNxbAogICAgICAgIHRhcmdldDogL2RvY2tlci1lbnRyeXBvaW50LWluaXRkYi5kL21pZ3JhdGlvbnMvOTctX3N1cGFiYXNlLnNxbAogICAgICAgIGNvbnRlbnQ6ICJcXHNldCBwZ3VzZXIgYGVjaG8gXCIkUE9TVEdSRVNfVVNFUlwiYFxuXG5DUkVBVEUgREFUQUJBU0UgX3N1cGFiYXNlIFdJVEggT1dORVIgOnBndXNlcjtcbiIKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9kYi9wb29sZXIuc3FsCiAgICAgICAgdGFyZ2V0OiAvZG9ja2VyLWVudHJ5cG9pbnQtaW5pdGRiLmQvbWlncmF0aW9ucy85OS1wb29sZXIuc3FsCiAgICAgICAgY29udGVudDogIlxcc2V0IHBndXNlciBgZWNobyBcInN1cGFiYXNlX2FkbWluXCJgXG5cXGMgX3N1cGFiYXNlXG5jcmVhdGUgc2NoZW1hIGlmIG5vdCBleGlzdHMgX3N1cGF2aXNvcjtcbmFsdGVyIHNjaGVtYSBfc3VwYXZpc29yIG93bmVyIHRvIDpwZ3VzZXI7XG5cXGMgcG9zdGdyZXNcbiIKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9kYi93ZWJob29rcy5zcWwKICAgICAgICB0YXJnZXQ6IC9kb2NrZXItZW50cnlwb2ludC1pbml0ZGIuZC9pbml0LXNjcmlwdHMvOTgtd2ViaG9va3Muc3FsCiAgICAgICAgY29udGVudDogIkJFR0lOO1xuLS0gQ3JlYXRlIHBnX25ldCBleHRlbnNpb25cbkNSRUFURSBFWFRFTlNJT04gSUYgTk9UIEVYSVNUUyBwZ19uZXQgU0NIRU1BIGV4dGVuc2lvbnM7XG4tLSBDcmVhdGUgc3VwYWJhc2VfZnVuY3Rpb25zIHNjaGVtYVxuQ1JFQVRFIFNDSEVNQSBzdXBhYmFzZV9mdW5jdGlvbnMgQVVUSE9SSVpBVElPTiBzdXBhYmFzZV9hZG1pbjtcbkdSQU5UIFVTQUdFIE9OIFNDSEVNQSBzdXBhYmFzZV9mdW5jdGlvbnMgVE8gcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbkFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBJTiBTQ0hFTUEgc3VwYWJhc2VfZnVuY3Rpb25zIEdSQU5UIEFMTCBPTiBUQUJMRVMgVE8gcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbkFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBJTiBTQ0hFTUEgc3VwYWJhc2VfZnVuY3Rpb25zIEdSQU5UIEFMTCBPTiBGVU5DVElPTlMgVE8gcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbkFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBJTiBTQ0hFTUEgc3VwYWJhc2VfZnVuY3Rpb25zIEdSQU5UIEFMTCBPTiBTRVFVRU5DRVMgVE8gcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbi0tIHN1cGFiYXNlX2Z1bmN0aW9ucy5taWdyYXRpb25zIGRlZmluaXRpb25cbkNSRUFURSBUQUJMRSBzdXBhYmFzZV9mdW5jdGlvbnMubWlncmF0aW9ucyAoXG4gIHZlcnNpb24gdGV4dCBQUklNQVJZIEtFWSxcbiAgaW5zZXJ0ZWRfYXQgdGltZXN0YW1wdHogTk9UIE5VTEwgREVGQVVMVCBOT1coKVxuKTtcbi0tIEluaXRpYWwgc3VwYWJhc2VfZnVuY3Rpb25zIG1pZ3JhdGlvblxuSU5TRVJUIElOVE8gc3VwYWJhc2VfZnVuY3Rpb25zLm1pZ3JhdGlvbnMgKHZlcnNpb24pIFZBTFVFUyAoJ2luaXRpYWwnKTtcbi0tIHN1cGFiYXNlX2Z1bmN0aW9ucy5ob29rcyBkZWZpbml0aW9uXG5DUkVBVEUgVEFCTEUgc3VwYWJhc2VfZnVuY3Rpb25zLmhvb2tzIChcbiAgaWQgYmlnc2VyaWFsIFBSSU1BUlkgS0VZLFxuICBob29rX3RhYmxlX2lkIGludGVnZXIgTk9UIE5VTEwsXG4gIGhvb2tfbmFtZSB0ZXh0IE5PVCBOVUxMLFxuICBjcmVhdGVkX2F0IHRpbWVzdGFtcHR6IE5PVCBOVUxMIERFRkFVTFQgTk9XKCksXG4gIHJlcXVlc3RfaWQgYmlnaW50XG4pO1xuQ1JFQVRFIElOREVYIHN1cGFiYXNlX2Z1bmN0aW9uc19ob29rc19yZXF1ZXN0X2lkX2lkeCBPTiBzdXBhYmFzZV9mdW5jdGlvbnMuaG9va3MgVVNJTkcgYnRyZWUgKHJlcXVlc3RfaWQpO1xuQ1JFQVRFIElOREVYIHN1cGFiYXNlX2Z1bmN0aW9uc19ob29rc19oX3RhYmxlX2lkX2hfbmFtZV9pZHggT04gc3VwYWJhc2VfZnVuY3Rpb25zLmhvb2tzIFVTSU5HIGJ0cmVlIChob29rX3RhYmxlX2lkLCBob29rX25hbWUpO1xuQ09NTUVOVCBPTiBUQUJMRSBzdXBhYmFzZV9mdW5jdGlvbnMuaG9va3MgSVMgJ1N1cGFiYXNlIEZ1bmN0aW9ucyBIb29rczogQXVkaXQgdHJhaWwgZm9yIHRyaWdnZXJlZCBob29rcy4nO1xuQ1JFQVRFIEZVTkNUSU9OIHN1cGFiYXNlX2Z1bmN0aW9ucy5odHRwX3JlcXVlc3QoKVxuICBSRVRVUk5TIHRyaWdnZXJcbiAgTEFOR1VBR0UgcGxwZ3NxbFxuICBBUyAkZnVuY3Rpb24kXG4gIERFQ0xBUkVcbiAgICByZXF1ZXN0X2lkIGJpZ2ludDtcbiAgICBwYXlsb2FkIGpzb25iO1xuICAgIHVybCB0ZXh0IDo9IFRHX0FSR1ZbMF06OnRleHQ7XG4gICAgbWV0aG9kIHRleHQgOj0gVEdfQVJHVlsxXTo6dGV4dDtcbiAgICBoZWFkZXJzIGpzb25iIERFRkFVTFQgJ3t9Jzo6anNvbmI7XG4gICAgcGFyYW1zIGpzb25iIERFRkFVTFQgJ3t9Jzo6anNvbmI7XG4gICAgdGltZW91dF9tcyBpbnRlZ2VyIERFRkFVTFQgMTAwMDtcbiAgQkVHSU5cbiAgICBJRiB1cmwgSVMgTlVMTCBPUiB1cmwgPSAnbnVsbCcgVEhFTlxuICAgICAgUkFJU0UgRVhDRVBUSU9OICd1cmwgYXJndW1lbnQgaXMgbWlzc2luZyc7XG4gICAgRU5EIElGO1xuXG4gICAgSUYgbWV0aG9kIElTIE5VTEwgT1IgbWV0aG9kID0gJ251bGwnIFRIRU5cbiAgICAgIFJBSVNFIEVYQ0VQVElPTiAnbWV0aG9kIGFyZ3VtZW50IGlzIG1pc3NpbmcnO1xuICAgIEVORCBJRjtcblxuICAgIElGIFRHX0FSR1ZbMl0gSVMgTlVMTCBPUiBUR19BUkdWWzJdID0gJ251bGwnIFRIRU5cbiAgICAgIGhlYWRlcnMgPSAne1wiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwifSc6Ompzb25iO1xuICAgIEVMU0VcbiAgICAgIGhlYWRlcnMgPSBUR19BUkdWWzJdOjpqc29uYjtcbiAgICBFTkQgSUY7XG5cbiAgICBJRiBUR19BUkdWWzNdIElTIE5VTEwgT1IgVEdfQVJHVlszXSA9ICdudWxsJyBUSEVOXG4gICAgICBwYXJhbXMgPSAne30nOjpqc29uYjtcbiAgICBFTFNFXG4gICAgICBwYXJhbXMgPSBUR19BUkdWWzNdOjpqc29uYjtcbiAgICBFTkQgSUY7XG5cbiAgICBJRiBUR19BUkdWWzRdIElTIE5VTEwgT1IgVEdfQVJHVls0XSA9ICdudWxsJyBUSEVOXG4gICAgICB0aW1lb3V0X21zID0gMTAwMDtcbiAgICBFTFNFXG4gICAgICB0aW1lb3V0X21zID0gVEdfQVJHVls0XTo6aW50ZWdlcjtcbiAgICBFTkQgSUY7XG5cbiAgICBDQVNFXG4gICAgICBXSEVOIG1ldGhvZCA9ICdHRVQnIFRIRU5cbiAgICAgICAgU0VMRUNUIGh0dHBfZ2V0IElOVE8gcmVxdWVzdF9pZCBGUk9NIG5ldC5odHRwX2dldChcbiAgICAgICAgICB1cmwsXG4gICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgIGhlYWRlcnMsXG4gICAgICAgICAgdGltZW91dF9tc1xuICAgICAgICApO1xuICAgICAgV0hFTiBtZXRob2QgPSAnUE9TVCcgVEhFTlxuICAgICAgICBwYXlsb2FkID0ganNvbmJfYnVpbGRfb2JqZWN0KFxuICAgICAgICAgICdvbGRfcmVjb3JkJywgT0xELFxuICAgICAgICAgICdyZWNvcmQnLCBORVcsXG4gICAgICAgICAgJ3R5cGUnLCBUR19PUCxcbiAgICAgICAgICAndGFibGUnLCBUR19UQUJMRV9OQU1FLFxuICAgICAgICAgICdzY2hlbWEnLCBUR19UQUJMRV9TQ0hFTUFcbiAgICAgICAgKTtcblxuICAgICAgICBTRUxFQ1QgaHR0cF9wb3N0IElOVE8gcmVxdWVzdF9pZCBGUk9NIG5ldC5odHRwX3Bvc3QoXG4gICAgICAgICAgdXJsLFxuICAgICAgICAgIHBheWxvYWQsXG4gICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgIGhlYWRlcnMsXG4gICAgICAgICAgdGltZW91dF9tc1xuICAgICAgICApO1xuICAgICAgRUxTRVxuICAgICAgICBSQUlTRSBFWENFUFRJT04gJ21ldGhvZCBhcmd1bWVudCAlIGlzIGludmFsaWQnLCBtZXRob2Q7XG4gICAgRU5EIENBU0U7XG5cbiAgICBJTlNFUlQgSU5UTyBzdXBhYmFzZV9mdW5jdGlvbnMuaG9va3NcbiAgICAgIChob29rX3RhYmxlX2lkLCBob29rX25hbWUsIHJlcXVlc3RfaWQpXG4gICAgVkFMVUVTXG4gICAgICAoVEdfUkVMSUQsIFRHX05BTUUsIHJlcXVlc3RfaWQpO1xuXG4gICAgUkVUVVJOIE5FVztcbiAgRU5EXG4kZnVuY3Rpb24kO1xuLS0gU3VwYWJhc2Ugc3VwZXIgYWRtaW5cbkRPXG4kJFxuQkVHSU5cbiAgSUYgTk9UIEVYSVNUUyAoXG4gICAgU0VMRUNUIDFcbiAgICBGUk9NIHBnX3JvbGVzXG4gICAgV0hFUkUgcm9sbmFtZSA9ICdzdXBhYmFzZV9mdW5jdGlvbnNfYWRtaW4nXG4gIClcbiAgVEhFTlxuICAgIENSRUFURSBVU0VSIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbiBOT0lOSEVSSVQgQ1JFQVRFUk9MRSBMT0dJTiBOT1JFUExJQ0FUSU9OO1xuICBFTkQgSUY7XG5FTkRcbiQkO1xuR1JBTlQgQUxMIFBSSVZJTEVHRVMgT04gU0NIRU1BIHN1cGFiYXNlX2Z1bmN0aW9ucyBUTyBzdXBhYmFzZV9mdW5jdGlvbnNfYWRtaW47XG5HUkFOVCBBTEwgUFJJVklMRUdFUyBPTiBBTEwgVEFCTEVTIElOIFNDSEVNQSBzdXBhYmFzZV9mdW5jdGlvbnMgVE8gc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluO1xuR1JBTlQgQUxMIFBSSVZJTEVHRVMgT04gQUxMIFNFUVVFTkNFUyBJTiBTQ0hFTUEgc3VwYWJhc2VfZnVuY3Rpb25zIFRPIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbjtcbkFMVEVSIFVTRVIgc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluIFNFVCBzZWFyY2hfcGF0aCA9IFwic3VwYWJhc2VfZnVuY3Rpb25zXCI7XG5BTFRFUiB0YWJsZSBcInN1cGFiYXNlX2Z1bmN0aW9uc1wiLm1pZ3JhdGlvbnMgT1dORVIgVE8gc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluO1xuQUxURVIgdGFibGUgXCJzdXBhYmFzZV9mdW5jdGlvbnNcIi5ob29rcyBPV05FUiBUTyBzdXBhYmFzZV9mdW5jdGlvbnNfYWRtaW47XG5BTFRFUiBmdW5jdGlvbiBcInN1cGFiYXNlX2Z1bmN0aW9uc1wiLmh0dHBfcmVxdWVzdCgpIE9XTkVSIFRPIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbjtcbkdSQU5UIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbiBUTyBwb3N0Z3Jlcztcbi0tIFJlbW92ZSB1bnVzZWQgc3VwYWJhc2VfcGdfbmV0X2FkbWluIHJvbGVcbkRPXG4kJFxuQkVHSU5cbiAgSUYgRVhJU1RTIChcbiAgICBTRUxFQ1QgMVxuICAgIEZST00gcGdfcm9sZXNcbiAgICBXSEVSRSByb2xuYW1lID0gJ3N1cGFiYXNlX3BnX25ldF9hZG1pbidcbiAgKVxuICBUSEVOXG4gICAgUkVBU1NJR04gT1dORUQgQlkgc3VwYWJhc2VfcGdfbmV0X2FkbWluIFRPIHN1cGFiYXNlX2FkbWluO1xuICAgIERST1AgT1dORUQgQlkgc3VwYWJhc2VfcGdfbmV0X2FkbWluO1xuICAgIERST1AgUk9MRSBzdXBhYmFzZV9wZ19uZXRfYWRtaW47XG4gIEVORCBJRjtcbkVORFxuJCQ7XG4tLSBwZ19uZXQgZ3JhbnRzIHdoZW4gZXh0ZW5zaW9uIGlzIGFscmVhZHkgZW5hYmxlZFxuRE9cbiQkXG5CRUdJTlxuICBJRiBFWElTVFMgKFxuICAgIFNFTEVDVCAxXG4gICAgRlJPTSBwZ19leHRlbnNpb25cbiAgICBXSEVSRSBleHRuYW1lID0gJ3BnX25ldCdcbiAgKVxuICBUSEVOXG4gICAgR1JBTlQgVVNBR0UgT04gU0NIRU1BIG5ldCBUTyBzdXBhYmFzZV9mdW5jdGlvbnNfYWRtaW4sIHBvc3RncmVzLCBhbm9uLCBhdXRoZW50aWNhdGVkLCBzZXJ2aWNlX3JvbGU7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfZ2V0KHVybCB0ZXh0LCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIFNFQ1VSSVRZIERFRklORVI7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfcG9zdCh1cmwgdGV4dCwgYm9keSBqc29uYiwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRUNVUklUWSBERUZJTkVSO1xuICAgIEFMVEVSIGZ1bmN0aW9uIG5ldC5odHRwX2dldCh1cmwgdGV4dCwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRVQgc2VhcmNoX3BhdGggPSBuZXQ7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfcG9zdCh1cmwgdGV4dCwgYm9keSBqc29uYiwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRVQgc2VhcmNoX3BhdGggPSBuZXQ7XG4gICAgUkVWT0tFIEFMTCBPTiBGVU5DVElPTiBuZXQuaHR0cF9nZXQodXJsIHRleHQsIHBhcmFtcyBqc29uYiwgaGVhZGVycyBqc29uYiwgdGltZW91dF9taWxsaXNlY29uZHMgaW50ZWdlcikgRlJPTSBQVUJMSUM7XG4gICAgUkVWT0tFIEFMTCBPTiBGVU5DVElPTiBuZXQuaHR0cF9wb3N0KHVybCB0ZXh0LCBib2R5IGpzb25iLCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIEZST00gUFVCTElDO1xuICAgIEdSQU5UIEVYRUNVVEUgT04gRlVOQ1RJT04gbmV0Lmh0dHBfZ2V0KHVybCB0ZXh0LCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIFRPIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbiwgcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbiAgICBHUkFOVCBFWEVDVVRFIE9OIEZVTkNUSU9OIG5ldC5odHRwX3Bvc3QodXJsIHRleHQsIGJvZHkganNvbmIsIHBhcmFtcyBqc29uYiwgaGVhZGVycyBqc29uYiwgdGltZW91dF9taWxsaXNlY29uZHMgaW50ZWdlcikgVE8gc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluLCBwb3N0Z3JlcywgYW5vbiwgYXV0aGVudGljYXRlZCwgc2VydmljZV9yb2xlO1xuICBFTkQgSUY7XG5FTkRcbiQkO1xuLS0gRXZlbnQgdHJpZ2dlciBmb3IgcGdfbmV0XG5DUkVBVEUgT1IgUkVQTEFDRSBGVU5DVElPTiBleHRlbnNpb25zLmdyYW50X3BnX25ldF9hY2Nlc3MoKVxuUkVUVVJOUyBldmVudF90cmlnZ2VyXG5MQU5HVUFHRSBwbHBnc3FsXG5BUyAkJFxuQkVHSU5cbiAgSUYgRVhJU1RTIChcbiAgICBTRUxFQ1QgMVxuICAgIEZST00gcGdfZXZlbnRfdHJpZ2dlcl9kZGxfY29tbWFuZHMoKSBBUyBldlxuICAgIEpPSU4gcGdfZXh0ZW5zaW9uIEFTIGV4dFxuICAgIE9OIGV2Lm9iamlkID0gZXh0Lm9pZFxuICAgIFdIRVJFIGV4dC5leHRuYW1lID0gJ3BnX25ldCdcbiAgKVxuICBUSEVOXG4gICAgR1JBTlQgVVNBR0UgT04gU0NIRU1BIG5ldCBUTyBzdXBhYmFzZV9mdW5jdGlvbnNfYWRtaW4sIHBvc3RncmVzLCBhbm9uLCBhdXRoZW50aWNhdGVkLCBzZXJ2aWNlX3JvbGU7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfZ2V0KHVybCB0ZXh0LCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIFNFQ1VSSVRZIERFRklORVI7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfcG9zdCh1cmwgdGV4dCwgYm9keSBqc29uYiwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRUNVUklUWSBERUZJTkVSO1xuICAgIEFMVEVSIGZ1bmN0aW9uIG5ldC5odHRwX2dldCh1cmwgdGV4dCwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRVQgc2VhcmNoX3BhdGggPSBuZXQ7XG4gICAgQUxURVIgZnVuY3Rpb24gbmV0Lmh0dHBfcG9zdCh1cmwgdGV4dCwgYm9keSBqc29uYiwgcGFyYW1zIGpzb25iLCBoZWFkZXJzIGpzb25iLCB0aW1lb3V0X21pbGxpc2Vjb25kcyBpbnRlZ2VyKSBTRVQgc2VhcmNoX3BhdGggPSBuZXQ7XG4gICAgUkVWT0tFIEFMTCBPTiBGVU5DVElPTiBuZXQuaHR0cF9nZXQodXJsIHRleHQsIHBhcmFtcyBqc29uYiwgaGVhZGVycyBqc29uYiwgdGltZW91dF9taWxsaXNlY29uZHMgaW50ZWdlcikgRlJPTSBQVUJMSUM7XG4gICAgUkVWT0tFIEFMTCBPTiBGVU5DVElPTiBuZXQuaHR0cF9wb3N0KHVybCB0ZXh0LCBib2R5IGpzb25iLCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIEZST00gUFVCTElDO1xuICAgIEdSQU5UIEVYRUNVVEUgT04gRlVOQ1RJT04gbmV0Lmh0dHBfZ2V0KHVybCB0ZXh0LCBwYXJhbXMganNvbmIsIGhlYWRlcnMganNvbmIsIHRpbWVvdXRfbWlsbGlzZWNvbmRzIGludGVnZXIpIFRPIHN1cGFiYXNlX2Z1bmN0aW9uc19hZG1pbiwgcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbiAgICBHUkFOVCBFWEVDVVRFIE9OIEZVTkNUSU9OIG5ldC5odHRwX3Bvc3QodXJsIHRleHQsIGJvZHkganNvbmIsIHBhcmFtcyBqc29uYiwgaGVhZGVycyBqc29uYiwgdGltZW91dF9taWxsaXNlY29uZHMgaW50ZWdlcikgVE8gc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluLCBwb3N0Z3JlcywgYW5vbiwgYXV0aGVudGljYXRlZCwgc2VydmljZV9yb2xlO1xuICBFTkQgSUY7XG5FTkQ7XG4kJDtcbkNPTU1FTlQgT04gRlVOQ1RJT04gZXh0ZW5zaW9ucy5ncmFudF9wZ19uZXRfYWNjZXNzIElTICdHcmFudHMgYWNjZXNzIHRvIHBnX25ldCc7XG5ET1xuJCRcbkJFR0lOXG4gIElGIE5PVCBFWElTVFMgKFxuICAgIFNFTEVDVCAxXG4gICAgRlJPTSBwZ19ldmVudF90cmlnZ2VyXG4gICAgV0hFUkUgZXZ0bmFtZSA9ICdpc3N1ZV9wZ19uZXRfYWNjZXNzJ1xuICApIFRIRU5cbiAgICBDUkVBVEUgRVZFTlQgVFJJR0dFUiBpc3N1ZV9wZ19uZXRfYWNjZXNzIE9OIGRkbF9jb21tYW5kX2VuZCBXSEVOIFRBRyBJTiAoJ0NSRUFURSBFWFRFTlNJT04nKVxuICAgIEVYRUNVVEUgUFJPQ0VEVVJFIGV4dGVuc2lvbnMuZ3JhbnRfcGdfbmV0X2FjY2VzcygpO1xuICBFTkQgSUY7XG5FTkRcbiQkO1xuSU5TRVJUIElOVE8gc3VwYWJhc2VfZnVuY3Rpb25zLm1pZ3JhdGlvbnMgKHZlcnNpb24pIFZBTFVFUyAoJzIwMjEwODA5MTgzNDIzX3VwZGF0ZV9ncmFudHMnKTtcbkFMVEVSIGZ1bmN0aW9uIHN1cGFiYXNlX2Z1bmN0aW9ucy5odHRwX3JlcXVlc3QoKSBTRUNVUklUWSBERUZJTkVSO1xuQUxURVIgZnVuY3Rpb24gc3VwYWJhc2VfZnVuY3Rpb25zLmh0dHBfcmVxdWVzdCgpIFNFVCBzZWFyY2hfcGF0aCA9IHN1cGFiYXNlX2Z1bmN0aW9ucztcblJFVk9LRSBBTEwgT04gRlVOQ1RJT04gc3VwYWJhc2VfZnVuY3Rpb25zLmh0dHBfcmVxdWVzdCgpIEZST00gUFVCTElDO1xuR1JBTlQgRVhFQ1VURSBPTiBGVU5DVElPTiBzdXBhYmFzZV9mdW5jdGlvbnMuaHR0cF9yZXF1ZXN0KCkgVE8gcG9zdGdyZXMsIGFub24sIGF1dGhlbnRpY2F0ZWQsIHNlcnZpY2Vfcm9sZTtcbkNPTU1JVDtcbiIKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9kYi9yb2xlcy5zcWwKICAgICAgICB0YXJnZXQ6IC9kb2NrZXItZW50cnlwb2ludC1pbml0ZGIuZC9pbml0LXNjcmlwdHMvOTktcm9sZXMuc3FsCiAgICAgICAgY29udGVudDogIi0tIE5PVEU6IGNoYW5nZSB0byB5b3VyIG93biBwYXNzd29yZHMgZm9yIHByb2R1Y3Rpb24gZW52aXJvbm1lbnRzXG4gXFxzZXQgcGdwYXNzIGBlY2hvIFwiJFBPU1RHUkVTX1BBU1NXT1JEXCJgXG5cbiBBTFRFUiBVU0VSIGF1dGhlbnRpY2F0b3IgV0lUSCBQQVNTV09SRCA6J3BncGFzcyc7XG4gQUxURVIgVVNFUiBwZ2JvdW5jZXIgV0lUSCBQQVNTV09SRCA6J3BncGFzcyc7XG4gQUxURVIgVVNFUiBzdXBhYmFzZV9hdXRoX2FkbWluIFdJVEggUEFTU1dPUkQgOidwZ3Bhc3MnO1xuIEFMVEVSIFVTRVIgc3VwYWJhc2VfZnVuY3Rpb25zX2FkbWluIFdJVEggUEFTU1dPUkQgOidwZ3Bhc3MnO1xuIEFMVEVSIFVTRVIgc3VwYWJhc2Vfc3RvcmFnZV9hZG1pbiBXSVRIIFBBU1NXT1JEIDoncGdwYXNzJztcbiIKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9kYi9qd3Quc3FsCiAgICAgICAgdGFyZ2V0OiAvZG9ja2VyLWVudHJ5cG9pbnQtaW5pdGRiLmQvaW5pdC1zY3JpcHRzLzk5LWp3dC5zcWwKICAgICAgICBjb250ZW50OiAiXFxzZXQgand0X3NlY3JldCBgZWNobyBcIiRKV1RfU0VDUkVUXCJgXG5cXHNldCBqd3RfZXhwIGBlY2hvIFwiJEpXVF9FWFBcImBcblxcc2V0IGRiX25hbWUgYGVjaG8gXCIke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc31cImBcblxuQUxURVIgREFUQUJBU0UgOmRiX25hbWUgU0VUIFwiYXBwLnNldHRpbmdzLmp3dF9zZWNyZXRcIiBUTyA6J2p3dF9zZWNyZXQnO1xuQUxURVIgREFUQUJBU0UgOmRiX25hbWUgU0VUIFwiYXBwLnNldHRpbmdzLmp3dF9leHBcIiBUTyA6J2p3dF9leHAnO1xuIgogICAgICAtCiAgICAgICAgdHlwZTogYmluZAogICAgICAgIHNvdXJjZTogLi92b2x1bWVzL2RiL2xvZ3Muc3FsCiAgICAgICAgdGFyZ2V0OiAvZG9ja2VyLWVudHJ5cG9pbnQtaW5pdGRiLmQvbWlncmF0aW9ucy85OS1sb2dzLnNxbAogICAgICAgIGNvbnRlbnQ6ICJcXHNldCBwZ3VzZXIgYGVjaG8gXCJzdXBhYmFzZV9hZG1pblwiYFxuXFxjIF9zdXBhYmFzZVxuY3JlYXRlIHNjaGVtYSBpZiBub3QgZXhpc3RzIF9hbmFseXRpY3M7XG5hbHRlciBzY2hlbWEgX2FuYWx5dGljcyBvd25lciB0byA6cGd1c2VyO1xuXFxjIHBvc3RncmVzXG4iCiAgICAgIC0gJ3N1cGFiYXNlLWRiLWNvbmZpZzovZXRjL3Bvc3RncmVzcWwtY3VzdG9tJwogIHN1cGFiYXNlLWFuYWx5dGljczoKICAgIGltYWdlOiAnc3VwYWJhc2UvbG9nZmxhcmU6MS40LjAnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gY3VybAogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6NDAwMC9oZWFsdGgnCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIGludGVydmFsOiA1cwogICAgICByZXRyaWVzOiAxMAogICAgZGVwZW5kc19vbjoKICAgICAgc3VwYWJhc2UtZGI6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIExPR0ZMQVJFX05PREVfSE9TVD0xMjcuMC4wLjEKICAgICAgLSBEQl9VU0VSTkFNRT1zdXBhYmFzZV9hZG1pbgogICAgICAtIERCX0RBVEFCQVNFPV9zdXBhYmFzZQogICAgICAtICdEQl9IT1NUTkFNRT0ke1BPU1RHUkVTX0hPU1ROQU1FOi1zdXBhYmFzZS1kYn0nCiAgICAgIC0gJ0RCX1BPUlQ9JHtQT1NUR1JFU19QT1JUOi01NDMyfScKICAgICAgLSAnREJfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSBEQl9TQ0hFTUE9X2FuYWx5dGljcwogICAgICAtICdMT0dGTEFSRV9BUElfS0VZPSR7U0VSVklDRV9QQVNTV09SRF9MT0dGTEFSRX0nCiAgICAgIC0gTE9HRkxBUkVfU0lOR0xFX1RFTkFOVD10cnVlCiAgICAgIC0gTE9HRkxBUkVfU0lOR0xFX1RFTkFOVF9NT0RFPXRydWUKICAgICAgLSBMT0dGTEFSRV9TVVBBQkFTRV9NT0RFPXRydWUKICAgICAgLSBMT0dGTEFSRV9NSU5fQ0xVU1RFUl9TSVpFPTEKICAgICAgLSAnUE9TVEdSRVNfQkFDS0VORF9VUkw9cG9zdGdyZXNxbDovL3N1cGFiYXNlX2FkbWluOiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU31AJHtQT1NUR1JFU19IT1NUTkFNRTotc3VwYWJhc2UtZGJ9OiR7UE9TVEdSRVNfUE9SVDotNTQzMn0vX3N1cGFiYXNlJwogICAgICAtIFBPU1RHUkVTX0JBQ0tFTkRfU0NIRU1BPV9hbmFseXRpY3MKICAgICAgLSBMT0dGTEFSRV9GRUFUVVJFX0ZMQUdfT1ZFUlJJREU9bXVsdGliYWNrZW5kPXRydWUKICBzdXBhYmFzZS12ZWN0b3I6CiAgICBpbWFnZTogJ3RpbWJlcmlvL3ZlY3RvcjowLjI4LjEtYWxwaW5lJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIHdnZXQKICAgICAgICAtICctLW5vLXZlcmJvc2UnCiAgICAgICAgLSAnLS10cmllcz0xJwogICAgICAgIC0gJy0tc3BpZGVyJwogICAgICAgIC0gJ2h0dHA6Ly9zdXBhYmFzZS12ZWN0b3I6OTAwMS9oZWFsdGgnCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIGludGVydmFsOiA1cwogICAgICByZXRyaWVzOiAzCiAgICB2b2x1bWVzOgogICAgICAtCiAgICAgICAgdHlwZTogYmluZAogICAgICAgIHNvdXJjZTogLi92b2x1bWVzL2xvZ3MvdmVjdG9yLnltbAogICAgICAgIHRhcmdldDogL2V0Yy92ZWN0b3IvdmVjdG9yLnltbAogICAgICAgIHJlYWRfb25seTogdHJ1ZQogICAgICAgIGNvbnRlbnQ6ICJhcGk6XG4gIGVuYWJsZWQ6IHRydWVcbiAgYWRkcmVzczogMC4wLjAuMDo5MDAxXG5cbnNvdXJjZXM6XG4gIGRvY2tlcl9ob3N0OlxuICAgIHR5cGU6IGRvY2tlcl9sb2dzXG4gICAgZXhjbHVkZV9jb250YWluZXJzOlxuICAgICAgLSBzdXBhYmFzZS12ZWN0b3JcblxudHJhbnNmb3JtczpcbiAgcHJvamVjdF9sb2dzOlxuICAgIHR5cGU6IHJlbWFwXG4gICAgaW5wdXRzOlxuICAgICAgLSBkb2NrZXJfaG9zdFxuICAgIHNvdXJjZTogfC1cbiAgICAgIC5wcm9qZWN0ID0gXCJkZWZhdWx0XCJcbiAgICAgIC5ldmVudF9tZXNzYWdlID0gZGVsKC5tZXNzYWdlKVxuICAgICAgLmFwcG5hbWUgPSBkZWwoLmNvbnRhaW5lcl9uYW1lKVxuICAgICAgZGVsKC5jb250YWluZXJfY3JlYXRlZF9hdClcbiAgICAgIGRlbCguY29udGFpbmVyX2lkKVxuICAgICAgZGVsKC5zb3VyY2VfdHlwZSlcbiAgICAgIGRlbCguc3RyZWFtKVxuICAgICAgZGVsKC5sYWJlbClcbiAgICAgIGRlbCguaW1hZ2UpXG4gICAgICBkZWwoLmhvc3QpXG4gICAgICBkZWwoLnN0cmVhbSlcbiAgcm91dGVyOlxuICAgIHR5cGU6IHJvdXRlXG4gICAgaW5wdXRzOlxuICAgICAgLSBwcm9qZWN0X2xvZ3NcbiAgICByb3V0ZTpcbiAgICAgIGtvbmc6ICdzdGFydHNfd2l0aChzdHJpbmchKC5hcHBuYW1lKSwgXCJzdXBhYmFzZS1rb25nXCIpJ1xuICAgICAgYXV0aDogJ3N0YXJ0c193aXRoKHN0cmluZyEoLmFwcG5hbWUpLCBcInN1cGFiYXNlLWF1dGhcIiknXG4gICAgICByZXN0OiAnc3RhcnRzX3dpdGgoc3RyaW5nISguYXBwbmFtZSksIFwic3VwYWJhc2UtcmVzdFwiKSdcbiAgICAgIHJlYWx0aW1lOiAnc3RhcnRzX3dpdGgoc3RyaW5nISguYXBwbmFtZSksIFwicmVhbHRpbWUtZGV2XCIpJ1xuICAgICAgc3RvcmFnZTogJ3N0YXJ0c193aXRoKHN0cmluZyEoLmFwcG5hbWUpLCBcInN1cGFiYXNlLXN0b3JhZ2VcIiknXG4gICAgICBmdW5jdGlvbnM6ICdzdGFydHNfd2l0aChzdHJpbmchKC5hcHBuYW1lKSwgXCJzdXBhYmFzZS1mdW5jdGlvbnNcIiknXG4gICAgICBkYjogJ3N0YXJ0c193aXRoKHN0cmluZyEoLmFwcG5hbWUpLCBcInN1cGFiYXNlLWRiXCIpJ1xuICAjIElnbm9yZXMgbm9uIG5naW54IGVycm9ycyBzaW5jZSB0aGV5IGFyZSByZWxhdGVkIHdpdGgga29uZyBib290aW5nIHVwXG4gIGtvbmdfbG9nczpcbiAgICB0eXBlOiByZW1hcFxuICAgIGlucHV0czpcbiAgICAgIC0gcm91dGVyLmtvbmdcbiAgICBzb3VyY2U6IHwtXG4gICAgICByZXEsIGVyciA9IHBhcnNlX25naW54X2xvZyguZXZlbnRfbWVzc2FnZSwgXCJjb21iaW5lZFwiKVxuICAgICAgaWYgZXJyID09IG51bGwge1xuICAgICAgICAgIC50aW1lc3RhbXAgPSByZXEudGltZXN0YW1wXG4gICAgICAgICAgLm1ldGFkYXRhLnJlcXVlc3QuaGVhZGVycy5yZWZlcmVyID0gcmVxLnJlZmVyZXJcbiAgICAgICAgICAubWV0YWRhdGEucmVxdWVzdC5oZWFkZXJzLnVzZXJfYWdlbnQgPSByZXEuYWdlbnRcbiAgICAgICAgICAubWV0YWRhdGEucmVxdWVzdC5oZWFkZXJzLmNmX2Nvbm5lY3RpbmdfaXAgPSByZXEuY2xpZW50XG4gICAgICAgICAgLm1ldGFkYXRhLnJlcXVlc3QubWV0aG9kID0gcmVxLm1ldGhvZFxuICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0LnBhdGggPSByZXEucGF0aFxuICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0LnByb3RvY29sID0gcmVxLnByb3RvY29sXG4gICAgICAgICAgLm1ldGFkYXRhLnJlc3BvbnNlLnN0YXR1c19jb2RlID0gcmVxLnN0YXR1c1xuICAgICAgfVxuICAgICAgaWYgZXJyICE9IG51bGwge1xuICAgICAgICBhYm9ydFxuICAgICAgfVxuICAjIElnbm9yZXMgbm9uIG5naW54IGVycm9ycyBzaW5jZSB0aGV5IGFyZSByZWxhdGVkIHdpdGgga29uZyBib290aW5nIHVwXG4gIGtvbmdfZXJyOlxuICAgIHR5cGU6IHJlbWFwXG4gICAgaW5wdXRzOlxuICAgICAgLSByb3V0ZXIua29uZ1xuICAgIHNvdXJjZTogfC1cbiAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0Lm1ldGhvZCA9IFwiR0VUXCJcbiAgICAgIC5tZXRhZGF0YS5yZXNwb25zZS5zdGF0dXNfY29kZSA9IDIwMFxuICAgICAgcGFyc2VkLCBlcnIgPSBwYXJzZV9uZ2lueF9sb2coLmV2ZW50X21lc3NhZ2UsIFwiZXJyb3JcIilcbiAgICAgIGlmIGVyciA9PSBudWxsIHtcbiAgICAgICAgICAudGltZXN0YW1wID0gcGFyc2VkLnRpbWVzdGFtcFxuICAgICAgICAgIC5zZXZlcml0eSA9IHBhcnNlZC5zZXZlcml0eVxuICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0Lmhvc3QgPSBwYXJzZWQuaG9zdFxuICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0LmhlYWRlcnMuY2ZfY29ubmVjdGluZ19pcCA9IHBhcnNlZC5jbGllbnRcbiAgICAgICAgICB1cmwsIGVyciA9IHNwbGl0KHBhcnNlZC5yZXF1ZXN0LCBcIiBcIilcbiAgICAgICAgICBpZiBlcnIgPT0gbnVsbCB7XG4gICAgICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0Lm1ldGhvZCA9IHVybFswXVxuICAgICAgICAgICAgICAubWV0YWRhdGEucmVxdWVzdC5wYXRoID0gdXJsWzFdXG4gICAgICAgICAgICAgIC5tZXRhZGF0YS5yZXF1ZXN0LnByb3RvY29sID0gdXJsWzJdXG4gICAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgZXJyICE9IG51bGwge1xuICAgICAgICBhYm9ydFxuICAgICAgfVxuICAjIEdvdHJ1ZSBsb2dzIGFyZSBzdHJ1Y3R1cmVkIGpzb24gc3RyaW5ncyB3aGljaCBmcm9udGVuZCBwYXJzZXMgZGlyZWN0bHkuIEJ1dCB3ZSBrZWVwIG1ldGFkYXRhIGZvciBjb25zaXN0ZW5jeS5cbiAgYXV0aF9sb2dzOlxuICAgIHR5cGU6IHJlbWFwXG4gICAgaW5wdXRzOlxuICAgICAgLSByb3V0ZXIuYXV0aFxuICAgIHNvdXJjZTogfC1cbiAgICAgIHBhcnNlZCwgZXJyID0gcGFyc2VfanNvbiguZXZlbnRfbWVzc2FnZSlcbiAgICAgIGlmIGVyciA9PSBudWxsIHtcbiAgICAgICAgICAubWV0YWRhdGEudGltZXN0YW1wID0gcGFyc2VkLnRpbWVcbiAgICAgICAgICAubWV0YWRhdGEgPSBtZXJnZSEoLm1ldGFkYXRhLCBwYXJzZWQpXG4gICAgICB9XG4gICMgUG9zdGdSRVNUIGxvZ3MgYXJlIHN0cnVjdHVyZWQgc28gd2Ugc2VwYXJhdGUgdGltZXN0YW1wIGZyb20gbWVzc2FnZSB1c2luZyByZWdleFxuICByZXN0X2xvZ3M6XG4gICAgdHlwZTogcmVtYXBcbiAgICBpbnB1dHM6XG4gICAgICAtIHJvdXRlci5yZXN0XG4gICAgc291cmNlOiB8LVxuICAgICAgcGFyc2VkLCBlcnIgPSBwYXJzZV9yZWdleCguZXZlbnRfbWVzc2FnZSwgcideKD9QPHRpbWU+LiopOiAoP1A8bXNnPi4qKSQnKVxuICAgICAgaWYgZXJyID09IG51bGwge1xuICAgICAgICAgIC5ldmVudF9tZXNzYWdlID0gcGFyc2VkLm1zZ1xuICAgICAgICAgIC50aW1lc3RhbXAgPSB0b190aW1lc3RhbXAhKHBhcnNlZC50aW1lKVxuICAgICAgICAgIC5tZXRhZGF0YS5ob3N0ID0gLnByb2plY3RcbiAgICAgIH1cbiAgIyBSZWFsdGltZSBsb2dzIGFyZSBzdHJ1Y3R1cmVkIHNvIHdlIHBhcnNlIHRoZSBzZXZlcml0eSBsZXZlbCB1c2luZyByZWdleCAoaWdub3JlIHRpbWUgYmVjYXVzZSBpdCBoYXMgbm8gZGF0ZSlcbiAgcmVhbHRpbWVfbG9nczpcbiAgICB0eXBlOiByZW1hcFxuICAgIGlucHV0czpcbiAgICAgIC0gcm91dGVyLnJlYWx0aW1lXG4gICAgc291cmNlOiB8LVxuICAgICAgLm1ldGFkYXRhLnByb2plY3QgPSBkZWwoLnByb2plY3QpXG4gICAgICAubWV0YWRhdGEuZXh0ZXJuYWxfaWQgPSAubWV0YWRhdGEucHJvamVjdFxuICAgICAgcGFyc2VkLCBlcnIgPSBwYXJzZV9yZWdleCguZXZlbnRfbWVzc2FnZSwgcideKD9QPHRpbWU+XFxkKzpcXGQrOlxcZCtcXC5cXGQrKSBcXFsoP1A8bGV2ZWw+XFx3KylcXF0gKD9QPG1zZz4uKikkJylcbiAgICAgIGlmIGVyciA9PSBudWxsIHtcbiAgICAgICAgICAuZXZlbnRfbWVzc2FnZSA9IHBhcnNlZC5tc2dcbiAgICAgICAgICAubWV0YWRhdGEubGV2ZWwgPSBwYXJzZWQubGV2ZWxcbiAgICAgIH1cbiAgIyBTdG9yYWdlIGxvZ3MgbWF5IGNvbnRhaW4ganNvbiBvYmplY3RzIHNvIHdlIHBhcnNlIHRoZW0gZm9yIGNvbXBsZXRlbmVzc1xuICBzdG9yYWdlX2xvZ3M6XG4gICAgdHlwZTogcmVtYXBcbiAgICBpbnB1dHM6XG4gICAgICAtIHJvdXRlci5zdG9yYWdlXG4gICAgc291cmNlOiB8LVxuICAgICAgLm1ldGFkYXRhLnByb2plY3QgPSBkZWwoLnByb2plY3QpXG4gICAgICAubWV0YWRhdGEudGVuYW50SWQgPSAubWV0YWRhdGEucHJvamVjdFxuICAgICAgcGFyc2VkLCBlcnIgPSBwYXJzZV9qc29uKC5ldmVudF9tZXNzYWdlKVxuICAgICAgaWYgZXJyID09IG51bGwge1xuICAgICAgICAgIC5ldmVudF9tZXNzYWdlID0gcGFyc2VkLm1zZ1xuICAgICAgICAgIC5tZXRhZGF0YS5sZXZlbCA9IHBhcnNlZC5sZXZlbFxuICAgICAgICAgIC5tZXRhZGF0YS50aW1lc3RhbXAgPSBwYXJzZWQudGltZVxuICAgICAgICAgIC5tZXRhZGF0YS5jb250ZXh0WzBdLmhvc3QgPSBwYXJzZWQuaG9zdG5hbWVcbiAgICAgICAgICAubWV0YWRhdGEuY29udGV4dFswXS5waWQgPSBwYXJzZWQucGlkXG4gICAgICB9XG4gICMgUG9zdGdyZXMgbG9ncyBzb21lIG1lc3NhZ2VzIHRvIHN0ZGVyciB3aGljaCB3ZSBtYXAgdG8gd2FybmluZyBzZXZlcml0eSBsZXZlbFxuICBkYl9sb2dzOlxuICAgIHR5cGU6IHJlbWFwXG4gICAgaW5wdXRzOlxuICAgICAgLSByb3V0ZXIuZGJcbiAgICBzb3VyY2U6IHwtXG4gICAgICAubWV0YWRhdGEuaG9zdCA9IFwiZGItZGVmYXVsdFwiXG4gICAgICAubWV0YWRhdGEucGFyc2VkLnRpbWVzdGFtcCA9IC50aW1lc3RhbXBcblxuICAgICAgcGFyc2VkLCBlcnIgPSBwYXJzZV9yZWdleCguZXZlbnRfbWVzc2FnZSwgcicuKig/UDxsZXZlbD5JTkZPfE5PVElDRXxXQVJOSU5HfEVSUk9SfExPR3xGQVRBTHxQQU5JQz8pOi4qJywgbnVtZXJpY19ncm91cHM6IHRydWUpXG5cbiAgICAgIGlmIGVyciAhPSBudWxsIHx8IHBhcnNlZCA9PSBudWxsIHtcbiAgICAgICAgLm1ldGFkYXRhLnBhcnNlZC5lcnJvcl9zZXZlcml0eSA9IFwiaW5mb1wiXG4gICAgICB9XG4gICAgICBpZiBwYXJzZWQgIT0gbnVsbCB7XG4gICAgICAubWV0YWRhdGEucGFyc2VkLmVycm9yX3NldmVyaXR5ID0gcGFyc2VkLmxldmVsXG4gICAgICB9XG4gICAgICBpZiAubWV0YWRhdGEucGFyc2VkLmVycm9yX3NldmVyaXR5ID09IFwiaW5mb1wiIHtcbiAgICAgICAgICAubWV0YWRhdGEucGFyc2VkLmVycm9yX3NldmVyaXR5ID0gXCJsb2dcIlxuICAgICAgfVxuICAgICAgLm1ldGFkYXRhLnBhcnNlZC5lcnJvcl9zZXZlcml0eSA9IHVwY2FzZSEoLm1ldGFkYXRhLnBhcnNlZC5lcnJvcl9zZXZlcml0eSlcblxuc2lua3M6XG4gIGxvZ2ZsYXJlX2F1dGg6XG4gICAgdHlwZTogJ2h0dHAnXG4gICAgaW5wdXRzOlxuICAgICAgLSBhdXRoX2xvZ3NcbiAgICBlbmNvZGluZzpcbiAgICAgIGNvZGVjOiAnanNvbidcbiAgICBtZXRob2Q6ICdwb3N0J1xuICAgIHJlcXVlc3Q6XG4gICAgICByZXRyeV9tYXhfZHVyYXRpb25fc2VjczogMTBcbiAgICB1cmk6ICdodHRwOi8vc3VwYWJhc2UtYW5hbHl0aWNzOjQwMDAvYXBpL2xvZ3M/c291cmNlX25hbWU9Z290cnVlLmxvZ3MucHJvZCZhcGlfa2V5PSR7TE9HRkxBUkVfQVBJX0tFWT9MT0dGTEFSRV9BUElfS0VZIGlzIHJlcXVpcmVkfSdcbiAgbG9nZmxhcmVfcmVhbHRpbWU6XG4gICAgdHlwZTogJ2h0dHAnXG4gICAgaW5wdXRzOlxuICAgICAgLSByZWFsdGltZV9sb2dzXG4gICAgZW5jb2Rpbmc6XG4gICAgICBjb2RlYzogJ2pzb24nXG4gICAgbWV0aG9kOiAncG9zdCdcbiAgICByZXF1ZXN0OlxuICAgICAgcmV0cnlfbWF4X2R1cmF0aW9uX3NlY3M6IDEwXG4gICAgdXJpOiAnaHR0cDovL3N1cGFiYXNlLWFuYWx5dGljczo0MDAwL2FwaS9sb2dzP3NvdXJjZV9uYW1lPXJlYWx0aW1lLmxvZ3MucHJvZCZhcGlfa2V5PSR7TE9HRkxBUkVfQVBJX0tFWT9MT0dGTEFSRV9BUElfS0VZIGlzIHJlcXVpcmVkfSdcbiAgbG9nZmxhcmVfcmVzdDpcbiAgICB0eXBlOiAnaHR0cCdcbiAgICBpbnB1dHM6XG4gICAgICAtIHJlc3RfbG9nc1xuICAgIGVuY29kaW5nOlxuICAgICAgY29kZWM6ICdqc29uJ1xuICAgIG1ldGhvZDogJ3Bvc3QnXG4gICAgcmVxdWVzdDpcbiAgICAgIHJldHJ5X21heF9kdXJhdGlvbl9zZWNzOiAxMFxuICAgIHVyaTogJ2h0dHA6Ly9zdXBhYmFzZS1hbmFseXRpY3M6NDAwMC9hcGkvbG9ncz9zb3VyY2VfbmFtZT1wb3N0Z1JFU1QubG9ncy5wcm9kJmFwaV9rZXk9JHtMT0dGTEFSRV9BUElfS0VZP0xPR0ZMQVJFX0FQSV9LRVkgaXMgcmVxdWlyZWR9J1xuICBsb2dmbGFyZV9kYjpcbiAgICB0eXBlOiAnaHR0cCdcbiAgICBpbnB1dHM6XG4gICAgICAtIGRiX2xvZ3NcbiAgICBlbmNvZGluZzpcbiAgICAgIGNvZGVjOiAnanNvbidcbiAgICBtZXRob2Q6ICdwb3N0J1xuICAgIHJlcXVlc3Q6XG4gICAgICByZXRyeV9tYXhfZHVyYXRpb25fc2VjczogMTBcbiAgICAjIFdlIG11c3Qgcm91dGUgdGhlIHNpbmsgdGhyb3VnaCBrb25nIGJlY2F1c2UgaW5nZXN0aW5nIGxvZ3MgYmVmb3JlIGxvZ2ZsYXJlIGlzIGZ1bGx5IGluaXRpYWxpc2VkIHdpbGxcbiAgICAjIGxlYWQgdG8gYnJva2VuIHF1ZXJpZXMgZnJvbSBzdHVkaW8uIFRoaXMgd29ya3MgYnkgdGhlIGFzc3VtcHRpb24gdGhhdCBjb250YWluZXJzIGFyZSBzdGFydGVkIGluIHRoZVxuICAgICMgZm9sbG93aW5nIG9yZGVyOiB2ZWN0b3IgPiBkYiA+IGxvZ2ZsYXJlID4ga29uZ1xuICAgIHVyaTogJ2h0dHA6Ly9zdXBhYmFzZS1rb25nOjgwMDAvYW5hbHl0aWNzL3YxL2FwaS9sb2dzP3NvdXJjZV9uYW1lPXBvc3RncmVzLmxvZ3MmYXBpX2tleT0ke0xPR0ZMQVJFX0FQSV9LRVk/TE9HRkxBUkVfQVBJX0tFWSBpcyByZXF1aXJlZH0nXG4gIGxvZ2ZsYXJlX2Z1bmN0aW9uczpcbiAgICB0eXBlOiAnaHR0cCdcbiAgICBpbnB1dHM6XG4gICAgICAtIHJvdXRlci5mdW5jdGlvbnNcbiAgICBlbmNvZGluZzpcbiAgICAgIGNvZGVjOiAnanNvbidcbiAgICBtZXRob2Q6ICdwb3N0J1xuICAgIHJlcXVlc3Q6XG4gICAgICByZXRyeV9tYXhfZHVyYXRpb25fc2VjczogMTBcbiAgICB1cmk6ICdodHRwOi8vc3VwYWJhc2UtYW5hbHl0aWNzOjQwMDAvYXBpL2xvZ3M/c291cmNlX25hbWU9ZGVuby1yZWxheS1sb2dzJmFwaV9rZXk9JHtMT0dGTEFSRV9BUElfS0VZP0xPR0ZMQVJFX0FQSV9LRVkgaXMgcmVxdWlyZWR9J1xuICBsb2dmbGFyZV9zdG9yYWdlOlxuICAgIHR5cGU6ICdodHRwJ1xuICAgIGlucHV0czpcbiAgICAgIC0gc3RvcmFnZV9sb2dzXG4gICAgZW5jb2Rpbmc6XG4gICAgICBjb2RlYzogJ2pzb24nXG4gICAgbWV0aG9kOiAncG9zdCdcbiAgICByZXF1ZXN0OlxuICAgICAgcmV0cnlfbWF4X2R1cmF0aW9uX3NlY3M6IDEwXG4gICAgdXJpOiAnaHR0cDovL3N1cGFiYXNlLWFuYWx5dGljczo0MDAwL2FwaS9sb2dzP3NvdXJjZV9uYW1lPXN0b3JhZ2UubG9ncy5wcm9kLjImYXBpX2tleT0ke0xPR0ZMQVJFX0FQSV9LRVk/TE9HRkxBUkVfQVBJX0tFWSBpcyByZXF1aXJlZH0nXG4gIGxvZ2ZsYXJlX2tvbmc6XG4gICAgdHlwZTogJ2h0dHAnXG4gICAgaW5wdXRzOlxuICAgICAgLSBrb25nX2xvZ3NcbiAgICAgIC0ga29uZ19lcnJcbiAgICBlbmNvZGluZzpcbiAgICAgIGNvZGVjOiAnanNvbidcbiAgICBtZXRob2Q6ICdwb3N0J1xuICAgIHJlcXVlc3Q6XG4gICAgICByZXRyeV9tYXhfZHVyYXRpb25fc2VjczogMTBcbiAgICB1cmk6ICdodHRwOi8vc3VwYWJhc2UtYW5hbHl0aWNzOjQwMDAvYXBpL2xvZ3M/c291cmNlX25hbWU9Y2xvdWRmbGFyZS5sb2dzLnByb2QmYXBpX2tleT0ke0xPR0ZMQVJFX0FQSV9LRVk/TE9HRkxBUkVfQVBJX0tFWSBpcyByZXF1aXJlZH0nXG4iCiAgICAgIC0gJy92YXIvcnVuL2RvY2tlci5zb2NrOi92YXIvcnVuL2RvY2tlci5zb2NrOnJvJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ0xPR0ZMQVJFX0FQSV9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX0xPR0ZMQVJFfScKICAgIGNvbW1hbmQ6CiAgICAgIC0gJy0tY29uZmlnJwogICAgICAtIGV0Yy92ZWN0b3IvdmVjdG9yLnltbAogIHN1cGFiYXNlLXJlc3Q6CiAgICBpbWFnZTogJ3Bvc3RncmVzdC9wb3N0Z3Jlc3Q6djEyLjIuMCcKICAgIGRlcGVuZHNfb246CiAgICAgIHN1cGFiYXNlLWRiOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICAgIHN1cGFiYXNlLWFuYWx5dGljczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BHUlNUX0RCX1VSST1wb3N0Z3JlczovL2F1dGhlbnRpY2F0b3I6JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfUAke1BPU1RHUkVTX0hPU1ROQU1FOi1zdXBhYmFzZS1kYn06JHtQT1NUR1JFU19QT1JUOi01NDMyfS8ke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc30nCiAgICAgIC0gJ1BHUlNUX0RCX1NDSEVNQVM9JHtQR1JTVF9EQl9TQ0hFTUFTOi1wdWJsaWMsc3RvcmFnZSxncmFwaHFsX3B1YmxpY30nCiAgICAgIC0gUEdSU1RfREJfQU5PTl9ST0xFPWFub24KICAgICAgLSAnUEdSU1RfSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfSldUfScKICAgICAgLSBQR1JTVF9EQl9VU0VfTEVHQUNZX0dVQ1M9ZmFsc2UKICAgICAgLSAnUEdSU1RfQVBQX1NFVFRJTkdTX0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX0pXVH0nCiAgICAgIC0gJ1BHUlNUX0FQUF9TRVRUSU5HU19KV1RfRVhQPSR7SldUX0VYUElSWTotMzYwMH0nCiAgICBjb21tYW5kOiBwb3N0Z3Jlc3QKICAgIGV4Y2x1ZGVfZnJvbV9oYzogdHJ1ZQogIHN1cGFiYXNlLWF1dGg6CiAgICBpbWFnZTogJ3N1cGFiYXNlL2dvdHJ1ZTp2Mi4xNjQuMCcKICAgIGRlcGVuZHNfb246CiAgICAgIHN1cGFiYXNlLWRiOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICAgIHN1cGFiYXNlLWFuYWx5dGljczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIHdnZXQKICAgICAgICAtICctLW5vLXZlcmJvc2UnCiAgICAgICAgLSAnLS10cmllcz0xJwogICAgICAgIC0gJy0tc3BpZGVyJwogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6OTk5OS9oZWFsdGgnCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIGludGVydmFsOiA1cwogICAgICByZXRyaWVzOiAzCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBHT1RSVUVfQVBJX0hPU1Q9MC4wLjAuMAogICAgICAtIEdPVFJVRV9BUElfUE9SVD05OTk5CiAgICAgIC0gJ0FQSV9FWFRFUk5BTF9VUkw9JHtBUElfRVhURVJOQUxfVVJMOi1odHRwOi8vc3VwYWJhc2Uta29uZzo4MDAwfScKICAgICAgLSBHT1RSVUVfREJfRFJJVkVSPXBvc3RncmVzCiAgICAgIC0gJ0dPVFJVRV9EQl9EQVRBQkFTRV9VUkw9cG9zdGdyZXM6Ly9zdXBhYmFzZV9hdXRoX2FkbWluOiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU31AJHtQT1NUR1JFU19IT1NUTkFNRTotc3VwYWJhc2UtZGJ9OiR7UE9TVEdSRVNfUE9SVDotNTQzMn0vJHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtICdHT1RSVUVfU0lURV9VUkw9JHtTRVJWSUNFX0ZRRE5fU1VQQUJBU0VLT05HfScKICAgICAgLSAnR09UUlVFX1VSSV9BTExPV19MSVNUPSR7QURESVRJT05BTF9SRURJUkVDVF9VUkxTfScKICAgICAgLSAnR09UUlVFX0RJU0FCTEVfU0lHTlVQPSR7RElTQUJMRV9TSUdOVVA6LWZhbHNlfScKICAgICAgLSBHT1RSVUVfSldUX0FETUlOX1JPTEVTPXNlcnZpY2Vfcm9sZQogICAgICAtIEdPVFJVRV9KV1RfQVVEPWF1dGhlbnRpY2F0ZWQKICAgICAgLSBHT1RSVUVfSldUX0RFRkFVTFRfR1JPVVBfTkFNRT1hdXRoZW50aWNhdGVkCiAgICAgIC0gJ0dPVFJVRV9KV1RfRVhQPSR7SldUX0VYUElSWTotMzYwMH0nCiAgICAgIC0gJ0dPVFJVRV9KV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF9KV1R9JwogICAgICAtICdHT1RSVUVfRVhURVJOQUxfRU1BSUxfRU5BQkxFRD0ke0VOQUJMRV9FTUFJTF9TSUdOVVA6LXRydWV9JwogICAgICAtICdHT1RSVUVfRVhURVJOQUxfQU5PTllNT1VTX1VTRVJTX0VOQUJMRUQ9JHtFTkFCTEVfQU5PTllNT1VTX1VTRVJTOi1mYWxzZX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfQVVUT0NPTkZJUk09JHtFTkFCTEVfRU1BSUxfQVVUT0NPTkZJUk06LWZhbHNlfScKICAgICAgLSAnR09UUlVFX1NNVFBfQURNSU5fRU1BSUw9JHtTTVRQX0FETUlOX0VNQUlMfScKICAgICAgLSAnR09UUlVFX1NNVFBfSE9TVD0ke1NNVFBfSE9TVH0nCiAgICAgIC0gJ0dPVFJVRV9TTVRQX1BPUlQ9JHtTTVRQX1BPUlQ6LTU4N30nCiAgICAgIC0gJ0dPVFJVRV9TTVRQX1VTRVI9JHtTTVRQX1VTRVJ9JwogICAgICAtICdHT1RSVUVfU01UUF9QQVNTPSR7U01UUF9QQVNTfScKICAgICAgLSAnR09UUlVFX1NNVFBfU0VOREVSX05BTUU9JHtTTVRQX1NFTkRFUl9OQU1FfScKICAgICAgLSAnR09UUlVFX01BSUxFUl9VUkxQQVRIU19JTlZJVEU9JHtNQUlMRVJfVVJMUEFUSFNfSU5WSVRFOi0vYXV0aC92MS92ZXJpZnl9JwogICAgICAtICdHT1RSVUVfTUFJTEVSX1VSTFBBVEhTX0NPTkZJUk1BVElPTj0ke01BSUxFUl9VUkxQQVRIU19DT05GSVJNQVRJT046LS9hdXRoL3YxL3ZlcmlmeX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfVVJMUEFUSFNfUkVDT1ZFUlk9JHtNQUlMRVJfVVJMUEFUSFNfUkVDT1ZFUlk6LS9hdXRoL3YxL3ZlcmlmeX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfVVJMUEFUSFNfRU1BSUxfQ0hBTkdFPSR7TUFJTEVSX1VSTFBBVEhTX0VNQUlMX0NIQU5HRTotL2F1dGgvdjEvdmVyaWZ5fScKICAgICAgLSAnR09UUlVFX01BSUxFUl9URU1QTEFURVNfSU5WSVRFPSR7TUFJTEVSX1RFTVBMQVRFU19JTlZJVEV9JwogICAgICAtICdHT1RSVUVfTUFJTEVSX1RFTVBMQVRFU19DT05GSVJNQVRJT049JHtNQUlMRVJfVEVNUExBVEVTX0NPTkZJUk1BVElPTn0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfVEVNUExBVEVTX1JFQ09WRVJZPSR7TUFJTEVSX1RFTVBMQVRFU19SRUNPVkVSWX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfVEVNUExBVEVTX01BR0lDX0xJTks9JHtNQUlMRVJfVEVNUExBVEVTX01BR0lDX0xJTkt9JwogICAgICAtICdHT1RSVUVfTUFJTEVSX1RFTVBMQVRFU19FTUFJTF9DSEFOR0U9JHtNQUlMRVJfVEVNUExBVEVTX0VNQUlMX0NIQU5HRX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfU1VCSkVDVFNfQ09ORklSTUFUSU9OPSR7TUFJTEVSX1NVQkpFQ1RTX0NPTkZJUk1BVElPTn0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfU1VCSkVDVFNfUkVDT1ZFUlk9JHtNQUlMRVJfU1VCSkVDVFNfUkVDT1ZFUll9JwogICAgICAtICdHT1RSVUVfTUFJTEVSX1NVQkpFQ1RTX01BR0lDX0xJTks9JHtNQUlMRVJfU1VCSkVDVFNfTUFHSUNfTElOS30nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfU1VCSkVDVFNfRU1BSUxfQ0hBTkdFPSR7TUFJTEVSX1NVQkpFQ1RTX0VNQUlMX0NIQU5HRX0nCiAgICAgIC0gJ0dPVFJVRV9NQUlMRVJfU1VCSkVDVFNfSU5WSVRFPSR7TUFJTEVSX1NVQkpFQ1RTX0lOVklURX0nCiAgICAgIC0gJ0dPVFJVRV9FWFRFUk5BTF9QSE9ORV9FTkFCTEVEPSR7RU5BQkxFX1BIT05FX1NJR05VUDotdHJ1ZX0nCiAgICAgIC0gJ0dPVFJVRV9TTVNfQVVUT0NPTkZJUk09JHtFTkFCTEVfUEhPTkVfQVVUT0NPTkZJUk06LXRydWV9JwogIHJlYWx0aW1lLWRldjoKICAgIGltYWdlOiAnc3VwYWJhc2UvcmVhbHRpbWU6djIuMzMuNzAnCiAgICBjb250YWluZXJfbmFtZTogcmVhbHRpbWUtZGV2LnN1cGFiYXNlLXJlYWx0aW1lCiAgICBkZXBlbmRzX29uOgogICAgICBzdXBhYmFzZS1kYjoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBzdXBhYmFzZS1hbmFseXRpY3M6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLXNTZkwnCiAgICAgICAgLSAnLS1oZWFkJwogICAgICAgIC0gJy1vJwogICAgICAgIC0gL2Rldi9udWxsCiAgICAgICAgLSAnLUgnCiAgICAgICAgLSAnQXV0aG9yaXphdGlvbjogQmVhcmVyICR7U0VSVklDRV9TVVBBQkFTRUFOT05fS0VZfScKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjQwMDAvYXBpL3RlbmFudHMvcmVhbHRpbWUtZGV2L2hlYWx0aCcKICAgICAgdGltZW91dDogNXMKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHJldHJpZXM6IDMKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPUlQ9NDAwMAogICAgICAtICdEQl9IT1NUPSR7UE9TVEdSRVNfSE9TVE5BTUU6LXN1cGFiYXNlLWRifScKICAgICAgLSAnREJfUE9SVD0ke1BPU1RHUkVTX1BPUlQ6LTU0MzJ9JwogICAgICAtIERCX1VTRVI9c3VwYWJhc2VfYWRtaW4KICAgICAgLSAnREJfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnREJfTkFNRT0ke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc30nCiAgICAgIC0gJ0RCX0FGVEVSX0NPTk5FQ1RfUVVFUlk9U0VUIHNlYXJjaF9wYXRoIFRPIF9yZWFsdGltZScKICAgICAgLSBEQl9FTkNfS0VZPXN1cGFiYXNlcmVhbHRpbWUKICAgICAgLSAnQVBJX0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX0pXVH0nCiAgICAgIC0gRkxZX0FMTE9DX0lEPWZseTEyMwogICAgICAtIEZMWV9BUFBfTkFNRT1yZWFsdGltZQogICAgICAtICdTRUNSRVRfS0VZX0JBU0U9JHtTRUNSRVRfUEFTU1dPUkRfUkVBTFRJTUV9JwogICAgICAtICdFUkxfQUZMQUdTPS1wcm90b19kaXN0IGluZXRfdGNwJwogICAgICAtIEVOQUJMRV9UQUlMU0NBTEU9ZmFsc2UKICAgICAgLSAiRE5TX05PREVTPScnIgogICAgICAtIFJMSU1JVF9OT0ZJTEU9MTAwMDAKICAgICAgLSBBUFBfTkFNRT1yZWFsdGltZQogICAgICAtIFNFRURfU0VMRl9IT1NUPXRydWUKICAgICAgLSBMT0dfTEVWRUw9ZXJyb3IKICAgICAgLSBSVU5fSkFOSVRPUj10cnVlCiAgICAgIC0gSkFOSVRPUl9JTlRFUlZBTD02MDAwMAogICAgY29tbWFuZDogInNoIC1jIFwiL2FwcC9iaW4vbWlncmF0ZSAmJiAvYXBwL2Jpbi9yZWFsdGltZSBldmFsICdSZWFsdGltZS5SZWxlYXNlLnNlZWRzKFJlYWx0aW1lLlJlcG8pJyAmJiAvYXBwL2Jpbi9zZXJ2ZXJcIlxuIgogIHN1cGFiYXNlLW1pbmlvOgogICAgaW1hZ2U6IG1pbmlvL21pbmlvCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgY29tbWFuZDogJ3NlcnZlciAtLWNvbnNvbGUtYWRkcmVzcyAiOjkwMDEiIC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6ICdzbGVlcCA1ICYmIGV4aXQgMCcKICAgICAgaW50ZXJ2YWw6IDJzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiA1CiAgICB2b2x1bWVzOgogICAgICAtICcuL3ZvbHVtZXMvc3RvcmFnZTovZGF0YScKICBtaW5pby1jcmVhdGVidWNrZXQ6CiAgICBpbWFnZTogbWluaW8vbWMKICAgIHJlc3RhcnQ6ICdubycKICAgIGVudmlyb25tZW50OgogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBkZXBlbmRzX29uOgogICAgICBzdXBhYmFzZS1taW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW50cnlwb2ludDoKICAgICAgLSAvZW50cnlwb2ludC5zaAogICAgdm9sdW1lczoKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vZW50cnlwb2ludC5zaAogICAgICAgIHRhcmdldDogL2VudHJ5cG9pbnQuc2gKICAgICAgICBjb250ZW50OiAiIyEvYmluL3NoXG4vdXNyL2Jpbi9tYyBhbGlhcyBzZXQgc3VwYWJhc2UtbWluaW8gaHR0cDovL3N1cGFiYXNlLW1pbmlvOjkwMDAgJHtNSU5JT19ST09UX1VTRVJ9ICR7TUlOSU9fUk9PVF9QQVNTV09SRH07XG4vdXNyL2Jpbi9tYyBtYiAtLWlnbm9yZS1leGlzdGluZyBzdXBhYmFzZS1taW5pby9zdHViO1xuZXhpdCAwXG4iCiAgc3VwYWJhc2Utc3RvcmFnZToKICAgIGltYWdlOiAnc3VwYWJhc2Uvc3RvcmFnZS1hcGk6djEuMTQuNicKICAgIGRlcGVuZHNfb246CiAgICAgIHN1cGFiYXNlLWRiOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICAgIHN1cGFiYXNlLXJlc3Q6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgICAgaW1ncHJveHk6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSB3Z2V0CiAgICAgICAgLSAnLS1uby12ZXJib3NlJwogICAgICAgIC0gJy0tdHJpZXM9MScKICAgICAgICAtICctLXNwaWRlcicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjUwMDAvc3RhdHVzJwogICAgICB0aW1lb3V0OiA1cwogICAgICBpbnRlcnZhbDogNXMKICAgICAgcmV0cmllczogMwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVkVSX1BPUlQ9NTAwMAogICAgICAtIFNFUlZFUl9SRUdJT049bG9jYWwKICAgICAgLSBNVUxUSV9URU5BTlQ9ZmFsc2UKICAgICAgLSAnQVVUSF9KV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF9KV1R9JwogICAgICAtICdEQVRBQkFTRV9VUkw9cG9zdGdyZXM6Ly9zdXBhYmFzZV9zdG9yYWdlX2FkbWluOiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU31AJHtQT1NUR1JFU19IT1NUTkFNRTotc3VwYWJhc2UtZGJ9OiR7UE9TVEdSRVNfUE9SVDotNTQzMn0vJHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtIERCX0lOU1RBTExfUk9MRVM9ZmFsc2UKICAgICAgLSBTVE9SQUdFX0JBQ0tFTkQ9czMKICAgICAgLSBTVE9SQUdFX1MzX0JVQ0tFVD1zdHViCiAgICAgIC0gJ1NUT1JBR0VfUzNfRU5EUE9JTlQ9aHR0cDovL3N1cGFiYXNlLW1pbmlvOjkwMDAnCiAgICAgIC0gU1RPUkFHRV9TM19GT1JDRV9QQVRIX1NUWUxFPXRydWUKICAgICAgLSBTVE9SQUdFX1MzX1JFR0lPTj11cy1lYXN0LTEKICAgICAgLSAnQVdTX0FDQ0VTU19LRVlfSUQ9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdBV1NfU0VDUkVUX0FDQ0VTU19LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfScKICAgICAgLSBVUExPQURfRklMRV9TSVpFX0xJTUlUPTUyNDI4ODAwMAogICAgICAtIFVQTE9BRF9GSUxFX1NJWkVfTElNSVRfU1RBTkRBUkQ9NTI0Mjg4MDAwCiAgICAgIC0gVVBMT0FEX1NJR05FRF9VUkxfRVhQSVJBVElPTl9USU1FPTEyMAogICAgICAtIFRVU19VUkxfUEFUSD11cGxvYWQvcmVzdW1hYmxlCiAgICAgIC0gVFVTX01BWF9TSVpFPTM2MDAwMDAKICAgICAgLSBFTkFCTEVfSU1BR0VfVFJBTlNGT1JNQVRJT049dHJ1ZQogICAgICAtICdJTUdQUk9YWV9VUkw9aHR0cDovL2ltZ3Byb3h5OjgwODAnCiAgICAgIC0gSU1HUFJPWFlfUkVRVUVTVF9USU1FT1VUPTE1CiAgICAgIC0gREFUQUJBU0VfU0VBUkNIX1BBVEg9c3RvcmFnZQogICAgICAtIE5PREVfRU5WPXByb2R1Y3Rpb24KICAgICAgLSBSRVFVRVNUX0FMTE9XX1hfRk9SV0FSREVEX1BBVEg9dHJ1ZQogICAgdm9sdW1lczoKICAgICAgLSAnLi92b2x1bWVzL3N0b3JhZ2U6L3Zhci9saWIvc3RvcmFnZScKICBpbWdwcm94eToKICAgIGltYWdlOiAnZGFydGhzaW0vaW1ncHJveHk6djMuOC4wJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGltZ3Byb3h5CiAgICAgICAgLSBoZWFsdGgKICAgICAgdGltZW91dDogNXMKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHJldHJpZXM6IDMKICAgIGVudmlyb25tZW50OgogICAgICAtIElNR1BST1hZX0xPQ0FMX0ZJTEVTWVNURU1fUk9PVD0vCiAgICAgIC0gSU1HUFJPWFlfVVNFX0VUQUc9dHJ1ZQogICAgICAtICdJTUdQUk9YWV9FTkFCTEVfV0VCUF9ERVRFQ1RJT049JHtJTUdQUk9YWV9FTkFCTEVfV0VCUF9ERVRFQ1RJT046LXRydWV9JwogICAgdm9sdW1lczoKICAgICAgLSAnLi92b2x1bWVzL3N0b3JhZ2U6L3Zhci9saWIvc3RvcmFnZScKICBzdXBhYmFzZS1tZXRhOgogICAgaW1hZ2U6ICdzdXBhYmFzZS9wb3N0Z3Jlcy1tZXRhOnYwLjg0LjInCiAgICBkZXBlbmRzX29uOgogICAgICBzdXBhYmFzZS1kYjoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBzdXBhYmFzZS1hbmFseXRpY3M6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIFBHX01FVEFfUE9SVD04MDgwCiAgICAgIC0gJ1BHX01FVEFfREJfSE9TVD0ke1BPU1RHUkVTX0hPU1ROQU1FOi1zdXBhYmFzZS1kYn0nCiAgICAgIC0gJ1BHX01FVEFfREJfUE9SVD0ke1BPU1RHUkVTX1BPUlQ6LTU0MzJ9JwogICAgICAtICdQR19NRVRBX0RCX05BTUU9JHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtIFBHX01FVEFfREJfVVNFUj1zdXBhYmFzZV9hZG1pbgogICAgICAtICdQR19NRVRBX0RCX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgc3VwYWJhc2UtZWRnZS1mdW5jdGlvbnM6CiAgICBpbWFnZTogJ3N1cGFiYXNlL2VkZ2UtcnVudGltZTp2MS42NS4zJwogICAgZGVwZW5kc19vbjoKICAgICAgc3VwYWJhc2UtYW5hbHl0aWNzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gZWNobwogICAgICAgIC0gJ0VkZ2UgRnVuY3Rpb25zIGlzIGhlYWx0aHknCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIGludGVydmFsOiA1cwogICAgICByZXRyaWVzOiAzCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfSldUfScKICAgICAgLSAnU1VQQUJBU0VfVVJMPSR7U0VSVklDRV9GUUROX1NVUEFCQVNFS09OR30nCiAgICAgIC0gJ1NVUEFCQVNFX0FOT05fS0VZPSR7U0VSVklDRV9TVVBBQkFTRUFOT05fS0VZfScKICAgICAgLSAnU1VQQUJBU0VfU0VSVklDRV9ST0xFX0tFWT0ke1NFUlZJQ0VfU1VQQUJBU0VTRVJWSUNFX0tFWX0nCiAgICAgIC0gJ1NVUEFCQVNFX0RCX1VSTD1wb3N0Z3Jlc3FsOi8vcG9zdGdyZXM6JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfUAke1BPU1RHUkVTX0hPU1ROQU1FOi1zdXBhYmFzZS1kYn06JHtQT1NUR1JFU19QT1JUOi01NDMyfS8ke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc30nCiAgICAgIC0gJ1ZFUklGWV9KV1Q9JHtGVU5DVElPTlNfVkVSSUZZX0pXVDotZmFsc2V9JwogICAgdm9sdW1lczoKICAgICAgLSAnLi92b2x1bWVzL2Z1bmN0aW9uczovaG9tZS9kZW5vL2Z1bmN0aW9ucycKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9mdW5jdGlvbnMvbWFpbi9pbmRleC50cwogICAgICAgIHRhcmdldDogL2hvbWUvZGVuby9mdW5jdGlvbnMvbWFpbi9pbmRleC50cwogICAgICAgIGNvbnRlbnQ6ICJpbXBvcnQgeyBzZXJ2ZSB9IGZyb20gJ2h0dHBzOi8vZGVuby5sYW5kL3N0ZEAwLjEzMS4wL2h0dHAvc2VydmVyLnRzJ1xuaW1wb3J0ICogYXMgam9zZSBmcm9tICdodHRwczovL2Rlbm8ubGFuZC94L2pvc2VAdjQuMTQuNC9pbmRleC50cydcblxuY29uc29sZS5sb2coJ21haW4gZnVuY3Rpb24gc3RhcnRlZCcpXG5cbmNvbnN0IEpXVF9TRUNSRVQgPSBEZW5vLmVudi5nZXQoJ0pXVF9TRUNSRVQnKVxuY29uc3QgVkVSSUZZX0pXVCA9IERlbm8uZW52LmdldCgnVkVSSUZZX0pXVCcpID09PSAndHJ1ZSdcblxuZnVuY3Rpb24gZ2V0QXV0aFRva2VuKHJlcTogUmVxdWVzdCkge1xuICBjb25zdCBhdXRoSGVhZGVyID0gcmVxLmhlYWRlcnMuZ2V0KCdhdXRob3JpemF0aW9uJylcbiAgaWYgKCFhdXRoSGVhZGVyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIGF1dGhvcml6YXRpb24gaGVhZGVyJylcbiAgfVxuICBjb25zdCBbYmVhcmVyLCB0b2tlbl0gPSBhdXRoSGVhZGVyLnNwbGl0KCcgJylcbiAgaWYgKGJlYXJlciAhPT0gJ0JlYXJlcicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEF1dGggaGVhZGVyIGlzIG5vdCAnQmVhcmVyIHt0b2tlbn0nYClcbiAgfVxuICByZXR1cm4gdG9rZW5cbn1cblxuYXN5bmMgZnVuY3Rpb24gdmVyaWZ5SldUKGp3dDogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGNvbnN0IGVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKVxuICBjb25zdCBzZWNyZXRLZXkgPSBlbmNvZGVyLmVuY29kZShKV1RfU0VDUkVUKVxuICB0cnkge1xuICAgIGF3YWl0IGpvc2Uuand0VmVyaWZ5KGp3dCwgc2VjcmV0S2V5KVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBjb25zb2xlLmVycm9yKGVycilcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuICByZXR1cm4gdHJ1ZVxufVxuXG5zZXJ2ZShhc3luYyAocmVxOiBSZXF1ZXN0KSA9PiB7XG4gIGlmIChyZXEubWV0aG9kICE9PSAnT1BUSU9OUycgJiYgVkVSSUZZX0pXVCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB0b2tlbiA9IGdldEF1dGhUb2tlbihyZXEpXG4gICAgICBjb25zdCBpc1ZhbGlkSldUID0gYXdhaXQgdmVyaWZ5SldUKHRva2VuKVxuXG4gICAgICBpZiAoIWlzVmFsaWRKV1QpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBSZXNwb25zZShKU09OLnN0cmluZ2lmeSh7IG1zZzogJ0ludmFsaWQgSldUJyB9KSwge1xuICAgICAgICAgIHN0YXR1czogNDAxLFxuICAgICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgICB9KVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZSlcbiAgICAgIHJldHVybiBuZXcgUmVzcG9uc2UoSlNPTi5zdHJpbmdpZnkoeyBtc2c6IGUudG9TdHJpbmcoKSB9KSwge1xuICAgICAgICBzdGF0dXM6IDQwMSxcbiAgICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHVybCA9IG5ldyBVUkwocmVxLnVybClcbiAgY29uc3QgeyBwYXRobmFtZSB9ID0gdXJsXG4gIGNvbnN0IHBhdGhfcGFydHMgPSBwYXRobmFtZS5zcGxpdCgnLycpXG4gIGNvbnN0IHNlcnZpY2VfbmFtZSA9IHBhdGhfcGFydHNbMV1cblxuICBpZiAoIXNlcnZpY2VfbmFtZSB8fCBzZXJ2aWNlX25hbWUgPT09ICcnKSB7XG4gICAgY29uc3QgZXJyb3IgPSB7IG1zZzogJ21pc3NpbmcgZnVuY3Rpb24gbmFtZSBpbiByZXF1ZXN0JyB9XG4gICAgcmV0dXJuIG5ldyBSZXNwb25zZShKU09OLnN0cmluZ2lmeShlcnJvciksIHtcbiAgICAgIHN0YXR1czogNDAwLFxuICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sXG4gICAgfSlcbiAgfVxuXG4gIGNvbnN0IHNlcnZpY2VQYXRoID0gYC9ob21lL2Rlbm8vZnVuY3Rpb25zLyR7c2VydmljZV9uYW1lfWBcbiAgY29uc29sZS5lcnJvcihgc2VydmluZyB0aGUgcmVxdWVzdCB3aXRoICR7c2VydmljZVBhdGh9YClcblxuICBjb25zdCBtZW1vcnlMaW1pdE1iID0gMTUwXG4gIGNvbnN0IHdvcmtlclRpbWVvdXRNcyA9IDEgKiA2MCAqIDEwMDBcbiAgY29uc3Qgbm9Nb2R1bGVDYWNoZSA9IGZhbHNlXG4gIGNvbnN0IGltcG9ydE1hcFBhdGggPSBudWxsXG4gIGNvbnN0IGVudlZhcnNPYmogPSBEZW5vLmVudi50b09iamVjdCgpXG4gIGNvbnN0IGVudlZhcnMgPSBPYmplY3Qua2V5cyhlbnZWYXJzT2JqKS5tYXAoKGspID0+IFtrLCBlbnZWYXJzT2JqW2tdXSlcblxuICB0cnkge1xuICAgIGNvbnN0IHdvcmtlciA9IGF3YWl0IEVkZ2VSdW50aW1lLnVzZXJXb3JrZXJzLmNyZWF0ZSh7XG4gICAgICBzZXJ2aWNlUGF0aCxcbiAgICAgIG1lbW9yeUxpbWl0TWIsXG4gICAgICB3b3JrZXJUaW1lb3V0TXMsXG4gICAgICBub01vZHVsZUNhY2hlLFxuICAgICAgaW1wb3J0TWFwUGF0aCxcbiAgICAgIGVudlZhcnMsXG4gICAgfSlcbiAgICByZXR1cm4gYXdhaXQgd29ya2VyLmZldGNoKHJlcSlcbiAgfSBjYXRjaCAoZSkge1xuICAgIGNvbnN0IGVycm9yID0geyBtc2c6IGUudG9TdHJpbmcoKSB9XG4gICAgcmV0dXJuIG5ldyBSZXNwb25zZShKU09OLnN0cmluZ2lmeShlcnJvciksIHtcbiAgICAgIHN0YXR1czogNTAwLFxuICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sXG4gICAgfSlcbiAgfVxufSlcbiIKICAgICAgLQogICAgICAgIHR5cGU6IGJpbmQKICAgICAgICBzb3VyY2U6IC4vdm9sdW1lcy9mdW5jdGlvbnMvaGVsbG8vaW5kZXgudHMKICAgICAgICB0YXJnZXQ6IC9ob21lL2Rlbm8vZnVuY3Rpb25zL2hlbGxvL2luZGV4LnRzCiAgICAgICAgY29udGVudDogIi8vIEZvbGxvdyB0aGlzIHNldHVwIGd1aWRlIHRvIGludGVncmF0ZSB0aGUgRGVubyBsYW5ndWFnZSBzZXJ2ZXIgd2l0aCB5b3VyIGVkaXRvcjpcbi8vIGh0dHBzOi8vZGVuby5sYW5kL21hbnVhbC9nZXR0aW5nX3N0YXJ0ZWQvc2V0dXBfeW91cl9lbnZpcm9ubWVudFxuLy8gVGhpcyBlbmFibGVzIGF1dG9jb21wbGV0ZSwgZ28gdG8gZGVmaW5pdGlvbiwgZXRjLlxuXG5pbXBvcnQgeyBzZXJ2ZSB9IGZyb20gXCJodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xNzcuMS9odHRwL3NlcnZlci50c1wiXG5cbnNlcnZlKGFzeW5jICgpID0+IHtcbiAgcmV0dXJuIG5ldyBSZXNwb25zZShcbiAgICBgXCJIZWxsbyBmcm9tIEVkZ2UgRnVuY3Rpb25zIVwiYCxcbiAgICB7IGhlYWRlcnM6IHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIgfSB9LFxuICApXG59KVxuXG4vLyBUbyBpbnZva2U6XG4vLyBjdXJsICdodHRwOi8vbG9jYWxob3N0OjxLT05HX0hUVFBfUE9SVD4vZnVuY3Rpb25zL3YxL2hlbGxvJyBcXFxuLy8gICAtLWhlYWRlciAnQXV0aG9yaXphdGlvbjogQmVhcmVyIDxhbm9uL3NlcnZpY2Vfcm9sZSBBUEkga2V5PidcbiIKICAgIGNvbW1hbmQ6CiAgICAgIC0gc3RhcnQKICAgICAgLSAnLS1tYWluLXNlcnZpY2UnCiAgICAgIC0gL2hvbWUvZGVuby9mdW5jdGlvbnMvbWFpbgogIHN1cGFiYXNlLXN1cGF2aXNvcjoKICAgIGltYWdlOiAnc3VwYWJhc2Uvc3VwYXZpc29yOjEuMS41NicKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLXNTZkwnCiAgICAgICAgLSAnLW8nCiAgICAgICAgLSAvZGV2L251bGwKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjQwMDAvYXBpL2hlYWx0aCcKICAgICAgdGltZW91dDogNXMKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHJldHJpZXM6IDEwCiAgICBkZXBlbmRzX29uOgogICAgICBzdXBhYmFzZS1kYjoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBzdXBhYmFzZS1hbmFseXRpY3M6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPT0xFUl9URU5BTlRfSUQ9ZGV2X3RlbmFudAogICAgICAtIFBPT0xFUl9QT09MX01PREU9dHJhbnNhY3Rpb24KICAgICAgLSAnUE9PTEVSX0RFRkFVTFRfUE9PTF9TSVpFPSR7UE9PTEVSX0RFRkFVTFRfUE9PTF9TSVpFOi0yMH0nCiAgICAgIC0gJ1BPT0xFUl9NQVhfQ0xJRU5UX0NPTk49JHtQT09MRVJfTUFYX0NMSUVOVF9DT05OOi0xMDB9JwogICAgICAtIFBPUlQ9NDAwMAogICAgICAtICdQT1NUR1JFU19QT1JUPSR7UE9TVEdSRVNfUE9SVDotNTQzMn0nCiAgICAgIC0gJ1BPU1RHUkVTX0hPU1ROQU1FPSR7UE9TVEdSRVNfSE9TVE5BTUU6LXN1cGFiYXNlLWRifScKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdEQVRBQkFTRV9VUkw9ZWN0bzovL3N1cGFiYXNlX2FkbWluOiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU31AJHtQT1NUR1JFU19IT1NUTkFNRTotc3VwYWJhc2UtZGJ9OiR7UE9TVEdSRVNfUE9SVDotNTQzMn0vX3N1cGFiYXNlJwogICAgICAtIENMVVNURVJfUE9TVEdSRVM9dHJ1ZQogICAgICAtICdTRUNSRVRfS0VZX0JBU0U9JHtTRVJWSUNFX1BBU1NXT1JEX1NVUEFWSVNPUlNFQ1JFVH0nCiAgICAgIC0gJ1ZBVUxUX0VOQ19LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX1ZBVUxURU5DfScKICAgICAgLSAnQVBJX0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX0pXVH0nCiAgICAgIC0gJ01FVFJJQ1NfSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfSldUfScKICAgICAgLSBSRUdJT049bG9jYWwKICAgICAgLSAnRVJMX0FGTEFHUz0tcHJvdG9fZGlzdCBpbmV0X3RjcCcKICAgIGNvbW1hbmQ6CiAgICAgIC0gL2Jpbi9zaAogICAgICAtICctYycKICAgICAgLSAnL2FwcC9iaW4vbWlncmF0ZSAmJiAvYXBwL2Jpbi9zdXBhdmlzb3IgZXZhbCAiJCQoY2F0IC9ldGMvcG9vbGVyL3Bvb2xlci5leHMpIiAmJiAvYXBwL2Jpbi9zZXJ2ZXInCiAgICB2b2x1bWVzOgogICAgICAtCiAgICAgICAgdHlwZTogYmluZAogICAgICAgIHNvdXJjZTogLi92b2x1bWVzL3Bvb2xlci9wb29sZXIuZXhzCiAgICAgICAgdGFyZ2V0OiAvZXRjL3Bvb2xlci9wb29sZXIuZXhzCiAgICAgICAgY29udGVudDogIns6b2ssIF99ID0gQXBwbGljYXRpb24uZW5zdXJlX2FsbF9zdGFydGVkKDpzdXBhdmlzb3IpXG57Om9rLCB2ZXJzaW9ufSA9XG4gICAgY2FzZSBTdXBhdmlzb3IuUmVwby5xdWVyeSEoXCJzZWxlY3QgdmVyc2lvbigpXCIpIGRvXG4gICAgJXtyb3dzOiBbW3Zlcl1dfSAtPiBTdXBhdmlzb3IuSGVscGVycy5wYXJzZV9wZ192ZXJzaW9uKHZlcilcbiAgICBfIC0+IG5pbFxuICAgIGVuZFxucGFyYW1zID0gJXtcbiAgICBcImV4dGVybmFsX2lkXCIgPT4gU3lzdGVtLmdldF9lbnYoXCJQT09MRVJfVEVOQU5UX0lEXCIpLFxuICAgIFwiZGJfaG9zdFwiID0+IFN5c3RlbS5nZXRfZW52KFwiUE9TVEdSRVNfSE9TVE5BTUVcIiksXG4gICAgXCJkYl9wb3J0XCIgPT4gU3lzdGVtLmdldF9lbnYoXCJQT1NUR1JFU19QT1JUXCIpIHw+IFN0cmluZy50b19pbnRlZ2VyKCksXG4gICAgXCJkYl9kYXRhYmFzZVwiID0+IFN5c3RlbS5nZXRfZW52KFwiUE9TVEdSRVNfREJcIiksXG4gICAgXCJyZXF1aXJlX3VzZXJcIiA9PiBmYWxzZSxcbiAgICBcImF1dGhfcXVlcnlcIiA9PiBcIlNFTEVDVCAqIEZST00gcGdib3VuY2VyLmdldF9hdXRoKCQxKVwiLFxuICAgIFwiZGVmYXVsdF9tYXhfY2xpZW50c1wiID0+IFN5c3RlbS5nZXRfZW52KFwiUE9PTEVSX01BWF9DTElFTlRfQ09OTlwiKSxcbiAgICBcImRlZmF1bHRfcG9vbF9zaXplXCIgPT4gU3lzdGVtLmdldF9lbnYoXCJQT09MRVJfREVGQVVMVF9QT09MX1NJWkVcIiksXG4gICAgXCJkZWZhdWx0X3BhcmFtZXRlcl9zdGF0dXNcIiA9PiAle1wic2VydmVyX3ZlcnNpb25cIiA9PiB2ZXJzaW9ufSxcbiAgICBcInVzZXJzXCIgPT4gWyV7XG4gICAgXCJkYl91c2VyXCIgPT4gXCJwZ2JvdW5jZXJcIixcbiAgICBcImRiX3Bhc3N3b3JkXCIgPT4gU3lzdGVtLmdldF9lbnYoXCJQT1NUR1JFU19QQVNTV09SRFwiKSxcbiAgICBcIm1vZGVfdHlwZVwiID0+IFN5c3RlbS5nZXRfZW52KFwiUE9PTEVSX1BPT0xfTU9ERVwiKSxcbiAgICBcInBvb2xfc2l6ZVwiID0+IFN5c3RlbS5nZXRfZW52KFwiUE9PTEVSX0RFRkFVTFRfUE9PTF9TSVpFXCIpLFxuICAgIFwiaXNfbWFuYWdlclwiID0+IHRydWVcbiAgICB9XVxufVxuXG50ZW5hbnQgPSBTdXBhdmlzb3IuVGVuYW50cy5nZXRfdGVuYW50X2J5X2V4dGVybmFsX2lkKHBhcmFtc1tcImV4dGVybmFsX2lkXCJdKVxuXG5pZiB0ZW5hbnQgZG9cbiAgezpvaywgX30gPSBTdXBhdmlzb3IuVGVuYW50cy51cGRhdGVfdGVuYW50KHRlbmFudCwgcGFyYW1zKVxuZWxzZVxuICB7Om9rLCBffSA9IFN1cGF2aXNvci5UZW5hbnRzLmNyZWF0ZV90ZW5hbnQocGFyYW1zKVxuZW5kXG4iCg==", "tags": [ "firebase", "alternative", From e8b3f68e66083eeacaa0b3d9b7fd2d68b4446a45 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 11 Mar 2025 22:29:17 +0100 Subject: [PATCH 72/99] feat(ui): Improve GitHub repository selection and styling --- resources/css/app.css | 11 +++---- .../new/github-private-repository.blade.php | 31 ++++++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/resources/css/app.css b/resources/css/app.css index f89d65d80..175ac3259 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -25,11 +25,6 @@ body { @apply hidden !important; } -.input, -.select { - @apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300; -} - .input-sticky { @apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300 focus:ring-2 dark:focus:ring-coolgray-300 focus:ring-neutral-400 block w-full py-1.5 rounded border-0 text-sm ring-1 ring-inset; } @@ -51,7 +46,11 @@ body { .input, .select { - @apply block w-full py-1.5 rounded border-0 text-sm ring-1 ring-inset; + @apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300 block w-full py-1.5 rounded border-0 text-sm ring-1 ring-inset; +} + +.select { + @apply w-full; } .input[type="password"] { diff --git a/resources/views/livewire/project/new/github-private-repository.blade.php b/resources/views/livewire/project/new/github-private-repository.blade.php index 94779e714..f4175cf21 100644 --- a/resources/views/livewire/project/new/github-private-repository.blade.php +++ b/resources/views/livewire/project/new/github-private-repository.blade.php @@ -15,9 +15,9 @@
Deploy any public or private Git repositories through a GitHub App.
@if ($github_apps->count() !== 0) -

Select a Github App

@if ($current_step === 'github_apps') +

Select a Github App

@foreach ($github_apps as $ghapp)
@@ -43,25 +43,28 @@ @endif @if ($current_step === 'repository') @if ($repositories->count() > 0) -
- - @foreach ($repositories as $repo) - @if ($loop->first) - - @else - - @endif - @endforeach - +
+
+ + @foreach ($repositories as $repo) + @if ($loop->first) + + @else + + @endif + @endforeach + +
Load Repository
@else
No repositories found. Check your GitHub App configuration.
@endif @if ($branches->count() > 0) +

Configuration

From 79d4169eb1beafb5ecc245e16637c4e86b4e3091 Mon Sep 17 00:00:00 2001 From: Ben Hybert Date: Wed, 12 Mar 2025 10:21:20 +0000 Subject: [PATCH 73/99] dont hide logs for now as it doesnt work --- resources/views/livewire/project/application/advanced.blade.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/resources/views/livewire/project/application/advanced.blade.php b/resources/views/livewire/project/application/advanced.blade.php index de84f2230..0ea29b48e 100644 --- a/resources/views/livewire/project/application/advanced.blade.php +++ b/resources/views/livewire/project/application/advanced.blade.php @@ -58,11 +58,9 @@ @endif - @if ($isLogDrainEnabled === false)

Logs

- @endif @if ($application->git_based())

Git

From f648653e107628edc760047352751febc5e95d78 Mon Sep 17 00:00:00 2001 From: Ben Hybert Date: Wed, 12 Mar 2025 10:48:33 +0000 Subject: [PATCH 74/99] implement correct IF statement --- resources/views/livewire/project/application/advanced.blade.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/views/livewire/project/application/advanced.blade.php b/resources/views/livewire/project/application/advanced.blade.php index 0ea29b48e..ff55f297f 100644 --- a/resources/views/livewire/project/application/advanced.blade.php +++ b/resources/views/livewire/project/application/advanced.blade.php @@ -58,9 +58,11 @@ @endif + @if ($application?->destination?->server?->isLogDrainEnabled())

Logs

+ @endif @if ($application->git_based())

Git

From 3634d7d889e99a32aa2dfdf23ede527729e5a0fd Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 12 Mar 2025 14:46:08 +0100 Subject: [PATCH 75/99] refactor(ui): Unhide log toggle in application settings --- .../livewire/project/application/advanced.blade.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/resources/views/livewire/project/application/advanced.blade.php b/resources/views/livewire/project/application/advanced.blade.php index ff55f297f..82b154bcb 100644 --- a/resources/views/livewire/project/application/advanced.blade.php +++ b/resources/views/livewire/project/application/advanced.blade.php @@ -58,12 +58,9 @@ @endif - @if ($application?->destination?->server?->isLogDrainEnabled()) -

Logs

- - @endif - +

Logs

+ @if ($application->git_based())

Git

Date: Wed, 12 Mar 2025 15:26:48 +0100 Subject: [PATCH 76/99] fix(plane): update APP_RELEASE to v0.25.2 in environment configuration --- templates/compose/plane.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/plane.yaml b/templates/compose/plane.yaml index f765015da..9904a1c8d 100644 --- a/templates/compose/plane.yaml +++ b/templates/compose/plane.yaml @@ -5,7 +5,7 @@ x-app-env: &app-env environment: - - APP_RELEASE=${APP_RELEASE:-v0.25.1} + - APP_RELEASE=${APP_RELEASE:-v0.25.2} - WEB_URL=${SERVICE_FQDN_PLANE} - DEBUG=${DEBUG:-0} - CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGIN:-http://localhost} From a7318c2d77fcf16aea5b2c186cc993c620492558 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 12 Mar 2025 15:37:06 +0100 Subject: [PATCH 77/99] fix(domain): dispatch refreshStatus event after successful domain update --- app/Livewire/Project/Service/EditDomain.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/Livewire/Project/Service/EditDomain.php b/app/Livewire/Project/Service/EditDomain.php index e89aeda85..fb1c05255 100644 --- a/app/Livewire/Project/Service/EditDomain.php +++ b/app/Livewire/Project/Service/EditDomain.php @@ -43,12 +43,11 @@ class EditDomain extends Component updateCompose($this->application); if (str($this->application->fqdn)->contains(',')) { $this->dispatch('warning', 'Some services do not support multiple domains, which can lead to problems and is NOT RECOMMENDED.

Only use multiple domains if you know what you are doing.'); - } else { - ! $warning && $this->dispatch('success', 'Service saved.'); } $this->application->service->parse(); $this->dispatch('refresh'); $this->dispatch('configurationChanged'); + $this->dispatch('refreshStatus'); } catch (\Throwable $e) { $originalFqdn = $this->application->getOriginal('fqdn'); if ($originalFqdn !== $this->application->fqdn) { From fa619550c210641d3f81980320c2c05fab5fc046 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 12 Mar 2025 16:33:00 +0100 Subject: [PATCH 78/99] fix(database): correct container name generation for service databases --- app/Actions/Database/StartDatabaseProxy.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index 14be9d2bc..c16a5638a 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -27,21 +27,19 @@ class StartDatabaseProxy $server = data_get($database, 'destination.server'); $containerName = data_get($database, 'uuid'); $proxyContainerName = "{$database->uuid}-proxy"; - if ($database->getMorphClass() === \App\Models\ServiceDatabase::class) { $databaseType = $database->databaseType(); - // $connectPredefined = data_get($database, 'service.connect_to_docker_network'); $network = $database->service->uuid; $server = data_get($database, 'service.destination.server'); $proxyContainerName = "{$database->service->uuid}-proxy"; - $containerName = "{$database->name}-{$database->service->uuid}"; + $containerName = str($database->name)->slug().'-'.$database->s˝ervice->uuid; } - $internalPort = match ($databaseType) { 'standalone-mariadb', 'standalone-mysql' => 3306, 'standalone-postgresql', 'standalone-supabase/postgres' => 5432, 'standalone-redis', 'standalone-keydb', 'standalone-dragonfly' => 6379, 'standalone-clickhouse' => 9000, + 'standalone-mongodb' => 27017, }; $configuration_dir = database_proxy_dir($database->uuid); From d894c3d9036b11a0071bc7cf6855e80623199100 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 12 Mar 2025 16:33:35 +0100 Subject: [PATCH 79/99] feat(database): implement two-step confirmation for database deletion Added a new delete method in the Database component that includes a two-step confirmation process requiring the user to enter their password. If two-step confirmation is disabled, the deletion proceeds without password verification. Additionally, a confirmation modal has been integrated into the database view to prompt users before deletion, enhancing the safety of this critical operation. --- app/Livewire/Project/Service/Database.php | 26 +++++++++++++++++++ .../project/service/database.blade.php | 4 +++ .../livewire/project/service/index.blade.php | 8 +++--- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/app/Livewire/Project/Service/Database.php b/app/Livewire/Project/Service/Database.php index 9f02db05c..c3b7577e9 100644 --- a/app/Livewire/Project/Service/Database.php +++ b/app/Livewire/Project/Service/Database.php @@ -4,7 +4,10 @@ namespace App\Livewire\Project\Service; use App\Actions\Database\StartDatabaseProxy; use App\Actions\Database\StopDatabaseProxy; +use App\Models\InstanceSettings; use App\Models\ServiceDatabase; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Hash; use Livewire\Component; class Database extends Component @@ -15,6 +18,8 @@ class Database extends Component public $fileStorages; + public $parameters; + protected $listeners = ['refreshFileStorages']; protected $rules = [ @@ -34,12 +39,33 @@ class Database extends Component public function mount() { + $this->parameters = get_route_parameters(); if ($this->database->is_public) { $this->db_url_public = $this->database->getServiceDatabaseUrl(); } $this->refreshFileStorages(); } + public function delete($password) + { + if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) { + if (! Hash::check($password, Auth::user()->password)) { + $this->addError('password', 'The provided password is incorrect.'); + + return; + } + } + + try { + $this->database->delete(); + $this->dispatch('success', 'Database deleted.'); + + return redirect()->route('project.service.configuration', $this->parameters); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function instantSaveExclude() { $this->submit(); diff --git a/resources/views/livewire/project/service/database.blade.php b/resources/views/livewire/project/service/database.blade.php index c18473a14..8ec73b4de 100644 --- a/resources/views/livewire/project/service/database.blade.php +++ b/resources/views/livewire/project/service/database.blade.php @@ -7,6 +7,10 @@

{{ Str::headline($database->name) }}

@endif Save +
diff --git a/resources/views/livewire/project/service/index.blade.php b/resources/views/livewire/project/service/index.blade.php index 8796be966..d5c0c4778 100644 --- a/resources/views/livewire/project/service/index.blade.php +++ b/resources/views/livewire/project/service/index.blade.php @@ -3,8 +3,8 @@
+ class="{{ request()->routeIs('project.service.configuration') ? 'menu-item-active' : '' }}" wire:navigate + href="{{ route('project.service.configuration', [...$parameters, 'stack_service_uuid' => null]) }}"> General @if ($serviceDatabase?->isBackupSolutionAvailable()) Backups + @click.prevent="activeTab = 'backups'; window.location.hash = 'backups'" wire:navigate + href="#backups">Backups @endif
From 18fe524cdbd578d0f9f8bb8b787771f8f80f380c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 12 Mar 2025 16:34:42 +0100 Subject: [PATCH 80/99] fix(database): limit container name length for database proxy Updated the container name generation logic in StartDatabaseProxy to ensure the resulting name does not exceed 32 characters. This change prevents potential issues with container name length restrictions, enhancing the robustness of the database proxy setup. --- app/Actions/Database/StartDatabaseProxy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index c16a5638a..8d7d1ce2e 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -32,7 +32,7 @@ class StartDatabaseProxy $network = $database->service->uuid; $server = data_get($database, 'service.destination.server'); $proxyContainerName = "{$database->service->uuid}-proxy"; - $containerName = str($database->name)->slug().'-'.$database->s˝ervice->uuid; + $containerName = substr(str($database->name)->slug().'-'.$database->service->uuid, 0, 32); } $internalPort = match ($databaseType) { 'standalone-mariadb', 'standalone-mysql' => 3306, From 078ef62eb87fd27bef1494779777cd807a852501 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 12 Mar 2025 16:35:47 +0100 Subject: [PATCH 81/99] fix(database): handle unsupported database types in StartDatabaseProxy Added a default case to the switch statement in StartDatabaseProxy to throw an exception for unsupported database types. This change improves error handling and ensures that only valid database types are processed, enhancing the robustness of the database proxy functionality. --- app/Actions/Database/StartDatabaseProxy.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index 8d7d1ce2e..3b36e9b70 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -40,6 +40,7 @@ class StartDatabaseProxy 'standalone-redis', 'standalone-keydb', 'standalone-dragonfly' => 6379, 'standalone-clickhouse' => 9000, 'standalone-mongodb' => 27017, + default => throw new \Exception("Unsupported database type: $databaseType"), }; $configuration_dir = database_proxy_dir($database->uuid); From a07b581478acfc039c051e343d0e96ae054cbee3 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 12 Mar 2025 16:46:31 +0100 Subject: [PATCH 82/99] fix(database): simplify container name generation in StartDatabaseProxy --- app/Actions/Database/StartDatabaseProxy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index 3b36e9b70..c4a40f020 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -32,7 +32,7 @@ class StartDatabaseProxy $network = $database->service->uuid; $server = data_get($database, 'service.destination.server'); $proxyContainerName = "{$database->service->uuid}-proxy"; - $containerName = substr(str($database->name)->slug().'-'.$database->service->uuid, 0, 32); + $containerName = "{$database->name}-{$database->service->uuid}"; } $internalPort = match ($databaseType) { 'standalone-mariadb', 'standalone-mysql' => 3306, From 81ecbec1b6445413a36d11147f350b383b0b7bf3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 22:46:41 +0000 Subject: [PATCH 83/99] chore(deps): bump laravel/framework from 11.44.0 to 11.44.1 Bumps [laravel/framework](https://github.com/laravel/framework) from 11.44.0 to 11.44.1. - [Release notes](https://github.com/laravel/framework/releases) - [Changelog](https://github.com/laravel/framework/blob/12.x/CHANGELOG.md) - [Commits](https://github.com/laravel/framework/compare/v11.44.0...v11.44.1) --- updated-dependencies: - dependency-name: laravel/framework dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- composer.lock | 145 +++++++++++++++++++++++--------------------------- 1 file changed, 66 insertions(+), 79 deletions(-) diff --git a/composer.lock b/composer.lock index 65271cb1a..d070b919f 100644 --- a/composer.lock +++ b/composer.lock @@ -1079,16 +1079,16 @@ }, { "name": "brick/math", - "version": "0.12.1", + "version": "0.12.3", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "f510c0a40911935b77b86859eb5223d58d660df1" + "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", - "reference": "f510c0a40911935b77b86859eb5223d58d660df1", + "url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba", + "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba", "shasum": "" }, "require": { @@ -1097,7 +1097,7 @@ "require-dev": { "php-coveralls/php-coveralls": "^2.2", "phpunit/phpunit": "^10.1", - "vimeo/psalm": "5.16.0" + "vimeo/psalm": "6.8.8" }, "type": "library", "autoload": { @@ -1127,7 +1127,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.12.1" + "source": "https://github.com/brick/math/tree/0.12.3" }, "funding": [ { @@ -1135,7 +1135,7 @@ "type": "github" } ], - "time": "2023-11-29T23:19:16+00:00" + "time": "2025-02-28T13:11:00+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -2732,16 +2732,16 @@ }, { "name": "laravel/framework", - "version": "v11.44.0", + "version": "v11.44.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "e9a33da34815ac1ed46c7e4c477a775f4592f0a7" + "reference": "0883d4175f4e2b5c299e7087ad3c74f2ce195c6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/e9a33da34815ac1ed46c7e4c477a775f4592f0a7", - "reference": "e9a33da34815ac1ed46c7e4c477a775f4592f0a7", + "url": "https://api.github.com/repos/laravel/framework/zipball/0883d4175f4e2b5c299e7087ad3c74f2ce195c6d", + "reference": "0883d4175f4e2b5c299e7087ad3c74f2ce195c6d", "shasum": "" }, "require": { @@ -2849,7 +2849,7 @@ "league/flysystem-read-only": "^3.25.1", "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", - "orchestra/testbench-core": "^9.9.4", + "orchestra/testbench-core": "^9.11.2", "pda/pheanstalk": "^5.0.6", "php-http/discovery": "^1.15", "phpstan/phpstan": "^2.0", @@ -2943,7 +2943,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-02-24T13:08:54+00:00" + "time": "2025-03-05T15:34:10+00:00" }, { "name": "laravel/horizon", @@ -6944,16 +6944,16 @@ }, { "name": "ramsey/collection", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" + "reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", - "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "url": "https://api.github.com/repos/ramsey/collection/zipball/3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109", + "reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109", "shasum": "" }, "require": { @@ -6961,25 +6961,22 @@ }, "require-dev": { "captainhook/plugin-composer": "^5.3", - "ergebnis/composer-normalize": "^2.28.3", - "fakerphp/faker": "^1.21", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", "hamcrest/hamcrest-php": "^2.0", - "jangregor/phpstan-prophecy": "^1.0", - "mockery/mockery": "^1.5", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpcsstandards/phpcsutils": "^1.0.0-rc1", - "phpspec/prophecy-phpunit": "^2.0", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5", - "psalm/plugin-mockery": "^1.1", - "psalm/plugin-phpunit": "^0.18.4", - "ramsey/coding-standard": "^2.0.3", - "ramsey/conventional-commits": "^1.3", - "vimeo/psalm": "^5.4" + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" }, "type": "library", "extra": { @@ -7017,19 +7014,9 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/2.0.0" + "source": "https://github.com/ramsey/collection/tree/2.1.0" }, - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", - "type": "tidelift" - } - ], - "time": "2022-12-31T21:50:55+00:00" + "time": "2025-03-02T04:48:29+00:00" }, { "name": "ramsey/uuid", @@ -8887,16 +8874,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.2.3", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "959a74d044a6db21f4caa6d695648dcb5584cb49" + "reference": "aabf79938aa795350c07ce6464dd1985607d95d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/959a74d044a6db21f4caa6d695648dcb5584cb49", - "reference": "959a74d044a6db21f4caa6d695648dcb5584cb49", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/aabf79938aa795350c07ce6464dd1985607d95d5", + "reference": "aabf79938aa795350c07ce6464dd1985607d95d5", "shasum": "" }, "require": { @@ -8942,7 +8929,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.2.3" + "source": "https://github.com/symfony/error-handler/tree/v7.2.4" }, "funding": [ { @@ -8958,7 +8945,7 @@ "type": "tidelift" } ], - "time": "2025-01-07T09:39:55+00:00" + "time": "2025-02-02T20:27:07+00:00" }, { "name": "symfony/event-dispatcher", @@ -9260,16 +9247,16 @@ }, { "name": "symfony/http-kernel", - "version": "v7.2.3", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "caae9807f8e25a9b43ce8cc6fafab6cf91f0cc9b" + "reference": "9f1103734c5789798fefb90e91de4586039003ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/caae9807f8e25a9b43ce8cc6fafab6cf91f0cc9b", - "reference": "caae9807f8e25a9b43ce8cc6fafab6cf91f0cc9b", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/9f1103734c5789798fefb90e91de4586039003ed", + "reference": "9f1103734c5789798fefb90e91de4586039003ed", "shasum": "" }, "require": { @@ -9354,7 +9341,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.3" + "source": "https://github.com/symfony/http-kernel/tree/v7.2.4" }, "funding": [ { @@ -9370,7 +9357,7 @@ "type": "tidelift" } ], - "time": "2025-01-29T07:40:13+00:00" + "time": "2025-02-26T11:01:22+00:00" }, { "name": "symfony/mailer", @@ -9454,16 +9441,16 @@ }, { "name": "symfony/mime", - "version": "v7.2.3", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "2fc3b4bd67e4747e45195bc4c98bea4628476204" + "reference": "87ca22046b78c3feaff04b337f33b38510fd686b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/2fc3b4bd67e4747e45195bc4c98bea4628476204", - "reference": "2fc3b4bd67e4747e45195bc4c98bea4628476204", + "url": "https://api.github.com/repos/symfony/mime/zipball/87ca22046b78c3feaff04b337f33b38510fd686b", + "reference": "87ca22046b78c3feaff04b337f33b38510fd686b", "shasum": "" }, "require": { @@ -9518,7 +9505,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.2.3" + "source": "https://github.com/symfony/mime/tree/v7.2.4" }, "funding": [ { @@ -9534,7 +9521,7 @@ "type": "tidelift" } ], - "time": "2025-01-27T11:08:17+00:00" + "time": "2025-02-19T08:51:20+00:00" }, { "name": "symfony/options-resolver", @@ -10321,16 +10308,16 @@ }, { "name": "symfony/process", - "version": "v7.2.0", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" + "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", - "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "url": "https://api.github.com/repos/symfony/process/zipball/d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf", + "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf", "shasum": "" }, "require": { @@ -10362,7 +10349,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.2.0" + "source": "https://github.com/symfony/process/tree/v7.2.4" }, "funding": [ { @@ -10378,7 +10365,7 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:24:19+00:00" + "time": "2025-02-05T08:33:46+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -10778,16 +10765,16 @@ }, { "name": "symfony/translation", - "version": "v7.2.2", + "version": "v7.2.4", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "e2674a30132b7cc4d74540d6c2573aa363f05923" + "reference": "283856e6981286cc0d800b53bd5703e8e363f05a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/e2674a30132b7cc4d74540d6c2573aa363f05923", - "reference": "e2674a30132b7cc4d74540d6c2573aa363f05923", + "url": "https://api.github.com/repos/symfony/translation/zipball/283856e6981286cc0d800b53bd5703e8e363f05a", + "reference": "283856e6981286cc0d800b53bd5703e8e363f05a", "shasum": "" }, "require": { @@ -10853,7 +10840,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.2.2" + "source": "https://github.com/symfony/translation/tree/v7.2.4" }, "funding": [ { @@ -10869,7 +10856,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:18:10+00:00" + "time": "2025-02-13T10:27:23+00:00" }, { "name": "symfony/translation-contracts", @@ -15569,12 +15556,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.4" }, - "platform-dev": {}, - "plugin-api-version": "2.6.0" + "platform-dev": [], + "plugin-api-version": "2.3.0" } From 6d90ed2f8f0537477c94186e0e8bc1ff33d8a79d Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 13 Mar 2025 08:43:53 +0100 Subject: [PATCH 84/99] feat(assets): add new SVG logo for Coolify --- public/coolify-logo.svg | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 public/coolify-logo.svg diff --git a/public/coolify-logo.svg b/public/coolify-logo.svg new file mode 100644 index 000000000..6f4f641f5 --- /dev/null +++ b/public/coolify-logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + From 46f55c946362d50448e64454b6a01377424446f4 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 13 Mar 2025 08:44:04 +0100 Subject: [PATCH 85/99] feat(install): enhance Docker address pool configuration and validation Updated the install scripts to include support for custom Docker address pool configurations via environment variables. Added validation for the address pool base and size, with default values provided. The script now checks for existing configurations in the .env file and merges them appropriately, ensuring a more flexible and user-friendly installation process. Additionally, the version has been bumped to 1.8 to reflect these enhancements. --- other/nightly/install.sh | 270 +++++++++++++++++++++++++++++++++------ scripts/install.sh | 264 ++++++++++++++++++++++++++++++++------ 2 files changed, 457 insertions(+), 77 deletions(-) diff --git a/other/nightly/install.sh b/other/nightly/install.sh index 31d0a1759..d9a3656eb 100755 --- a/other/nightly/install.sh +++ b/other/nightly/install.sh @@ -1,6 +1,14 @@ #!/bin/bash ## Do not modify this file. You will lose the ability to install and auto-update! +## Environment variables that can be set: +## ROOT_USERNAME - Predefined root username +## ROOT_USER_EMAIL - Predefined root user email +## ROOT_USER_PASSWORD - Predefined root user password +## DOCKER_ADDRESS_POOL_BASE - Custom Docker address pool base (default: 10.0.0.0/8) +## DOCKER_ADDRESS_POOL_SIZE - Custom Docker address pool size (default: 24) +## AUTOUPDATE - Set to "false" to disable auto-updates + set -e # Exit immediately if a command exits with a non-zero status ## $1 could be empty, so we need to disable this check #set -u # Treat unset variables as an error and exit @@ -8,7 +16,7 @@ set -o pipefail # Cause a pipeline to return the status of the last command that CDN="https://cdn.coollabs.io/coolify-nightly" DATE=$(date +"%Y%m%d-%H%M%S") -VERSION="1.7" +VERSION="1.8" DOCKER_VERSION="27.0" # TODO: Ask for a user CURRENT_USER=$USER @@ -27,6 +35,80 @@ ROOT_USERNAME=${ROOT_USERNAME:-} ROOT_USER_EMAIL=${ROOT_USER_EMAIL:-} ROOT_USER_PASSWORD=${ROOT_USER_PASSWORD:-} +# Docker address pool configuration defaults +DOCKER_ADDRESS_POOL_BASE_DEFAULT="10.0.0.0/8" +DOCKER_ADDRESS_POOL_SIZE_DEFAULT=24 + +# Check if environment variables were explicitly provided +DOCKER_POOL_BASE_PROVIDED=false +DOCKER_POOL_SIZE_PROVIDED=false + +if [ -n "${DOCKER_ADDRESS_POOL_BASE+x}" ]; then + DOCKER_POOL_BASE_PROVIDED=true +fi + +if [ -n "${DOCKER_ADDRESS_POOL_SIZE+x}" ]; then + DOCKER_POOL_SIZE_PROVIDED=true +fi + +# Function to compare address pools +compare_address_pools() { + local base1="$1" + local size1="$2" + local base2="$3" + local size2="$4" + + # Normalize CIDR notation for comparison + local ip1=$(echo "$base1" | cut -d'/' -f1) + local prefix1=$(echo "$base1" | cut -d'/' -f2) + local ip2=$(echo "$base2" | cut -d'/' -f1) + local prefix2=$(echo "$base2" | cut -d'/' -f2) + + # Compare IPs and prefixes + if [ "$ip1" = "$ip2" ] && [ "$prefix1" = "$prefix2" ] && [ "$size1" = "$size2" ]; then + return 0 # Pools are the same + else + return 1 # Pools are different + fi +} + +# Docker address pool configuration +DOCKER_ADDRESS_POOL_BASE=${DOCKER_ADDRESS_POOL_BASE:-"$DOCKER_ADDRESS_POOL_BASE_DEFAULT"} +DOCKER_ADDRESS_POOL_SIZE=${DOCKER_ADDRESS_POOL_SIZE:-$DOCKER_ADDRESS_POOL_SIZE_DEFAULT} + +# Load Docker address pool configuration from .env file if it exists and environment variables were not provided +if [ -f "/data/coolify/source/.env" ] && [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then + ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2) + ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2) + + if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ] || [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then + echo "Found custom docker address pool configuration in .env file." + fi + + if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ]; then + echo "Using Docker address pool base: $ENV_DOCKER_ADDRESS_POOL_BASE" + DOCKER_ADDRESS_POOL_BASE="$ENV_DOCKER_ADDRESS_POOL_BASE" + fi + + if [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then + echo "Using Docker address pool size: $ENV_DOCKER_ADDRESS_POOL_SIZE" + DOCKER_ADDRESS_POOL_SIZE="$ENV_DOCKER_ADDRESS_POOL_SIZE" + fi +fi + +# Validate Docker address pool configuration +if ! [[ $DOCKER_ADDRESS_POOL_BASE =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]]; then + echo "Warning: Invalid DOCKER_ADDRESS_POOL_BASE format: $DOCKER_ADDRESS_POOL_BASE" + echo "Using default value: $DOCKER_ADDRESS_POOL_BASE_DEFAULT" + DOCKER_ADDRESS_POOL_BASE="$DOCKER_ADDRESS_POOL_BASE_DEFAULT" +fi + +if ! [[ $DOCKER_ADDRESS_POOL_SIZE =~ ^[0-9]+$ ]] || [ "$DOCKER_ADDRESS_POOL_SIZE" -lt 16 ] || [ "$DOCKER_ADDRESS_POOL_SIZE" -gt 28 ]; then + echo "Warning: Invalid DOCKER_ADDRESS_POOL_SIZE: $DOCKER_ADDRESS_POOL_SIZE (must be a number between 16 and 28)" + echo "Using default value: $DOCKER_ADDRESS_POOL_SIZE_DEFAULT" + DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE_DEFAULT +fi + TOTAL_SPACE=$(df -BG / | awk 'NR==2 {print $2}' | sed 's/G//') AVAILABLE_SPACE=$(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//') REQUIRED_TOTAL_SPACE=30 @@ -160,6 +242,7 @@ echo "| Docker | $DOCKER_VERSION" echo "| Coolify | $LATEST_VERSION" echo "| Helper | $LATEST_HELPER_VERSION" echo "| Realtime | $LATEST_REALTIME_VERSION" +echo "| Docker Pool | $DOCKER_ADDRESS_POOL_BASE (size $DOCKER_ADDRESS_POOL_SIZE)" echo -e "---------------------------------------------\n" echo -e "1. Installing required packages (curl, wget, git, jq, openssl). " @@ -336,13 +419,13 @@ if ! [ -x "$(command -v docker)" ]; then exit 1 fi ;; - "fedora") + "centos" | "fedora" | "rhel") if [ -x "$(command -v dnf5)" ]; then # dnf5 is available - dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/fedora/docker-ce.repo --overwrite >/dev/null 2>&1 + dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo --overwrite >/dev/null 2>&1 else # dnf5 is not available, use dnf - dnf config-manager --add-repo=https://download.docker.com/linux/fedora/docker-ce.repo >/dev/null 2>&1 + dnf config-manager --add-repo=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo >/dev/null 2>&1 fi dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 if ! [ -x "$(command -v docker)" ]; then @@ -375,38 +458,109 @@ else fi echo -e "4. Check Docker Configuration. " -mkdir -p /etc/docker -# shellcheck disable=SC2015 -test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json /etc/docker/daemon.json.original-"$DATE" || cat >/etc/docker/daemon.json </etc/docker/daemon.json.coolify <"$TEMP_FILE"; then - echo "Error merging JSON files" - exit 1 + +# Check if daemon.json exists and extract existing address pool configuration +if [ -f /etc/docker/daemon.json ]; then + echo " - Existing Docker configuration found." + if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then + EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) + EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) + + if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then + echo " - Found existing Docker address pool: $EXISTING_POOL_BASE (size $EXISTING_POOL_SIZE)" + + # Check if environment variables were explicitly provided + if [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then + echo " - No custom Docker address pool provided. Using existing configuration." + DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" + DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" + else + # Check if the provided values are different from existing ones + if compare_address_pools "$DOCKER_ADDRESS_POOL_BASE" "$DOCKER_ADDRESS_POOL_SIZE" "$EXISTING_POOL_BASE" "$EXISTING_POOL_SIZE"; then + echo " - Provided Docker address pool is identical to existing configuration." + else + echo " - Custom Docker address pool provided: $DOCKER_ADDRESS_POOL_BASE (size $DOCKER_ADDRESS_POOL_SIZE)" + echo " - This will override the existing configuration in daemon.json: $EXISTING_POOL_BASE (size $EXISTING_POOL_SIZE)" + fi + fi + fi + fi +fi + +echo " - Using Docker address pool: ${DOCKER_ADDRESS_POOL_BASE} (size ${DOCKER_ADDRESS_POOL_SIZE})" +echo " To override, set DOCKER_ADDRESS_POOL_BASE and DOCKER_ADDRESS_POOL_SIZE environment variables." + +mkdir -p /etc/docker + +# Backup original daemon.json if it exists +if [ -f /etc/docker/daemon.json ]; then + cp /etc/docker/daemon.json /etc/docker/daemon.json.original-"$DATE" +fi + +# Create coolify configuration with or without address pools based on whether they were explicitly provided +if [ "$DOCKER_POOL_BASE_PROVIDED" = true ] || [ "$DOCKER_POOL_SIZE_PROVIDED" = true ] || ! [ -f /etc/docker/daemon.json ]; then + # If environment variables were explicitly provided or daemon.json doesn't exist, + # create a new configuration with the specified address pools + cat >/etc/docker/daemon.json.coolify </dev/null 2>&1; then + echo " - Docker log configuration is already set correctly." + NEED_MERGE=false + else + # If no environment variables were provided and daemon.json exists, + # create a configuration without address pools to preserve existing ones + cat >/etc/docker/daemon.json.coolify </etc/docker/daemon.json <"$TEMP_FILE"; then + echo "Error merging JSON files" + exit 1 + fi + mv "$TEMP_FILE" /etc/docker/daemon.json fi -mv "$TEMP_FILE" /etc/docker/daemon.json restart_docker_service() { # Check if systemctl is available @@ -443,14 +597,30 @@ restart_docker_service() { if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE")) if [ "$DIFF" != "" ]; then + echo " - Docker configuration updated, checking changes..." + + # Check if address pools were changed + if echo "$DIFF" | grep -q "default-address-pools"; then + if [ "$DOCKER_POOL_BASE_PROVIDED" = true ] || [ "$DOCKER_POOL_SIZE_PROVIDED" = true ]; then + echo " - Docker address pools were explicitly changed by user request." + else + echo " - Warning: Docker address pools were changed but not by user request." + echo " This might be due to a configuration issue. Please check your Docker configuration." + fi + fi + + echo " - Restarting Docker daemon..." + restart_docker_service + else + echo " - Docker configuration is up to date, no restart needed." + fi +else + if [ "$NEED_MERGE" = true ]; then echo " - Docker configuration updated, restart docker daemon..." restart_docker_service else - echo " - Docker configuration is up to date." + echo " - Docker configuration is up to date, no restart needed." fi -else - echo " - Docker configuration updated, restart docker daemon..." - restart_docker_service fi echo -e "5. Download required files from CDN. " @@ -510,6 +680,26 @@ if [ "$AUTOUPDATE" = "false" ]; then sed -i "s|AUTOUPDATE=.*|AUTOUPDATE=false|g" /data/coolify/source/.env fi fi + +# Save Docker address pool configuration to .env file +if ! grep -q "DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env; then + echo "DOCKER_ADDRESS_POOL_BASE=$DOCKER_ADDRESS_POOL_BASE" >>/data/coolify/source/.env +else + # Only update if explicitly provided + if [ "$DOCKER_POOL_BASE_PROVIDED" = true ]; then + sed -i "s|DOCKER_ADDRESS_POOL_BASE=.*|DOCKER_ADDRESS_POOL_BASE=$DOCKER_ADDRESS_POOL_BASE|g" /data/coolify/source/.env + fi +fi + +if ! grep -q "DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env; then + echo "DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE" >>/data/coolify/source/.env +else + # Only update if explicitly provided + if [ "$DOCKER_POOL_SIZE_PROVIDED" = true ]; then + sed -i "s|DOCKER_ADDRESS_POOL_SIZE=.*|DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE|g" /data/coolify/source/.env + fi +fi + echo -e "8. Checking for SSH key for localhost access." if [ ! -f ~/.ssh/authorized_keys ]; then mkdir -p ~/.ssh @@ -572,4 +762,4 @@ if [ -n "$PRIVATE_IPS" ]; then done fi echo -e "\nWARNING: It is highly recommended to backup your Environment variables file (/data/coolify/source/.env) to a safe location, outside of this server (e.g. into a Password Manager).\n" -cp /data/coolify/source/.env /data/coolify/source/.env.backup +cp /data/coolify/source/.env /data/coolify/source/.env.backup \ No newline at end of file diff --git a/scripts/install.sh b/scripts/install.sh index 2162c0bf4..42bdb91b2 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,6 +1,14 @@ #!/bin/bash ## Do not modify this file. You will lose the ability to install and auto-update! +## Environment variables that can be set: +## ROOT_USERNAME - Predefined root username +## ROOT_USER_EMAIL - Predefined root user email +## ROOT_USER_PASSWORD - Predefined root user password +## DOCKER_ADDRESS_POOL_BASE - Custom Docker address pool base (default: 10.0.0.0/8) +## DOCKER_ADDRESS_POOL_SIZE - Custom Docker address pool size (default: 24) +## AUTOUPDATE - Set to "false" to disable auto-updates + set -e # Exit immediately if a command exits with a non-zero status ## $1 could be empty, so we need to disable this check #set -u # Treat unset variables as an error and exit @@ -8,7 +16,7 @@ set -o pipefail # Cause a pipeline to return the status of the last command that CDN="https://cdn.coollabs.io/coolify" DATE=$(date +"%Y%m%d-%H%M%S") -VERSION="1.7" +VERSION="1.8" DOCKER_VERSION="27.0" # TODO: Ask for a user CURRENT_USER=$USER @@ -27,6 +35,80 @@ ROOT_USERNAME=${ROOT_USERNAME:-} ROOT_USER_EMAIL=${ROOT_USER_EMAIL:-} ROOT_USER_PASSWORD=${ROOT_USER_PASSWORD:-} +# Docker address pool configuration defaults +DOCKER_ADDRESS_POOL_BASE_DEFAULT="10.0.0.0/8" +DOCKER_ADDRESS_POOL_SIZE_DEFAULT=24 + +# Check if environment variables were explicitly provided +DOCKER_POOL_BASE_PROVIDED=false +DOCKER_POOL_SIZE_PROVIDED=false + +if [ -n "${DOCKER_ADDRESS_POOL_BASE+x}" ]; then + DOCKER_POOL_BASE_PROVIDED=true +fi + +if [ -n "${DOCKER_ADDRESS_POOL_SIZE+x}" ]; then + DOCKER_POOL_SIZE_PROVIDED=true +fi + +# Function to compare address pools +compare_address_pools() { + local base1="$1" + local size1="$2" + local base2="$3" + local size2="$4" + + # Normalize CIDR notation for comparison + local ip1=$(echo "$base1" | cut -d'/' -f1) + local prefix1=$(echo "$base1" | cut -d'/' -f2) + local ip2=$(echo "$base2" | cut -d'/' -f1) + local prefix2=$(echo "$base2" | cut -d'/' -f2) + + # Compare IPs and prefixes + if [ "$ip1" = "$ip2" ] && [ "$prefix1" = "$prefix2" ] && [ "$size1" = "$size2" ]; then + return 0 # Pools are the same + else + return 1 # Pools are different + fi +} + +# Docker address pool configuration +DOCKER_ADDRESS_POOL_BASE=${DOCKER_ADDRESS_POOL_BASE:-"$DOCKER_ADDRESS_POOL_BASE_DEFAULT"} +DOCKER_ADDRESS_POOL_SIZE=${DOCKER_ADDRESS_POOL_SIZE:-$DOCKER_ADDRESS_POOL_SIZE_DEFAULT} + +# Load Docker address pool configuration from .env file if it exists and environment variables were not provided +if [ -f "/data/coolify/source/.env" ] && [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then + ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2) + ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2) + + if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ] || [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then + echo "Found custom docker address pool configuration in .env file." + fi + + if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ]; then + echo "Using Docker address pool base: $ENV_DOCKER_ADDRESS_POOL_BASE" + DOCKER_ADDRESS_POOL_BASE="$ENV_DOCKER_ADDRESS_POOL_BASE" + fi + + if [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then + echo "Using Docker address pool size: $ENV_DOCKER_ADDRESS_POOL_SIZE" + DOCKER_ADDRESS_POOL_SIZE="$ENV_DOCKER_ADDRESS_POOL_SIZE" + fi +fi + +# Validate Docker address pool configuration +if ! [[ $DOCKER_ADDRESS_POOL_BASE =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]]; then + echo "Warning: Invalid DOCKER_ADDRESS_POOL_BASE format: $DOCKER_ADDRESS_POOL_BASE" + echo "Using default value: $DOCKER_ADDRESS_POOL_BASE_DEFAULT" + DOCKER_ADDRESS_POOL_BASE="$DOCKER_ADDRESS_POOL_BASE_DEFAULT" +fi + +if ! [[ $DOCKER_ADDRESS_POOL_SIZE =~ ^[0-9]+$ ]] || [ "$DOCKER_ADDRESS_POOL_SIZE" -lt 16 ] || [ "$DOCKER_ADDRESS_POOL_SIZE" -gt 28 ]; then + echo "Warning: Invalid DOCKER_ADDRESS_POOL_SIZE: $DOCKER_ADDRESS_POOL_SIZE (must be a number between 16 and 28)" + echo "Using default value: $DOCKER_ADDRESS_POOL_SIZE_DEFAULT" + DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE_DEFAULT +fi + TOTAL_SPACE=$(df -BG / | awk 'NR==2 {print $2}' | sed 's/G//') AVAILABLE_SPACE=$(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//') REQUIRED_TOTAL_SPACE=30 @@ -160,6 +242,7 @@ echo "| Docker | $DOCKER_VERSION" echo "| Coolify | $LATEST_VERSION" echo "| Helper | $LATEST_HELPER_VERSION" echo "| Realtime | $LATEST_REALTIME_VERSION" +echo "| Docker Pool | $DOCKER_ADDRESS_POOL_BASE (size $DOCKER_ADDRESS_POOL_SIZE)" echo -e "---------------------------------------------\n" echo -e "1. Installing required packages (curl, wget, git, jq, openssl). " @@ -375,38 +458,109 @@ else fi echo -e "4. Check Docker Configuration. " -mkdir -p /etc/docker -# shellcheck disable=SC2015 -test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json /etc/docker/daemon.json.original-"$DATE" || cat >/etc/docker/daemon.json </etc/docker/daemon.json.coolify <"$TEMP_FILE"; then - echo "Error merging JSON files" - exit 1 + +# Check if daemon.json exists and extract existing address pool configuration +if [ -f /etc/docker/daemon.json ]; then + echo " - Existing Docker configuration found." + if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then + EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) + EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) + + if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then + echo " - Found existing Docker address pool: $EXISTING_POOL_BASE (size $EXISTING_POOL_SIZE)" + + # Check if environment variables were explicitly provided + if [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then + echo " - No custom Docker address pool provided. Using existing configuration." + DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" + DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" + else + # Check if the provided values are different from existing ones + if compare_address_pools "$DOCKER_ADDRESS_POOL_BASE" "$DOCKER_ADDRESS_POOL_SIZE" "$EXISTING_POOL_BASE" "$EXISTING_POOL_SIZE"; then + echo " - Provided Docker address pool is identical to existing configuration." + else + echo " - Custom Docker address pool provided: $DOCKER_ADDRESS_POOL_BASE (size $DOCKER_ADDRESS_POOL_SIZE)" + echo " - This will override the existing configuration in daemon.json: $EXISTING_POOL_BASE (size $EXISTING_POOL_SIZE)" + fi + fi + fi + fi +fi + +echo " - Using Docker address pool: ${DOCKER_ADDRESS_POOL_BASE} (size ${DOCKER_ADDRESS_POOL_SIZE})" +echo " To override, set DOCKER_ADDRESS_POOL_BASE and DOCKER_ADDRESS_POOL_SIZE environment variables." + +mkdir -p /etc/docker + +# Backup original daemon.json if it exists +if [ -f /etc/docker/daemon.json ]; then + cp /etc/docker/daemon.json /etc/docker/daemon.json.original-"$DATE" +fi + +# Create coolify configuration with or without address pools based on whether they were explicitly provided +if [ "$DOCKER_POOL_BASE_PROVIDED" = true ] || [ "$DOCKER_POOL_SIZE_PROVIDED" = true ] || ! [ -f /etc/docker/daemon.json ]; then + # If environment variables were explicitly provided or daemon.json doesn't exist, + # create a new configuration with the specified address pools + cat >/etc/docker/daemon.json.coolify </dev/null 2>&1; then + echo " - Docker log configuration is already set correctly." + NEED_MERGE=false + else + # If no environment variables were provided and daemon.json exists, + # create a configuration without address pools to preserve existing ones + cat >/etc/docker/daemon.json.coolify </etc/docker/daemon.json <"$TEMP_FILE"; then + echo "Error merging JSON files" + exit 1 + fi + mv "$TEMP_FILE" /etc/docker/daemon.json fi -mv "$TEMP_FILE" /etc/docker/daemon.json restart_docker_service() { # Check if systemctl is available @@ -443,14 +597,30 @@ restart_docker_service() { if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE")) if [ "$DIFF" != "" ]; then + echo " - Docker configuration updated, checking changes..." + + # Check if address pools were changed + if echo "$DIFF" | grep -q "default-address-pools"; then + if [ "$DOCKER_POOL_BASE_PROVIDED" = true ] || [ "$DOCKER_POOL_SIZE_PROVIDED" = true ]; then + echo " - Docker address pools were explicitly changed by user request." + else + echo " - Warning: Docker address pools were changed but not by user request." + echo " This might be due to a configuration issue. Please check your Docker configuration." + fi + fi + + echo " - Restarting Docker daemon..." + restart_docker_service + else + echo " - Docker configuration is up to date, no restart needed." + fi +else + if [ "$NEED_MERGE" = true ]; then echo " - Docker configuration updated, restart docker daemon..." restart_docker_service else - echo " - Docker configuration is up to date." + echo " - Docker configuration is up to date, no restart needed." fi -else - echo " - Docker configuration updated, restart docker daemon..." - restart_docker_service fi echo -e "5. Download required files from CDN. " @@ -510,6 +680,26 @@ if [ "$AUTOUPDATE" = "false" ]; then sed -i "s|AUTOUPDATE=.*|AUTOUPDATE=false|g" /data/coolify/source/.env fi fi + +# Save Docker address pool configuration to .env file +if ! grep -q "DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env; then + echo "DOCKER_ADDRESS_POOL_BASE=$DOCKER_ADDRESS_POOL_BASE" >>/data/coolify/source/.env +else + # Only update if explicitly provided + if [ "$DOCKER_POOL_BASE_PROVIDED" = true ]; then + sed -i "s|DOCKER_ADDRESS_POOL_BASE=.*|DOCKER_ADDRESS_POOL_BASE=$DOCKER_ADDRESS_POOL_BASE|g" /data/coolify/source/.env + fi +fi + +if ! grep -q "DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env; then + echo "DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE" >>/data/coolify/source/.env +else + # Only update if explicitly provided + if [ "$DOCKER_POOL_SIZE_PROVIDED" = true ]; then + sed -i "s|DOCKER_ADDRESS_POOL_SIZE=.*|DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE|g" /data/coolify/source/.env + fi +fi + echo -e "8. Checking for SSH key for localhost access." if [ ! -f ~/.ssh/authorized_keys ]; then mkdir -p ~/.ssh @@ -572,4 +762,4 @@ if [ -n "$PRIVATE_IPS" ]; then done fi echo -e "\nWARNING: It is highly recommended to backup your Environment variables file (/data/coolify/source/.env) to a safe location, outside of this server (e.g. into a Password Manager).\n" -cp /data/coolify/source/.env /data/coolify/source/.env.backup +cp /data/coolify/source/.env /data/coolify/source/.env.backup \ No newline at end of file From d0b8a20564c15a8c948fe4ce6c1c2bf342ada3b0 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 13 Mar 2025 10:47:27 +0100 Subject: [PATCH 86/99] feat(install): improve Docker address pool management and service restart logic Enhanced the install script to support a force override for Docker address pool configurations, allowing users to update existing settings if desired. The script now checks for existing configurations in the daemon.json file and provides clearer messaging regarding the use of custom pools versus existing configurations. Additionally, the restart logic for the Docker service has been streamlined, ensuring that unnecessary restarts are avoided when configurations remain unchanged. This update improves the flexibility and usability of the installation process. --- other/nightly/install.sh | 233 ++++++++++++++++++++++----------------- scripts/install.sh | 233 ++++++++++++++++++++++----------------- 2 files changed, 260 insertions(+), 206 deletions(-) diff --git a/other/nightly/install.sh b/other/nightly/install.sh index d9a3656eb..af28baee1 100755 --- a/other/nightly/install.sh +++ b/other/nightly/install.sh @@ -42,6 +42,7 @@ DOCKER_ADDRESS_POOL_SIZE_DEFAULT=24 # Check if environment variables were explicitly provided DOCKER_POOL_BASE_PROVIDED=false DOCKER_POOL_SIZE_PROVIDED=false +DOCKER_POOL_FORCE_OVERRIDE=${DOCKER_POOL_FORCE_OVERRIDE:-false} if [ -n "${DOCKER_ADDRESS_POOL_BASE+x}" ]; then DOCKER_POOL_BASE_PROVIDED=true @@ -51,6 +52,32 @@ if [ -n "${DOCKER_ADDRESS_POOL_SIZE+x}" ]; then DOCKER_POOL_SIZE_PROVIDED=true fi +restart_docker_service() { + # Check if systemctl is available + if command -v systemctl >/dev/null 2>&1; then + systemctl restart docker + if [ $? -eq 0 ]; then + echo " - Docker daemon restarted successfully" + else + echo " - Failed to restart Docker daemon" + return 1 + fi + # Check if service command is available + elif command -v service >/dev/null 2>&1; then + service docker restart + if [ $? -eq 0 ]; then + echo " - Docker daemon restarted successfully" + else + echo " - Failed to restart Docker daemon" + return 1 + fi + # If neither systemctl nor service is available + else + echo " - Error: No service management system found" + return 1 + fi +} + # Function to compare address pools compare_address_pools() { local base1="$1" @@ -81,32 +108,69 @@ if [ -f "/data/coolify/source/.env" ] && [ "$DOCKER_POOL_BASE_PROVIDED" = false ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2) ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2) - if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ] || [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then - echo "Found custom docker address pool configuration in .env file." - fi - if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ]; then - echo "Using Docker address pool base: $ENV_DOCKER_ADDRESS_POOL_BASE" DOCKER_ADDRESS_POOL_BASE="$ENV_DOCKER_ADDRESS_POOL_BASE" fi if [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then - echo "Using Docker address pool size: $ENV_DOCKER_ADDRESS_POOL_SIZE" DOCKER_ADDRESS_POOL_SIZE="$ENV_DOCKER_ADDRESS_POOL_SIZE" fi fi +# Check if daemon.json exists and extract existing address pool configuration +EXISTING_POOL_CONFIGURED=false +if [ -f /etc/docker/daemon.json ]; then + if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then + EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) + EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) + + if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then + echo "Found existing Docker network pool: $EXISTING_POOL_BASE/$EXISTING_POOL_SIZE" + EXISTING_POOL_CONFIGURED=true + + # Check if environment variables were explicitly provided + if [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then + DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" + DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" + else + # Check if force override is enabled + if [ "$DOCKER_POOL_FORCE_OVERRIDE" = true ]; then + echo "Force override enabled - network pool will be updated with $DOCKER_ADDRESS_POOL_BASE/$DOCKER_ADDRESS_POOL_SIZE." + else + echo "Custom pool provided but force override not enabled - using existing configuration." + echo "To force override, set DOCKER_POOL_FORCE_OVERRIDE=true" + echo "This won't change the existing docker networks, only the pool configuration for the newly created networks." + DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" + DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" + DOCKER_POOL_BASE_PROVIDED=false + DOCKER_POOL_SIZE_PROVIDED=false + fi + fi + fi + fi +fi + # Validate Docker address pool configuration if ! [[ $DOCKER_ADDRESS_POOL_BASE =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]]; then - echo "Warning: Invalid DOCKER_ADDRESS_POOL_BASE format: $DOCKER_ADDRESS_POOL_BASE" - echo "Using default value: $DOCKER_ADDRESS_POOL_BASE_DEFAULT" - DOCKER_ADDRESS_POOL_BASE="$DOCKER_ADDRESS_POOL_BASE_DEFAULT" + echo "Warning: Invalid network pool base format: $DOCKER_ADDRESS_POOL_BASE" + if [ "$EXISTING_POOL_CONFIGURED" = true ]; then + echo "Using existing configuration: $EXISTING_POOL_BASE" + DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" + else + echo "Using default configuration: $DOCKER_ADDRESS_POOL_BASE_DEFAULT" + DOCKER_ADDRESS_POOL_BASE="$DOCKER_ADDRESS_POOL_BASE_DEFAULT" + fi fi if ! [[ $DOCKER_ADDRESS_POOL_SIZE =~ ^[0-9]+$ ]] || [ "$DOCKER_ADDRESS_POOL_SIZE" -lt 16 ] || [ "$DOCKER_ADDRESS_POOL_SIZE" -gt 28 ]; then - echo "Warning: Invalid DOCKER_ADDRESS_POOL_SIZE: $DOCKER_ADDRESS_POOL_SIZE (must be a number between 16 and 28)" - echo "Using default value: $DOCKER_ADDRESS_POOL_SIZE_DEFAULT" - DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE_DEFAULT + echo "Warning: Invalid network pool size: $DOCKER_ADDRESS_POOL_SIZE (must be 16-28)" + if [ "$EXISTING_POOL_CONFIGURED" = true ]; then + echo "Using existing configuration: $EXISTING_POOL_SIZE" + DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" + else + echo "Using default configuration: $DOCKER_ADDRESS_POOL_SIZE_DEFAULT" + DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE_DEFAULT + fi fi TOTAL_SPACE=$(df -BG / | awk 'NR==2 {print $2}' | sed 's/G//') @@ -459,36 +523,8 @@ fi echo -e "4. Check Docker Configuration. " -# Check if daemon.json exists and extract existing address pool configuration -if [ -f /etc/docker/daemon.json ]; then - echo " - Existing Docker configuration found." - if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then - EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) - EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) - - if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then - echo " - Found existing Docker address pool: $EXISTING_POOL_BASE (size $EXISTING_POOL_SIZE)" - - # Check if environment variables were explicitly provided - if [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then - echo " - No custom Docker address pool provided. Using existing configuration." - DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" - DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" - else - # Check if the provided values are different from existing ones - if compare_address_pools "$DOCKER_ADDRESS_POOL_BASE" "$DOCKER_ADDRESS_POOL_SIZE" "$EXISTING_POOL_BASE" "$EXISTING_POOL_SIZE"; then - echo " - Provided Docker address pool is identical to existing configuration." - else - echo " - Custom Docker address pool provided: $DOCKER_ADDRESS_POOL_BASE (size $DOCKER_ADDRESS_POOL_SIZE)" - echo " - This will override the existing configuration in daemon.json: $EXISTING_POOL_BASE (size $EXISTING_POOL_SIZE)" - fi - fi - fi - fi -fi - -echo " - Using Docker address pool: ${DOCKER_ADDRESS_POOL_BASE} (size ${DOCKER_ADDRESS_POOL_SIZE})" -echo " To override, set DOCKER_ADDRESS_POOL_BASE and DOCKER_ADDRESS_POOL_SIZE environment variables." +echo " - Network pool configuration: ${DOCKER_ADDRESS_POOL_BASE}/${DOCKER_ADDRESS_POOL_SIZE}" +echo " - To override existing configuration: DOCKER_POOL_FORCE_OVERRIDE=true" mkdir -p /etc/docker @@ -498,10 +534,20 @@ if [ -f /etc/docker/daemon.json ]; then fi # Create coolify configuration with or without address pools based on whether they were explicitly provided -if [ "$DOCKER_POOL_BASE_PROVIDED" = true ] || [ "$DOCKER_POOL_SIZE_PROVIDED" = true ] || ! [ -f /etc/docker/daemon.json ]; then - # If environment variables were explicitly provided or daemon.json doesn't exist, - # create a new configuration with the specified address pools - cat >/etc/docker/daemon.json.coolify </dev/null) + CURRENT_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) + + if [ "$CURRENT_POOL_BASE" = "$DOCKER_ADDRESS_POOL_BASE" ] && [ "$CURRENT_POOL_SIZE" = "$DOCKER_ADDRESS_POOL_SIZE" ]; then + echo " - Network pool configuration unchanged, skipping update" + NEED_MERGE=false + else + # If force override is enabled or no existing configuration exists, + # create a new configuration with the specified address pools + echo " - Creating new Docker configuration with network pool: ${DOCKER_ADDRESS_POOL_BASE}/${DOCKER_ADDRESS_POOL_SIZE}" + cat >/etc/docker/daemon.json </etc/docker/daemon.json </dev/null 2>&1; then - echo " - Docker log configuration is already set correctly." + echo " - Log configuration is up to date" NEED_MERGE=false else - # If no environment variables were provided and daemon.json exists, - # create a configuration without address pools to preserve existing ones + # Create a configuration without address pools to preserve existing ones cat >/etc/docker/daemon.json.coolify </etc/docker/daemon.json <"$TEMP_FILE"; then - echo "Error merging JSON files" - exit 1 - fi - mv "$TEMP_FILE" /etc/docker/daemon.json -fi - -restart_docker_service() { - # Check if systemctl is available - if command -v systemctl >/dev/null 2>&1; then - echo " - Using systemctl to restart Docker." - systemctl restart docker - - if [ $? -eq 0 ]; then - echo " - Docker restarted successfully using systemctl." - else - echo " - Failed to restart Docker using systemctl." - return 1 - fi - - # Check if service command is available - elif command -v service >/dev/null 2>&1; then - echo " - Using service command to restart Docker." - service docker restart - - if [ $? -eq 0 ]; then - echo " - Docker restarted successfully using service." - else - echo " - Failed to restart Docker using service." - return 1 - fi - - # If neither systemctl nor service is available - else - echo " - Neither systemctl nor service command is available on this system." - return 1 - fi -} - if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then - DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE")) + DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE") || true) if [ "$DIFF" != "" ]; then - echo " - Docker configuration updated, checking changes..." + echo " - Checking configuration changes..." # Check if address pools were changed if echo "$DIFF" | grep -q "default-address-pools"; then if [ "$DOCKER_POOL_BASE_PROVIDED" = true ] || [ "$DOCKER_POOL_SIZE_PROVIDED" = true ]; then - echo " - Docker address pools were explicitly changed by user request." + echo " - Network pool updated per user request" else - echo " - Warning: Docker address pools were changed but not by user request." - echo " This might be due to a configuration issue. Please check your Docker configuration." + echo " - Warning: Network pool modified without explicit request" fi fi - echo " - Restarting Docker daemon..." - restart_docker_service + # Remove this redundant restart since we already restarted when writing the config + echo " - Configuration changes confirmed" + if [ "$NEED_MERGE" = true ]; then + echo " - Configuration updated - restarting Docker daemon..." + restart_docker_service + else + echo " - Configuration is up to date" + fi else - echo " - Docker configuration is up to date, no restart needed." + echo " - Configuration is up to date" fi else if [ "$NEED_MERGE" = true ]; then - echo " - Docker configuration updated, restart docker daemon..." + echo " - Configuration updated - restarting Docker daemon..." restart_docker_service else - echo " - Docker configuration is up to date, no restart needed." + echo " - Configuration is up to date" fi fi diff --git a/scripts/install.sh b/scripts/install.sh index 42bdb91b2..2c10174df 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -42,6 +42,7 @@ DOCKER_ADDRESS_POOL_SIZE_DEFAULT=24 # Check if environment variables were explicitly provided DOCKER_POOL_BASE_PROVIDED=false DOCKER_POOL_SIZE_PROVIDED=false +DOCKER_POOL_FORCE_OVERRIDE=${DOCKER_POOL_FORCE_OVERRIDE:-false} if [ -n "${DOCKER_ADDRESS_POOL_BASE+x}" ]; then DOCKER_POOL_BASE_PROVIDED=true @@ -51,6 +52,32 @@ if [ -n "${DOCKER_ADDRESS_POOL_SIZE+x}" ]; then DOCKER_POOL_SIZE_PROVIDED=true fi +restart_docker_service() { + # Check if systemctl is available + if command -v systemctl >/dev/null 2>&1; then + systemctl restart docker + if [ $? -eq 0 ]; then + echo " - Docker daemon restarted successfully" + else + echo " - Failed to restart Docker daemon" + return 1 + fi + # Check if service command is available + elif command -v service >/dev/null 2>&1; then + service docker restart + if [ $? -eq 0 ]; then + echo " - Docker daemon restarted successfully" + else + echo " - Failed to restart Docker daemon" + return 1 + fi + # If neither systemctl nor service is available + else + echo " - Error: No service management system found" + return 1 + fi +} + # Function to compare address pools compare_address_pools() { local base1="$1" @@ -81,32 +108,69 @@ if [ -f "/data/coolify/source/.env" ] && [ "$DOCKER_POOL_BASE_PROVIDED" = false ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2) ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2) - if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ] || [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then - echo "Found custom docker address pool configuration in .env file." - fi - if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ]; then - echo "Using Docker address pool base: $ENV_DOCKER_ADDRESS_POOL_BASE" DOCKER_ADDRESS_POOL_BASE="$ENV_DOCKER_ADDRESS_POOL_BASE" fi if [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then - echo "Using Docker address pool size: $ENV_DOCKER_ADDRESS_POOL_SIZE" DOCKER_ADDRESS_POOL_SIZE="$ENV_DOCKER_ADDRESS_POOL_SIZE" fi fi +# Check if daemon.json exists and extract existing address pool configuration +EXISTING_POOL_CONFIGURED=false +if [ -f /etc/docker/daemon.json ]; then + if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then + EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) + EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) + + if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then + echo "Found existing Docker network pool: $EXISTING_POOL_BASE/$EXISTING_POOL_SIZE" + EXISTING_POOL_CONFIGURED=true + + # Check if environment variables were explicitly provided + if [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then + DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" + DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" + else + # Check if force override is enabled + if [ "$DOCKER_POOL_FORCE_OVERRIDE" = true ]; then + echo "Force override enabled - network pool will be updated with $DOCKER_ADDRESS_POOL_BASE/$DOCKER_ADDRESS_POOL_SIZE." + else + echo "Custom pool provided but force override not enabled - using existing configuration." + echo "To force override, set DOCKER_POOL_FORCE_OVERRIDE=true" + echo "This won't change the existing docker networks, only the pool configuration for the newly created networks." + DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" + DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" + DOCKER_POOL_BASE_PROVIDED=false + DOCKER_POOL_SIZE_PROVIDED=false + fi + fi + fi + fi +fi + # Validate Docker address pool configuration if ! [[ $DOCKER_ADDRESS_POOL_BASE =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]]; then - echo "Warning: Invalid DOCKER_ADDRESS_POOL_BASE format: $DOCKER_ADDRESS_POOL_BASE" - echo "Using default value: $DOCKER_ADDRESS_POOL_BASE_DEFAULT" - DOCKER_ADDRESS_POOL_BASE="$DOCKER_ADDRESS_POOL_BASE_DEFAULT" + echo "Warning: Invalid network pool base format: $DOCKER_ADDRESS_POOL_BASE" + if [ "$EXISTING_POOL_CONFIGURED" = true ]; then + echo "Using existing configuration: $EXISTING_POOL_BASE" + DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" + else + echo "Using default configuration: $DOCKER_ADDRESS_POOL_BASE_DEFAULT" + DOCKER_ADDRESS_POOL_BASE="$DOCKER_ADDRESS_POOL_BASE_DEFAULT" + fi fi if ! [[ $DOCKER_ADDRESS_POOL_SIZE =~ ^[0-9]+$ ]] || [ "$DOCKER_ADDRESS_POOL_SIZE" -lt 16 ] || [ "$DOCKER_ADDRESS_POOL_SIZE" -gt 28 ]; then - echo "Warning: Invalid DOCKER_ADDRESS_POOL_SIZE: $DOCKER_ADDRESS_POOL_SIZE (must be a number between 16 and 28)" - echo "Using default value: $DOCKER_ADDRESS_POOL_SIZE_DEFAULT" - DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE_DEFAULT + echo "Warning: Invalid network pool size: $DOCKER_ADDRESS_POOL_SIZE (must be 16-28)" + if [ "$EXISTING_POOL_CONFIGURED" = true ]; then + echo "Using existing configuration: $EXISTING_POOL_SIZE" + DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" + else + echo "Using default configuration: $DOCKER_ADDRESS_POOL_SIZE_DEFAULT" + DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE_DEFAULT + fi fi TOTAL_SPACE=$(df -BG / | awk 'NR==2 {print $2}' | sed 's/G//') @@ -459,36 +523,8 @@ fi echo -e "4. Check Docker Configuration. " -# Check if daemon.json exists and extract existing address pool configuration -if [ -f /etc/docker/daemon.json ]; then - echo " - Existing Docker configuration found." - if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then - EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) - EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) - - if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then - echo " - Found existing Docker address pool: $EXISTING_POOL_BASE (size $EXISTING_POOL_SIZE)" - - # Check if environment variables were explicitly provided - if [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then - echo " - No custom Docker address pool provided. Using existing configuration." - DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" - DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" - else - # Check if the provided values are different from existing ones - if compare_address_pools "$DOCKER_ADDRESS_POOL_BASE" "$DOCKER_ADDRESS_POOL_SIZE" "$EXISTING_POOL_BASE" "$EXISTING_POOL_SIZE"; then - echo " - Provided Docker address pool is identical to existing configuration." - else - echo " - Custom Docker address pool provided: $DOCKER_ADDRESS_POOL_BASE (size $DOCKER_ADDRESS_POOL_SIZE)" - echo " - This will override the existing configuration in daemon.json: $EXISTING_POOL_BASE (size $EXISTING_POOL_SIZE)" - fi - fi - fi - fi -fi - -echo " - Using Docker address pool: ${DOCKER_ADDRESS_POOL_BASE} (size ${DOCKER_ADDRESS_POOL_SIZE})" -echo " To override, set DOCKER_ADDRESS_POOL_BASE and DOCKER_ADDRESS_POOL_SIZE environment variables." +echo " - Network pool configuration: ${DOCKER_ADDRESS_POOL_BASE}/${DOCKER_ADDRESS_POOL_SIZE}" +echo " - To override existing configuration: DOCKER_POOL_FORCE_OVERRIDE=true" mkdir -p /etc/docker @@ -498,10 +534,20 @@ if [ -f /etc/docker/daemon.json ]; then fi # Create coolify configuration with or without address pools based on whether they were explicitly provided -if [ "$DOCKER_POOL_BASE_PROVIDED" = true ] || [ "$DOCKER_POOL_SIZE_PROVIDED" = true ] || ! [ -f /etc/docker/daemon.json ]; then - # If environment variables were explicitly provided or daemon.json doesn't exist, - # create a new configuration with the specified address pools - cat >/etc/docker/daemon.json.coolify </dev/null) + CURRENT_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) + + if [ "$CURRENT_POOL_BASE" = "$DOCKER_ADDRESS_POOL_BASE" ] && [ "$CURRENT_POOL_SIZE" = "$DOCKER_ADDRESS_POOL_SIZE" ]; then + echo " - Network pool configuration unchanged, skipping update" + NEED_MERGE=false + else + # If force override is enabled or no existing configuration exists, + # create a new configuration with the specified address pools + echo " - Creating new Docker configuration with network pool: ${DOCKER_ADDRESS_POOL_BASE}/${DOCKER_ADDRESS_POOL_SIZE}" + cat >/etc/docker/daemon.json </etc/docker/daemon.json </dev/null 2>&1; then - echo " - Docker log configuration is already set correctly." + echo " - Log configuration is up to date" NEED_MERGE=false else - # If no environment variables were provided and daemon.json exists, - # create a configuration without address pools to preserve existing ones + # Create a configuration without address pools to preserve existing ones cat >/etc/docker/daemon.json.coolify </etc/docker/daemon.json <"$TEMP_FILE"; then - echo "Error merging JSON files" - exit 1 - fi - mv "$TEMP_FILE" /etc/docker/daemon.json -fi - -restart_docker_service() { - # Check if systemctl is available - if command -v systemctl >/dev/null 2>&1; then - echo " - Using systemctl to restart Docker." - systemctl restart docker - - if [ $? -eq 0 ]; then - echo " - Docker restarted successfully using systemctl." - else - echo " - Failed to restart Docker using systemctl." - return 1 - fi - - # Check if service command is available - elif command -v service >/dev/null 2>&1; then - echo " - Using service command to restart Docker." - service docker restart - - if [ $? -eq 0 ]; then - echo " - Docker restarted successfully using service." - else - echo " - Failed to restart Docker using service." - return 1 - fi - - # If neither systemctl nor service is available - else - echo " - Neither systemctl nor service command is available on this system." - return 1 - fi -} - if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then - DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE")) + DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE") || true) if [ "$DIFF" != "" ]; then - echo " - Docker configuration updated, checking changes..." + echo " - Checking configuration changes..." # Check if address pools were changed if echo "$DIFF" | grep -q "default-address-pools"; then if [ "$DOCKER_POOL_BASE_PROVIDED" = true ] || [ "$DOCKER_POOL_SIZE_PROVIDED" = true ]; then - echo " - Docker address pools were explicitly changed by user request." + echo " - Network pool updated per user request" else - echo " - Warning: Docker address pools were changed but not by user request." - echo " This might be due to a configuration issue. Please check your Docker configuration." + echo " - Warning: Network pool modified without explicit request" fi fi - echo " - Restarting Docker daemon..." - restart_docker_service + # Remove this redundant restart since we already restarted when writing the config + echo " - Configuration changes confirmed" + if [ "$NEED_MERGE" = true ]; then + echo " - Configuration updated - restarting Docker daemon..." + restart_docker_service + else + echo " - Configuration is up to date" + fi else - echo " - Docker configuration is up to date, no restart needed." + echo " - Configuration is up to date" fi else if [ "$NEED_MERGE" = true ]; then - echo " - Docker configuration updated, restart docker daemon..." + echo " - Configuration updated - restarting Docker daemon..." restart_docker_service else - echo " - Docker configuration is up to date, no restart needed." + echo " - Configuration is up to date" fi fi From 546b07c477fcb0ea6ef83de462b35e6422f94cd2 Mon Sep 17 00:00:00 2001 From: georgetasioulis Date: Thu, 13 Mar 2025 11:48:20 +0200 Subject: [PATCH 87/99] Update correct services URL --- resources/views/livewire/project/new/select.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/project/new/select.blade.php b/resources/views/livewire/project/new/select.blade.php index 730ced42a..000a3304d 100644 --- a/resources/views/livewire/project/new/select.blade.php +++ b/resources/views/livewire/project/new/select.blade.php @@ -80,7 +80,7 @@ respective companies, and use of them does not imply any affiliation or endorsement.
Find more services here. + href="https://coolify.io/docs/services/overview">here.
From 815a2701fc8cffb8926c445244779faffe1c51ed Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 13 Mar 2025 18:10:57 +0100 Subject: [PATCH 88/99] feat(install): add missing env variable to install script --- scripts/install-1.7.sh | 575 +++++++++++++++++++++++++++++++++++++++++ scripts/install.sh | 1 + 2 files changed, 576 insertions(+) create mode 100644 scripts/install-1.7.sh diff --git a/scripts/install-1.7.sh b/scripts/install-1.7.sh new file mode 100644 index 000000000..4c6eba4d6 --- /dev/null +++ b/scripts/install-1.7.sh @@ -0,0 +1,575 @@ +#!/bin/bash +## Do not modify this file. You will lose the ability to install and auto-update! + +set -e # Exit immediately if a command exits with a non-zero status +## $1 could be empty, so we need to disable this check +#set -u # Treat unset variables as an error and exit +set -o pipefail # Cause a pipeline to return the status of the last command that exited with a non-zero status +CDN="https://cdn.coollabs.io/coolify" +DATE=$(date +"%Y%m%d-%H%M%S") + +VERSION="1.7" +DOCKER_VERSION="27.0" +# TODO: Ask for a user +CURRENT_USER=$USER + +if [ $EUID != 0 ]; then + echo "Please run this script as root or with sudo" + exit +fi + +echo -e "Welcome to Coolify Installer!" +echo -e "This script will install everything for you. Sit back and relax." +echo -e "Source code: https://github.com/coollabsio/coolify/blob/main/scripts/install.sh\n" + +# Predefined root user +ROOT_USERNAME=${ROOT_USERNAME:-} +ROOT_USER_EMAIL=${ROOT_USER_EMAIL:-} +ROOT_USER_PASSWORD=${ROOT_USER_PASSWORD:-} + +TOTAL_SPACE=$(df -BG / | awk 'NR==2 {print $2}' | sed 's/G//') +AVAILABLE_SPACE=$(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//') +REQUIRED_TOTAL_SPACE=30 +REQUIRED_AVAILABLE_SPACE=20 +WARNING_SPACE=false + +if [ "$TOTAL_SPACE" -lt "$REQUIRED_TOTAL_SPACE" ]; then + WARNING_SPACE=true + cat << EOF +WARNING: Insufficient total disk space! + +Total disk space: ${TOTAL_SPACE}GB +Required disk space: ${REQUIRED_TOTAL_SPACE}GB + +================== +EOF +fi + +if [ "$AVAILABLE_SPACE" -lt "$REQUIRED_AVAILABLE_SPACE" ]; then + cat << EOF +WARNING: Insufficient available disk space! + +Available disk space: ${AVAILABLE_SPACE}GB +Required available space: ${REQUIRED_AVAILABLE_SPACE}GB + +================== +EOF +WARNING_SPACE=true +fi + +if [ "$WARNING_SPACE" = true ]; then + echo "Sleeping for 5 seconds." + sleep 5 +fi + +mkdir -p /data/coolify/{source,ssh,applications,databases,backups,services,proxy,webhooks-during-maintenance,sentinel} +mkdir -p /data/coolify/ssh/{keys,mux} +mkdir -p /data/coolify/proxy/dynamic + +chown -R 9999:root /data/coolify +chmod -R 700 /data/coolify + +INSTALLATION_LOG_WITH_DATE="/data/coolify/source/installation-${DATE}.log" + +exec > >(tee -a $INSTALLATION_LOG_WITH_DATE) 2>&1 + +getAJoke() { + JOKES=$(curl -s --max-time 2 "https://v2.jokeapi.dev/joke/Programming?blacklistFlags=nsfw,religious,political,racist,sexist,explicit&format=txt&type=single" || true) + if [ "$JOKES" != "" ]; then + echo -e " - Until then, here's a joke for you:\n" + echo -e "$JOKES\n" + fi +} +OS_TYPE=$(grep -w "ID" /etc/os-release | cut -d "=" -f 2 | tr -d '"') +ENV_FILE="/data/coolify/source/.env" + +# Check if the OS is manjaro, if so, change it to arch +if [ "$OS_TYPE" = "manjaro" ] || [ "$OS_TYPE" = "manjaro-arm" ]; then + OS_TYPE="arch" +fi + +# Check if the OS is Endeavour OS, if so, change it to arch +if [ "$OS_TYPE" = "endeavouros" ]; then + OS_TYPE="arch" +fi + +# Check if the OS is Asahi Linux, if so, change it to fedora +if [ "$OS_TYPE" = "fedora-asahi-remix" ]; then + OS_TYPE="fedora" +fi + +# Check if the OS is popOS, if so, change it to ubuntu +if [ "$OS_TYPE" = "pop" ]; then + OS_TYPE="ubuntu" +fi + +# Check if the OS is linuxmint, if so, change it to ubuntu +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 + OS_VERSION=$(grep -w "VERSION_ID" /etc/os-release | cut -d "=" -f 2 | tr -d '"') +fi + +# Install xargs on Amazon Linux 2023 - lol +if [ "$OS_TYPE" = 'amzn' ]; then + dnf install -y findutils >/dev/null +fi + +LATEST_VERSION=$(curl --silent $CDN/versions.json | grep -i version | xargs | awk '{print $2}' | tr -d ',') +LATEST_HELPER_VERSION=$(curl --silent $CDN/versions.json | grep -i version | xargs | awk '{print $6}' | tr -d ',') +LATEST_REALTIME_VERSION=$(curl --silent $CDN/versions.json | grep -i version | xargs | awk '{print $8}' | tr -d ',') + +if [ -z "$LATEST_HELPER_VERSION" ]; then + LATEST_HELPER_VERSION=latest +fi + +if [ -z "$LATEST_REALTIME_VERSION" ]; then + LATEST_REALTIME_VERSION=latest +fi + + +case "$OS_TYPE" in +arch | ubuntu | debian | raspbian | centos | fedora | rhel | ol | rocky | sles | opensuse-leap | opensuse-tumbleweed | almalinux | amzn | alpine) ;; +*) + echo "This script only supports Debian, Redhat, Arch Linux, Alpine Linux, or SLES based operating systems for now." + exit + ;; +esac + +# Overwrite LATEST_VERSION if user pass a version number +if [ "$1" != "" ]; then + LATEST_VERSION=$1 + LATEST_VERSION="${LATEST_VERSION,,}" + LATEST_VERSION="${LATEST_VERSION#v}" +fi + + + +echo -e "---------------------------------------------" +echo "| Operating System | $OS_TYPE $OS_VERSION" +echo "| Docker | $DOCKER_VERSION" +echo "| Coolify | $LATEST_VERSION" +echo "| Helper | $LATEST_HELPER_VERSION" +echo "| Realtime | $LATEST_REALTIME_VERSION" +echo -e "---------------------------------------------\n" +echo -e "1. Installing required packages (curl, wget, git, jq, openssl). " + +case "$OS_TYPE" in +arch) + pacman -Sy --noconfirm --needed curl wget git jq openssl >/dev/null || true + ;; +alpine) + sed -i '/^#.*\/community/s/^#//' /etc/apk/repositories + apk update >/dev/null + apk add curl wget git jq openssl >/dev/null + ;; +ubuntu | debian | raspbian) + apt-get update -y >/dev/null + apt-get install -y curl wget git jq openssl >/dev/null + ;; +centos | fedora | rhel | ol | rocky | almalinux | amzn) + if [ "$OS_TYPE" = "amzn" ]; then + dnf install -y wget git jq openssl >/dev/null + else + if ! command -v dnf >/dev/null; then + yum install -y dnf >/dev/null + fi + if ! command -v curl >/dev/null; then + dnf install -y curl >/dev/null + fi + dnf install -y wget git jq openssl >/dev/null + fi + ;; +sles | opensuse-leap | opensuse-tumbleweed) + zypper refresh >/dev/null + zypper install -y curl wget git jq openssl >/dev/null + ;; +*) + echo "This script only supports Debian, Redhat, Arch Linux, or SLES based operating systems for now." + exit + ;; +esac + + +echo -e "2. Check OpenSSH server configuration. " + +# Detect OpenSSH server +SSH_DETECTED=false +if [ -x "$(command -v systemctl)" ]; then + if systemctl status sshd >/dev/null 2>&1; then + echo " - OpenSSH server is installed." + SSH_DETECTED=true + elif systemctl status ssh >/dev/null 2>&1; then + echo " - OpenSSH server is installed." + SSH_DETECTED=true + fi +elif [ -x "$(command -v service)" ]; then + if service sshd status >/dev/null 2>&1; then + echo " - OpenSSH server is installed." + SSH_DETECTED=true + elif service ssh status >/dev/null 2>&1; then + echo " - OpenSSH server is installed." + SSH_DETECTED=true + fi +fi + + +if [ "$SSH_DETECTED" = "false" ]; then + echo " - OpenSSH server not detected. Installing OpenSSH server." + case "$OS_TYPE" in + arch) + pacman -Sy --noconfirm openssh >/dev/null + systemctl enable sshd >/dev/null 2>&1 + systemctl start sshd >/dev/null 2>&1 + ;; + alpine) + apk add openssh >/dev/null + rc-update add sshd default >/dev/null 2>&1 + service sshd start >/dev/null 2>&1 + ;; + ubuntu | debian | raspbian) + apt-get update -y >/dev/null + apt-get install -y openssh-server >/dev/null + systemctl enable ssh >/dev/null 2>&1 + systemctl start ssh >/dev/null 2>&1 + ;; + centos | fedora | rhel | ol | rocky | almalinux | amzn) + if [ "$OS_TYPE" = "amzn" ]; then + dnf install -y openssh-server >/dev/null + else + dnf install -y openssh-server >/dev/null + fi + systemctl enable sshd >/dev/null 2>&1 + systemctl start sshd >/dev/null 2>&1 + ;; + sles | opensuse-leap | opensuse-tumbleweed) + zypper install -y openssh >/dev/null + systemctl enable sshd >/dev/null 2>&1 + systemctl start sshd >/dev/null 2>&1 + ;; + *) + echo "###############################################################################" + echo "WARNING: Could not detect and install OpenSSH server - this does not mean that it is not installed or not running, just that we could not detect it." + echo -e "Please make sure it is installed and running, otherwise Coolify cannot connect to the host system. \n" + echo "###############################################################################" + exit 1 + ;; + esac + echo " - OpenSSH server installed successfully." + SSH_DETECTED=true +fi + +# Detect SSH PermitRootLogin +SSH_PERMIT_ROOT_LOGIN=$(sshd -T | grep -i "permitrootlogin" | awk '{print $2}') || true +if [ "$SSH_PERMIT_ROOT_LOGIN" = "yes" ] || [ "$SSH_PERMIT_ROOT_LOGIN" = "without-password" ] || [ "$SSH_PERMIT_ROOT_LOGIN" = "prohibit-password" ]; then + echo " - SSH PermitRootLogin is enabled." +else + echo " - SSH PermitRootLogin is disabled." + echo " If you have problems with SSH, please read this: https://coolify.io/docs/knowledge-base/server/openssh" +fi + +# Detect if docker is installed via snap +if [ -x "$(command -v snap)" ]; then + SNAP_DOCKER_INSTALLED=$(snap list docker >/dev/null 2>&1 && echo "true" || echo "false") + if [ "$SNAP_DOCKER_INSTALLED" = "true" ]; then + echo " - Docker is installed via snap." + echo " Please note that Coolify does not support Docker installed via snap." + echo " Please remove Docker with snap (snap remove docker) and reexecute this script." + exit 1 + fi +fi + +echo -e "3. Check Docker Installation. " +if ! [ -x "$(command -v docker)" ]; then + echo " - Docker is not installed. Installing Docker. It may take a while." + getAJoke + case "$OS_TYPE" in + "almalinux") + dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo >/dev/null 2>&1 + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + ;; + "alpine") + apk add docker docker-cli-compose >/dev/null 2>&1 + rc-update add docker default >/dev/null 2>&1 + service docker start >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with apk. Try to install it manually." + echo " Please visit https://wiki.alpinelinux.org/wiki/Docker for more information." + exit 1 + fi + ;; + "arch") + pacman -Sy docker docker-compose --noconfirm >/dev/null 2>&1 + systemctl enable docker.service >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with pacman. Try to install it manually." + echo " Please visit https://wiki.archlinux.org/title/docker for more information." + exit 1 + fi + ;; + "amzn") + dnf install docker -y >/dev/null 2>&1 + DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} + mkdir -p $DOCKER_CONFIG/cli-plugins >/dev/null 2>&1 + curl -sL https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 + chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with dnf. Try to install it manually." + echo " Please visit https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/ for more information." + exit 1 + fi + ;; + "fedora") + if [ -x "$(command -v dnf5)" ]; then + # dnf5 is available + dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/fedora/docker-ce.repo --overwrite >/dev/null 2>&1 + else + # dnf5 is not available, use dnf + dnf config-manager --add-repo=https://download.docker.com/linux/fedora/docker-ce.repo >/dev/null 2>&1 + fi + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + ;; + *) + if [ "$OS_TYPE" = "ubuntu" ] && [ "$OS_VERSION" = "24.10" ]; then + echo "Docker automated installation is not supported on Ubuntu 24.10 (non-LTS release)." + echo "Please install Docker manually." + exit 1 + fi + curl -s https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh 2>&1 + if ! [ -x "$(command -v docker)" ]; then + curl -s https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker installation failed." + echo " Maybe your OS is not supported?" + echo " - Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + fi + esac + echo " - Docker installed successfully." +else + echo " - Docker is installed." +fi + +echo -e "4. Check Docker Configuration. " +mkdir -p /etc/docker +# shellcheck disable=SC2015 +test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json /etc/docker/daemon.json.original-"$DATE" || cat >/etc/docker/daemon.json </etc/docker/daemon.json.coolify <"$TEMP_FILE"; then + echo "Error merging JSON files" + exit 1 +fi +mv "$TEMP_FILE" /etc/docker/daemon.json + +restart_docker_service() { + # Check if systemctl is available + if command -v systemctl >/dev/null 2>&1; then + echo " - Using systemctl to restart Docker." + systemctl restart docker + + if [ $? -eq 0 ]; then + echo " - Docker restarted successfully using systemctl." + else + echo " - Failed to restart Docker using systemctl." + return 1 + fi + + # Check if service command is available + elif command -v service >/dev/null 2>&1; then + echo " - Using service command to restart Docker." + service docker restart + + if [ $? -eq 0 ]; then + echo " - Docker restarted successfully using service." + else + echo " - Failed to restart Docker using service." + return 1 + fi + + # If neither systemctl nor service is available + else + echo " - Neither systemctl nor service command is available on this system." + return 1 + fi +} + +if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then + DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE")) + if [ "$DIFF" != "" ]; then + echo " - Docker configuration updated, restart docker daemon..." + restart_docker_service + else + echo " - Docker configuration is up to date." + fi +else + echo " - Docker configuration updated, restart docker daemon..." + restart_docker_service +fi + +echo -e "5. Download required files from CDN. " +curl -fsSL $CDN/docker-compose.yml -o /data/coolify/source/docker-compose.yml +curl -fsSL $CDN/docker-compose.prod.yml -o /data/coolify/source/docker-compose.prod.yml +curl -fsSL $CDN/.env.production -o /data/coolify/source/.env.production +curl -fsSL $CDN/upgrade.sh -o /data/coolify/source/upgrade.sh + +echo -e "6. Make backup of .env to .env-$DATE" + +# Copy .env.example if .env does not exist +if [ -f $ENV_FILE ]; then + cp $ENV_FILE $ENV_FILE-$DATE +else + echo " - File does not exist: $ENV_FILE" + echo " - Copying .env.production to .env-$DATE" + cp /data/coolify/source/.env.production $ENV_FILE-$DATE + # Generate a secure APP_ID and APP_KEY + sed -i "s|^APP_ID=.*|APP_ID=$(openssl rand -hex 16)|" "$ENV_FILE-$DATE" + sed -i "s|^APP_KEY=.*|APP_KEY=base64:$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" + + # Generate a secure Postgres DB username and password + # Causes issues: database "random-user" does not exist + # sed -i "s|^DB_USERNAME=.*|DB_USERNAME=$(openssl rand -hex 16)|" "$ENV_FILE-$DATE" + sed -i "s|^DB_PASSWORD=.*|DB_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" + + # Generate a secure Redis password + sed -i "s|^REDIS_PASSWORD=.*|REDIS_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" + + # Generate secure Pusher credentials + sed -i "s|^PUSHER_APP_ID=.*|PUSHER_APP_ID=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" + sed -i "s|^PUSHER_APP_KEY=.*|PUSHER_APP_KEY=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" + sed -i "s|^PUSHER_APP_SECRET=.*|PUSHER_APP_SECRET=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" +fi + +# Add default root user credentials from environment variables +if [ -n "$ROOT_USERNAME" ] && [ -n "$ROOT_USER_EMAIL" ] && [ -n "$ROOT_USER_PASSWORD" ]; then + if grep -q "^ROOT_USERNAME=" "$ENV_FILE-$DATE"; then + sed -i "s|^ROOT_USERNAME=.*|ROOT_USERNAME=$ROOT_USERNAME|" "$ENV_FILE-$DATE" + fi + if grep -q "^ROOT_USER_EMAIL=" "$ENV_FILE-$DATE"; then + sed -i "s|^ROOT_USER_EMAIL=.*|ROOT_USER_EMAIL=$ROOT_USER_EMAIL|" "$ENV_FILE-$DATE" + fi + if grep -q "^ROOT_USER_PASSWORD=" "$ENV_FILE-$DATE"; then + sed -i "s|^ROOT_USER_PASSWORD=.*|ROOT_USER_PASSWORD=$ROOT_USER_PASSWORD|" "$ENV_FILE-$DATE" + fi +fi + +# Merge .env and .env.production. New values will be added to .env +echo -e "7. Propagating .env with new values - if necessary." +awk -F '=' '!seen[$1]++' "$ENV_FILE-$DATE" /data/coolify/source/.env.production > $ENV_FILE + +if [ "$AUTOUPDATE" = "false" ]; then + if ! grep -q "AUTOUPDATE=" /data/coolify/source/.env; then + echo "AUTOUPDATE=false" >>/data/coolify/source/.env + else + sed -i "s|AUTOUPDATE=.*|AUTOUPDATE=false|g" /data/coolify/source/.env + fi +fi +echo -e "8. Checking for SSH key for localhost access." +if [ ! -f ~/.ssh/authorized_keys ]; then + mkdir -p ~/.ssh + chmod 700 ~/.ssh + touch ~/.ssh/authorized_keys + chmod 600 ~/.ssh/authorized_keys +fi + +set +e +IS_COOLIFY_VOLUME_EXISTS=$(docker volume ls | grep coolify-db | wc -l) +set -e + +if [ "$IS_COOLIFY_VOLUME_EXISTS" -eq 0 ]; then + echo " - Generating SSH key." + ssh-keygen -t ed25519 -a 100 -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal -q -N "" -C coolify + chown 9999 /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal + sed -i "/coolify/d" ~/.ssh/authorized_keys + cat /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub >> ~/.ssh/authorized_keys + rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub +fi + +chown -R 9999:root /data/coolify +chmod -R 700 /data/coolify + +echo -e "9. Installing Coolify ($LATEST_VERSION)" +echo -e " - It could take a while based on your server's performance, network speed, stars, etc." +echo -e " - Please wait." +getAJoke + +bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" +echo " - Coolify installed successfully." +rm -f $ENV_FILE-$DATE + +echo " - Waiting for 20 seconds for Coolify (database migrations) to be ready." +getAJoke + +sleep 20 +echo -e "\033[0;35m + ____ _ _ _ _ _ + / ___|___ _ __ __ _ _ __ __ _| |_ _ _| | __ _| |_(_) ___ _ __ ___| | + | | / _ \| '_ \ / _\` | '__/ _\` | __| | | | |/ _\` | __| |/ _ \| '_ \/ __| | + | |__| (_) | | | | (_| | | | (_| | |_| |_| | | (_| | |_| | (_) | | | \__ \_| + \____\___/|_| |_|\__, |_| \__,_|\__|\__,_|_|\__,_|\__|_|\___/|_| |_|___(_) + |___/ +\033[0m" +echo -e "\nYour instance is ready to use!\n" +echo -e "You can access Coolify through your Public IP: http://$(curl -4s https://ifconfig.io):8000" + +set +e +DEFAULT_PRIVATE_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p') +PRIVATE_IPS=$(hostname -I 2>/dev/null || ip -o addr show scope global | awk '{print $4}' | cut -d/ -f1) +set -e + +if [ -n "$PRIVATE_IPS" ]; then + echo -e "\nIf your Public IP is not accessible, you can use the following Private IPs:\n" + for IP in $PRIVATE_IPS; do + if [ "$IP" != "$DEFAULT_PRIVATE_IP" ]; then + echo -e "http://$IP:8000" + fi + done +fi +echo -e "\nWARNING: It is highly recommended to backup your Environment variables file (/data/coolify/source/.env) to a safe location, outside of this server (e.g. into a Password Manager).\n" +cp /data/coolify/source/.env /data/coolify/source/.env.backup \ No newline at end of file diff --git a/scripts/install.sh b/scripts/install.sh index 2c10174df..292af38d2 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -7,6 +7,7 @@ ## ROOT_USER_PASSWORD - Predefined root user password ## DOCKER_ADDRESS_POOL_BASE - Custom Docker address pool base (default: 10.0.0.0/8) ## DOCKER_ADDRESS_POOL_SIZE - Custom Docker address pool size (default: 24) +## DOCKER_POOL_FORCE_OVERRIDE - Force override Docker address pool configuration (default: false) ## AUTOUPDATE - Set to "false" to disable auto-updates set -e # Exit immediately if a command exits with a non-zero status From 2c845461c95700920b794c7b5eb43c9eb546a532 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 13 Mar 2025 20:30:22 +0100 Subject: [PATCH 89/99] refactor(nginx): streamline default Nginx configuration and improve error handling Updated the default Nginx configuration function to enhance clarity and maintainability. Removed unnecessary redirection logic and added explicit handling for 404 errors, ensuring a more robust error management strategy. This refactor simplifies the configuration while maintaining essential functionality, contributing to a cleaner and more efficient setup. --- bootstrap/helpers/shared.php | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 17ddcbda0..db3085649 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -4054,29 +4054,24 @@ function defaultNginxConfiguration(): string { return 'server { location / { - root /usr/share/nginx/html; - index index.html index.htm; - try_files $uri $uri.html $uri/index.html $uri/index.htm $uri/ /index.html /index.htm =404; + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri.html $uri/index.html $uri/index.htm $uri/ =404; } + # Handle 404 errors + error_page 404 /404.html; + location = /404.html { + root /usr/share/nginx/html; + internal; + } + + # Handle server errors (50x) error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; - try_files $uri @redirect_to_index; internal; } - - error_page 404 = @handle_404; - - location @handle_404 { - root /usr/share/nginx/html; - try_files /404.html @redirect_to_index; - internal; - } - - location @redirect_to_index { - return 302 /; - } }'; } From 9dbe221ad58c10ebd466aafea3991d70416d4dd1 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 14 Mar 2025 13:20:45 +0100 Subject: [PATCH 90/99] refactor(install): clean up install script and enhance Docker installation logic Refactored the install script to improve readability by removing unnecessary whitespace and consolidating Docker installation logic into a dedicated function. This change enhances maintainability and clarity, particularly for the installation process across different operating systems. Additionally, the script now includes specific handling for Ubuntu 24.10, ensuring users receive appropriate guidance for installation. Overall, these updates contribute to a more streamlined and user-friendly installation experience. --- scripts/install.sh | 209 +++++++++++++++++++++++++-------------------- 1 file changed, 115 insertions(+), 94 deletions(-) diff --git a/scripts/install.sh b/scripts/install.sh index 292af38d2..a19236974 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -85,18 +85,18 @@ compare_address_pools() { local size1="$2" local base2="$3" local size2="$4" - + # Normalize CIDR notation for comparison local ip1=$(echo "$base1" | cut -d'/' -f1) local prefix1=$(echo "$base1" | cut -d'/' -f2) local ip2=$(echo "$base2" | cut -d'/' -f1) local prefix2=$(echo "$base2" | cut -d'/' -f2) - + # Compare IPs and prefixes if [ "$ip1" = "$ip2" ] && [ "$prefix1" = "$prefix2" ] && [ "$size1" = "$size2" ]; then - return 0 # Pools are the same + return 0 # Pools are the same else - return 1 # Pools are different + return 1 # Pools are different fi } @@ -108,11 +108,11 @@ DOCKER_ADDRESS_POOL_SIZE=${DOCKER_ADDRESS_POOL_SIZE:-$DOCKER_ADDRESS_POOL_SIZE_D if [ -f "/data/coolify/source/.env" ] && [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2) ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2) - + if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ]; then DOCKER_ADDRESS_POOL_BASE="$ENV_DOCKER_ADDRESS_POOL_BASE" fi - + if [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then DOCKER_ADDRESS_POOL_SIZE="$ENV_DOCKER_ADDRESS_POOL_SIZE" fi @@ -124,11 +124,11 @@ if [ -f /etc/docker/daemon.json ]; then if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) - + if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then echo "Found existing Docker network pool: $EXISTING_POOL_BASE/$EXISTING_POOL_SIZE" EXISTING_POOL_CONFIGURED=true - + # Check if environment variables were explicitly provided if [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" @@ -182,7 +182,7 @@ WARNING_SPACE=false if [ "$TOTAL_SPACE" -lt "$REQUIRED_TOTAL_SPACE" ]; then WARNING_SPACE=true - cat << EOF + cat <&1 + if ! [ -x "$(command -v docker)" ]; then + curl -s https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker installation failed." + echo " Maybe your OS is not supported?" + echo " - Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + fi +} echo -e "3. Check Docker Installation. " if ! [ -x "$(command -v docker)" ]; then echo " - Docker is not installed. Installing Docker. It may take a while." getAJoke case "$OS_TYPE" in - "almalinux") - dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo >/dev/null 2>&1 - dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + "almalinux") + dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo >/dev/null 2>&1 + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + ;; + "alpine") + apk add docker docker-cli-compose >/dev/null 2>&1 + rc-update add docker default >/dev/null 2>&1 + service docker start >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with apk. Try to install it manually." + echo " Please visit https://wiki.alpinelinux.org/wiki/Docker for more information." + exit 1 + fi + ;; + "arch") + pacman -Sy docker docker-compose --noconfirm >/dev/null 2>&1 + systemctl enable docker.service >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with pacman. Try to install it manually." + echo " Please visit https://wiki.archlinux.org/title/docker for more information." + exit 1 + fi + ;; + "amzn") + dnf install docker -y >/dev/null 2>&1 + DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} + mkdir -p $DOCKER_CONFIG/cli-plugins >/dev/null 2>&1 + curl -sL https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 + chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with dnf. Try to install it manually." + echo " Please visit https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/ for more information." + exit 1 + fi + ;; + "centos" | "fedora" | "rhel") + if [ -x "$(command -v dnf5)" ]; then + # dnf5 is available + dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo --overwrite >/dev/null 2>&1 + else + # dnf5 is not available, use dnf + dnf config-manager --add-repo=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo >/dev/null 2>&1 + fi + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + ;; + "ubuntu" | "debian" | "raspbian") + if [ "$OS_TYPE" = "ubuntu" ] && [ "$OS_VERSION" = "24.10" ]; then + echo " - Installing Docker for Ubuntu 24.10..." + apt-get update >/dev/null + apt-get install -y ca-certificates curl >/dev/null + install -m 0755 -d /etc/apt/keyrings + curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc + chmod a+r /etc/apt/keyrings/docker.asc + + # Add the repository to Apt sources + echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ + $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | + tee /etc/apt/sources.list.d/docker.list >/dev/null + apt-get update >/dev/null + apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin >/dev/null + if ! [ -x "$(command -v docker)" ]; then - echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + echo " - Docker installation failed." + echo " Please visit https://docs.docker.com/engine/install/ubuntu/ and install Docker manually to continue." exit 1 fi - systemctl start docker >/dev/null 2>&1 - systemctl enable docker >/dev/null 2>&1 - ;; - "alpine") - apk add docker docker-cli-compose >/dev/null 2>&1 - rc-update add docker default >/dev/null 2>&1 - service docker start >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Failed to install Docker with apk. Try to install it manually." - echo " Please visit https://wiki.alpinelinux.org/wiki/Docker for more information." - exit 1 - fi - ;; - "arch") - pacman -Sy docker docker-compose --noconfirm >/dev/null 2>&1 - systemctl enable docker.service >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Failed to install Docker with pacman. Try to install it manually." - echo " Please visit https://wiki.archlinux.org/title/docker for more information." - exit 1 - fi - ;; - "amzn") - dnf install docker -y >/dev/null 2>&1 - DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} - mkdir -p $DOCKER_CONFIG/cli-plugins >/dev/null 2>&1 - curl -sL https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 - chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 - systemctl start docker >/dev/null 2>&1 - systemctl enable docker >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Failed to install Docker with dnf. Try to install it manually." - echo " Please visit https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/ for more information." - exit 1 - fi - ;; - "centos" | "fedora" | "rhel") - if [ -x "$(command -v dnf5)" ]; then - # dnf5 is available - dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo --overwrite >/dev/null 2>&1 - else - # dnf5 is not available, use dnf - dnf config-manager --add-repo=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo >/dev/null 2>&1 - fi - dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." - exit 1 - fi - systemctl start docker >/dev/null 2>&1 - systemctl enable docker >/dev/null 2>&1 - ;; - *) - if [ "$OS_TYPE" = "ubuntu" ] && [ "$OS_VERSION" = "24.10" ]; then - echo "Docker automated installation is not supported on Ubuntu 24.10 (non-LTS release)." - echo "Please install Docker manually." - exit 1 - fi - curl -s https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh 2>&1 - if ! [ -x "$(command -v docker)" ]; then - curl -s https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Docker installation failed." - echo " Maybe your OS is not supported?" - echo " - Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." - exit 1 - fi - fi + echo " - Docker installed successfully for Ubuntu 24.10." + else + install_docker + fi + ;; + *) + install_docker + ;; esac echo " - Docker installed successfully." else @@ -540,7 +561,7 @@ if [ "$DOCKER_POOL_FORCE_OVERRIDE" = true ] || [ "$EXISTING_POOL_CONFIGURED" = f if [ -f /etc/docker/daemon.json ]; then CURRENT_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) CURRENT_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) - + if [ "$CURRENT_POOL_BASE" = "$DOCKER_ADDRESS_POOL_BASE" ] && [ "$CURRENT_POOL_SIZE" = "$DOCKER_ADDRESS_POOL_SIZE" ]; then echo " - Network pool configuration unchanged, skipping update" NEED_MERGE=false @@ -621,7 +642,7 @@ if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE") || true) if [ "$DIFF" != "" ]; then echo " - Checking configuration changes..." - + # Check if address pools were changed if echo "$DIFF" | grep -q "default-address-pools"; then if [ "$DOCKER_POOL_BASE_PROVIDED" = true ] || [ "$DOCKER_POOL_SIZE_PROVIDED" = true ]; then @@ -630,7 +651,7 @@ if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then echo " - Warning: Network pool modified without explicit request" fi fi - + # Remove this redundant restart since we already restarted when writing the config echo " - Configuration changes confirmed" if [ "$NEED_MERGE" = true ]; then @@ -699,7 +720,7 @@ fi # Merge .env and .env.production. New values will be added to .env echo -e "7. Propagating .env with new values - if necessary." -awk -F '=' '!seen[$1]++' "$ENV_FILE-$DATE" /data/coolify/source/.env.production > $ENV_FILE +awk -F '=' '!seen[$1]++' "$ENV_FILE-$DATE" /data/coolify/source/.env.production >$ENV_FILE if [ "$AUTOUPDATE" = "false" ]; then if ! grep -q "AUTOUPDATE=" /data/coolify/source/.env; then @@ -745,7 +766,7 @@ if [ "$IS_COOLIFY_VOLUME_EXISTS" -eq 0 ]; then ssh-keygen -t ed25519 -a 100 -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal -q -N "" -C coolify chown 9999 /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal sed -i "/coolify/d" ~/.ssh/authorized_keys - cat /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub >> ~/.ssh/authorized_keys + cat /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub >>~/.ssh/authorized_keys rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub fi @@ -790,4 +811,4 @@ if [ -n "$PRIVATE_IPS" ]; then done fi echo -e "\nWARNING: It is highly recommended to backup your Environment variables file (/data/coolify/source/.env) to a safe location, outside of this server (e.g. into a Password Manager).\n" -cp /data/coolify/source/.env /data/coolify/source/.env.backup \ No newline at end of file +cp /data/coolify/source/.env /data/coolify/source/.env.backup From 3cf4d6364c5c32edc84be2414b30435c63f2cd78 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 14 Mar 2025 13:20:48 +0100 Subject: [PATCH 91/99] fix --- other/nightly/install.sh | 210 +++++++------- scripts/install-1.6.sh | 571 +++++++++++++++++++++++++++++++++++++++ scripts/install-1.7.sh | 514 +++++++++++++++++++++++++---------- 3 files changed, 1051 insertions(+), 244 deletions(-) create mode 100644 scripts/install-1.6.sh mode change 100644 => 100755 scripts/install-1.7.sh diff --git a/other/nightly/install.sh b/other/nightly/install.sh index af28baee1..72780e045 100755 --- a/other/nightly/install.sh +++ b/other/nightly/install.sh @@ -7,6 +7,7 @@ ## ROOT_USER_PASSWORD - Predefined root user password ## DOCKER_ADDRESS_POOL_BASE - Custom Docker address pool base (default: 10.0.0.0/8) ## DOCKER_ADDRESS_POOL_SIZE - Custom Docker address pool size (default: 24) +## DOCKER_POOL_FORCE_OVERRIDE - Force override Docker address pool configuration (default: false) ## AUTOUPDATE - Set to "false" to disable auto-updates set -e # Exit immediately if a command exits with a non-zero status @@ -84,18 +85,18 @@ compare_address_pools() { local size1="$2" local base2="$3" local size2="$4" - + # Normalize CIDR notation for comparison local ip1=$(echo "$base1" | cut -d'/' -f1) local prefix1=$(echo "$base1" | cut -d'/' -f2) local ip2=$(echo "$base2" | cut -d'/' -f1) local prefix2=$(echo "$base2" | cut -d'/' -f2) - + # Compare IPs and prefixes if [ "$ip1" = "$ip2" ] && [ "$prefix1" = "$prefix2" ] && [ "$size1" = "$size2" ]; then - return 0 # Pools are the same + return 0 # Pools are the same else - return 1 # Pools are different + return 1 # Pools are different fi } @@ -107,11 +108,11 @@ DOCKER_ADDRESS_POOL_SIZE=${DOCKER_ADDRESS_POOL_SIZE:-$DOCKER_ADDRESS_POOL_SIZE_D if [ -f "/data/coolify/source/.env" ] && [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2) ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2) - + if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ]; then DOCKER_ADDRESS_POOL_BASE="$ENV_DOCKER_ADDRESS_POOL_BASE" fi - + if [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then DOCKER_ADDRESS_POOL_SIZE="$ENV_DOCKER_ADDRESS_POOL_SIZE" fi @@ -123,11 +124,11 @@ if [ -f /etc/docker/daemon.json ]; then if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) - + if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then echo "Found existing Docker network pool: $EXISTING_POOL_BASE/$EXISTING_POOL_SIZE" EXISTING_POOL_CONFIGURED=true - + # Check if environment variables were explicitly provided if [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" @@ -181,7 +182,7 @@ WARNING_SPACE=false if [ "$TOTAL_SPACE" -lt "$REQUIRED_TOTAL_SPACE" ]; then WARNING_SPACE=true - cat << EOF + cat <&1 + if ! [ -x "$(command -v docker)" ]; then + curl -s https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker installation failed." + echo " Maybe your OS is not supported?" + echo " - Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + fi +} echo -e "3. Check Docker Installation. " if ! [ -x "$(command -v docker)" ]; then echo " - Docker is not installed. Installing Docker. It may take a while." getAJoke case "$OS_TYPE" in - "almalinux") - dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo >/dev/null 2>&1 - dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + "almalinux") + dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo >/dev/null 2>&1 + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + ;; + "alpine") + apk add docker docker-cli-compose >/dev/null 2>&1 + rc-update add docker default >/dev/null 2>&1 + service docker start >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with apk. Try to install it manually." + echo " Please visit https://wiki.alpinelinux.org/wiki/Docker for more information." + exit 1 + fi + ;; + "arch") + pacman -Sy docker docker-compose --noconfirm >/dev/null 2>&1 + systemctl enable docker.service >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with pacman. Try to install it manually." + echo " Please visit https://wiki.archlinux.org/title/docker for more information." + exit 1 + fi + ;; + "amzn") + dnf install docker -y >/dev/null 2>&1 + DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} + mkdir -p $DOCKER_CONFIG/cli-plugins >/dev/null 2>&1 + curl -sL https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 + chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with dnf. Try to install it manually." + echo " Please visit https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/ for more information." + exit 1 + fi + ;; + "centos" | "fedora" | "rhel") + if [ -x "$(command -v dnf5)" ]; then + # dnf5 is available + dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo --overwrite >/dev/null 2>&1 + else + # dnf5 is not available, use dnf + dnf config-manager --add-repo=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo >/dev/null 2>&1 + fi + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + ;; + "ubuntu" | "debian" | "raspbian") + if [ "$OS_TYPE" = "ubuntu" ] && [ "$OS_VERSION" = "24.10" ]; then + echo " - Installing Docker for Ubuntu 24.10..." + apt-get update >/dev/null + apt-get install -y ca-certificates curl >/dev/null + install -m 0755 -d /etc/apt/keyrings + curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc + chmod a+r /etc/apt/keyrings/docker.asc + + # Add the repository to Apt sources + echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ + $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | + tee /etc/apt/sources.list.d/docker.list >/dev/null + apt-get update >/dev/null + apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin >/dev/null + if ! [ -x "$(command -v docker)" ]; then - echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + echo " - Docker installation failed." + echo " Please visit https://docs.docker.com/engine/install/ubuntu/ and install Docker manually to continue." exit 1 fi - systemctl start docker >/dev/null 2>&1 - systemctl enable docker >/dev/null 2>&1 - ;; - "alpine") - apk add docker docker-cli-compose >/dev/null 2>&1 - rc-update add docker default >/dev/null 2>&1 - service docker start >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Failed to install Docker with apk. Try to install it manually." - echo " Please visit https://wiki.alpinelinux.org/wiki/Docker for more information." - exit 1 - fi - ;; - "arch") - pacman -Sy docker docker-compose --noconfirm >/dev/null 2>&1 - systemctl enable docker.service >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Failed to install Docker with pacman. Try to install it manually." - echo " Please visit https://wiki.archlinux.org/title/docker for more information." - exit 1 - fi - ;; - "amzn") - dnf install docker -y >/dev/null 2>&1 - DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} - mkdir -p $DOCKER_CONFIG/cli-plugins >/dev/null 2>&1 - curl -sL https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 - chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 - systemctl start docker >/dev/null 2>&1 - systemctl enable docker >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Failed to install Docker with dnf. Try to install it manually." - echo " Please visit https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/ for more information." - exit 1 - fi - ;; - "centos" | "fedora" | "rhel") - if [ -x "$(command -v dnf5)" ]; then - # dnf5 is available - dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo --overwrite >/dev/null 2>&1 - else - # dnf5 is not available, use dnf - dnf config-manager --add-repo=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo >/dev/null 2>&1 - fi - dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." - exit 1 - fi - systemctl start docker >/dev/null 2>&1 - systemctl enable docker >/dev/null 2>&1 - ;; - *) - if [ "$OS_TYPE" = "ubuntu" ] && [ "$OS_VERSION" = "24.10" ]; then - echo "Docker automated installation is not supported on Ubuntu 24.10 (non-LTS release)." - echo "Please install Docker manually." - exit 1 - fi - curl -s https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh 2>&1 - if ! [ -x "$(command -v docker)" ]; then - curl -s https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Docker installation failed." - echo " Maybe your OS is not supported?" - echo " - Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." - exit 1 - fi - fi + echo " - Docker installed successfully for Ubuntu 24.10." + else + install_docker + fi + ;; + *) + install_docker + ;; esac echo " - Docker installed successfully." else @@ -539,7 +561,7 @@ if [ "$DOCKER_POOL_FORCE_OVERRIDE" = true ] || [ "$EXISTING_POOL_CONFIGURED" = f if [ -f /etc/docker/daemon.json ]; then CURRENT_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) CURRENT_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) - + if [ "$CURRENT_POOL_BASE" = "$DOCKER_ADDRESS_POOL_BASE" ] && [ "$CURRENT_POOL_SIZE" = "$DOCKER_ADDRESS_POOL_SIZE" ]; then echo " - Network pool configuration unchanged, skipping update" NEED_MERGE=false @@ -620,7 +642,7 @@ if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE") || true) if [ "$DIFF" != "" ]; then echo " - Checking configuration changes..." - + # Check if address pools were changed if echo "$DIFF" | grep -q "default-address-pools"; then if [ "$DOCKER_POOL_BASE_PROVIDED" = true ] || [ "$DOCKER_POOL_SIZE_PROVIDED" = true ]; then @@ -629,7 +651,7 @@ if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then echo " - Warning: Network pool modified without explicit request" fi fi - + # Remove this redundant restart since we already restarted when writing the config echo " - Configuration changes confirmed" if [ "$NEED_MERGE" = true ]; then @@ -698,7 +720,7 @@ fi # Merge .env and .env.production. New values will be added to .env echo -e "7. Propagating .env with new values - if necessary." -awk -F '=' '!seen[$1]++' "$ENV_FILE-$DATE" /data/coolify/source/.env.production > $ENV_FILE +awk -F '=' '!seen[$1]++' "$ENV_FILE-$DATE" /data/coolify/source/.env.production >$ENV_FILE if [ "$AUTOUPDATE" = "false" ]; then if ! grep -q "AUTOUPDATE=" /data/coolify/source/.env; then @@ -744,7 +766,7 @@ if [ "$IS_COOLIFY_VOLUME_EXISTS" -eq 0 ]; then ssh-keygen -t ed25519 -a 100 -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal -q -N "" -C coolify chown 9999 /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal sed -i "/coolify/d" ~/.ssh/authorized_keys - cat /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub >> ~/.ssh/authorized_keys + cat /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub >>~/.ssh/authorized_keys rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub fi @@ -789,4 +811,4 @@ if [ -n "$PRIVATE_IPS" ]; then done fi echo -e "\nWARNING: It is highly recommended to backup your Environment variables file (/data/coolify/source/.env) to a safe location, outside of this server (e.g. into a Password Manager).\n" -cp /data/coolify/source/.env /data/coolify/source/.env.backup \ No newline at end of file +cp /data/coolify/source/.env /data/coolify/source/.env.backup diff --git a/scripts/install-1.6.sh b/scripts/install-1.6.sh new file mode 100644 index 000000000..50bce4e55 --- /dev/null +++ b/scripts/install-1.6.sh @@ -0,0 +1,571 @@ +#!/bin/bash +## Do not modify this file. You will lose the ability to install and auto-update! + +set -e # Exit immediately if a command exits with a non-zero status +## $1 could be empty, so we need to disable this check +#set -u # Treat unset variables as an error and exit +set -o pipefail # Cause a pipeline to return the status of the last command that exited with a non-zero status +CDN="https://cdn.coollabs.io/coolify" +DATE=$(date +"%Y%m%d-%H%M%S") + +VERSION="1.6" +DOCKER_VERSION="27.0" +# TODO: Ask for a user +CURRENT_USER=$USER + +if [ $EUID != 0 ]; then + echo "Please run this script as root or with sudo" + exit +fi + +echo -e "Welcome to Coolify Installer!" +echo -e "This script will install everything for you. Sit back and relax." +echo -e "Source code: https://github.com/coollabsio/coolify/blob/main/scripts/install.sh\n" + +# Predefined root user +ROOT_USERNAME=${ROOT_USERNAME:-} +ROOT_USER_EMAIL=${ROOT_USER_EMAIL:-} +ROOT_USER_PASSWORD=${ROOT_USER_PASSWORD:-} + +TOTAL_SPACE=$(df -BG / | awk 'NR==2 {print $2}' | sed 's/G//') +AVAILABLE_SPACE=$(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//') +REQUIRED_TOTAL_SPACE=30 +REQUIRED_AVAILABLE_SPACE=20 +WARNING_SPACE=false + +if [ "$TOTAL_SPACE" -lt "$REQUIRED_TOTAL_SPACE" ]; then + WARNING_SPACE=true + cat < >(tee -a $INSTALLATION_LOG_WITH_DATE) 2>&1 + +getAJoke() { + JOKES=$(curl -s --max-time 2 "https://v2.jokeapi.dev/joke/Programming?blacklistFlags=nsfw,religious,political,racist,sexist,explicit&format=txt&type=single" || true) + if [ "$JOKES" != "" ]; then + echo -e " - Until then, here's a joke for you:\n" + echo -e "$JOKES\n" + fi +} +OS_TYPE=$(grep -w "ID" /etc/os-release | cut -d "=" -f 2 | tr -d '"') +ENV_FILE="/data/coolify/source/.env" + +# Check if the OS is manjaro, if so, change it to arch +if [ "$OS_TYPE" = "manjaro" ] || [ "$OS_TYPE" = "manjaro-arm" ]; then + OS_TYPE="arch" +fi + +# Check if the OS is Endeavour OS, if so, change it to arch +if [ "$OS_TYPE" = "endeavouros" ]; then + OS_TYPE="arch" +fi + +# Check if the OS is Asahi Linux, if so, change it to fedora +if [ "$OS_TYPE" = "fedora-asahi-remix" ]; then + OS_TYPE="fedora" +fi + +# Check if the OS is popOS, if so, change it to ubuntu +if [ "$OS_TYPE" = "pop" ]; then + OS_TYPE="ubuntu" +fi + +# Check if the OS is linuxmint, if so, change it to ubuntu +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 + OS_VERSION=$(grep -w "VERSION_ID" /etc/os-release | cut -d "=" -f 2 | tr -d '"') +fi + +# Install xargs on Amazon Linux 2023 - lol +if [ "$OS_TYPE" = 'amzn' ]; then + dnf install -y findutils >/dev/null +fi + +LATEST_VERSION=$(curl --silent $CDN/versions.json | grep -i version | xargs | awk '{print $2}' | tr -d ',') +LATEST_HELPER_VERSION=$(curl --silent $CDN/versions.json | grep -i version | xargs | awk '{print $6}' | tr -d ',') +LATEST_REALTIME_VERSION=$(curl --silent $CDN/versions.json | grep -i version | xargs | awk '{print $8}' | tr -d ',') + +if [ -z "$LATEST_HELPER_VERSION" ]; then + LATEST_HELPER_VERSION=latest +fi + +if [ -z "$LATEST_REALTIME_VERSION" ]; then + LATEST_REALTIME_VERSION=latest +fi + +case "$OS_TYPE" in +arch | ubuntu | debian | raspbian | centos | fedora | rhel | ol | rocky | sles | opensuse-leap | opensuse-tumbleweed | almalinux | amzn | alpine) ;; +*) + echo "This script only supports Debian, Redhat, Arch Linux, Alpine Linux, or SLES based operating systems for now." + exit + ;; +esac + +# Overwrite LATEST_VERSION if user pass a version number +if [ "$1" != "" ]; then + LATEST_VERSION=$1 + LATEST_VERSION="${LATEST_VERSION,,}" + LATEST_VERSION="${LATEST_VERSION#v}" +fi + +echo -e "---------------------------------------------" +echo "| Operating System | $OS_TYPE $OS_VERSION" +echo "| Docker | $DOCKER_VERSION" +echo "| Coolify | $LATEST_VERSION" +echo "| Helper | $LATEST_HELPER_VERSION" +echo "| Realtime | $LATEST_REALTIME_VERSION" +echo -e "---------------------------------------------\n" +echo -e "1. Installing required packages (curl, wget, git, jq, openssl). " + +case "$OS_TYPE" in +arch) + pacman -Sy --noconfirm --needed curl wget git jq openssl >/dev/null || true + ;; +alpine) + sed -i '/^#.*\/community/s/^#//' /etc/apk/repositories + apk update >/dev/null + apk add curl wget git jq openssl >/dev/null + ;; +ubuntu | debian | raspbian) + apt-get update -y >/dev/null + apt-get install -y curl wget git jq openssl >/dev/null + ;; +centos | fedora | rhel | ol | rocky | almalinux | amzn) + if [ "$OS_TYPE" = "amzn" ]; then + dnf install -y wget git jq openssl >/dev/null + else + if ! command -v dnf >/dev/null; then + yum install -y dnf >/dev/null + fi + if ! command -v curl >/dev/null; then + dnf install -y curl >/dev/null + fi + dnf install -y wget git jq openssl >/dev/null + fi + ;; +sles | opensuse-leap | opensuse-tumbleweed) + zypper refresh >/dev/null + zypper install -y curl wget git jq openssl >/dev/null + ;; +*) + echo "This script only supports Debian, Redhat, Arch Linux, or SLES based operating systems for now." + exit + ;; +esac + +echo -e "2. Check OpenSSH server configuration. " + +# Detect OpenSSH server +SSH_DETECTED=false +if [ -x "$(command -v systemctl)" ]; then + if systemctl status sshd >/dev/null 2>&1; then + echo " - OpenSSH server is installed." + SSH_DETECTED=true + elif systemctl status ssh >/dev/null 2>&1; then + echo " - OpenSSH server is installed." + SSH_DETECTED=true + fi +elif [ -x "$(command -v service)" ]; then + if service sshd status >/dev/null 2>&1; then + echo " - OpenSSH server is installed." + SSH_DETECTED=true + elif service ssh status >/dev/null 2>&1; then + echo " - OpenSSH server is installed." + SSH_DETECTED=true + fi +fi + +if [ "$SSH_DETECTED" = "false" ]; then + echo " - OpenSSH server not detected. Installing OpenSSH server." + case "$OS_TYPE" in + arch) + pacman -Sy --noconfirm openssh >/dev/null + systemctl enable sshd >/dev/null 2>&1 + systemctl start sshd >/dev/null 2>&1 + ;; + alpine) + apk add openssh >/dev/null + rc-update add sshd default >/dev/null 2>&1 + service sshd start >/dev/null 2>&1 + ;; + ubuntu | debian | raspbian) + apt-get update -y >/dev/null + apt-get install -y openssh-server >/dev/null + systemctl enable ssh >/dev/null 2>&1 + systemctl start ssh >/dev/null 2>&1 + ;; + centos | fedora | rhel | ol | rocky | almalinux | amzn) + if [ "$OS_TYPE" = "amzn" ]; then + dnf install -y openssh-server >/dev/null + else + dnf install -y openssh-server >/dev/null + fi + systemctl enable sshd >/dev/null 2>&1 + systemctl start sshd >/dev/null 2>&1 + ;; + sles | opensuse-leap | opensuse-tumbleweed) + zypper install -y openssh >/dev/null + systemctl enable sshd >/dev/null 2>&1 + systemctl start sshd >/dev/null 2>&1 + ;; + *) + echo "###############################################################################" + echo "WARNING: Could not detect and install OpenSSH server - this does not mean that it is not installed or not running, just that we could not detect it." + echo -e "Please make sure it is installed and running, otherwise Coolify cannot connect to the host system. \n" + echo "###############################################################################" + exit 1 + ;; + esac + echo " - OpenSSH server installed successfully." + SSH_DETECTED=true +fi + +# Detect SSH PermitRootLogin +SSH_PERMIT_ROOT_LOGIN=$(sshd -T | grep -i "permitrootlogin" | awk '{print $2}') || true +if [ "$SSH_PERMIT_ROOT_LOGIN" = "yes" ] || [ "$SSH_PERMIT_ROOT_LOGIN" = "without-password" ] || [ "$SSH_PERMIT_ROOT_LOGIN" = "prohibit-password" ]; then + echo " - SSH PermitRootLogin is enabled." +else + echo " - SSH PermitRootLogin is disabled." + echo " If you have problems with SSH, please read this: https://coolify.io/docs/knowledge-base/server/openssh" +fi + +# Detect if docker is installed via snap +if [ -x "$(command -v snap)" ]; then + SNAP_DOCKER_INSTALLED=$(snap list docker >/dev/null 2>&1 && echo "true" || echo "false") + if [ "$SNAP_DOCKER_INSTALLED" = "true" ]; then + echo " - Docker is installed via snap." + echo " Please note that Coolify does not support Docker installed via snap." + echo " Please remove Docker with snap (snap remove docker) and reexecute this script." + exit 1 + fi +fi + +echo -e "3. Check Docker Installation. " +if ! [ -x "$(command -v docker)" ]; then + echo " - Docker is not installed. Installing Docker. It may take a while." + getAJoke + case "$OS_TYPE" in + "almalinux") + dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo >/dev/null 2>&1 + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + ;; + "alpine") + apk add docker docker-cli-compose >/dev/null 2>&1 + rc-update add docker default >/dev/null 2>&1 + service docker start >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with apk. Try to install it manually." + echo " Please visit https://wiki.alpinelinux.org/wiki/Docker for more information." + exit 1 + fi + ;; + "arch") + pacman -Sy docker docker-compose --noconfirm >/dev/null 2>&1 + systemctl enable docker.service >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with pacman. Try to install it manually." + echo " Please visit https://wiki.archlinux.org/title/docker for more information." + exit 1 + fi + ;; + "amzn") + dnf install docker -y >/dev/null 2>&1 + DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} + mkdir -p $DOCKER_CONFIG/cli-plugins >/dev/null 2>&1 + curl -sL https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 + chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with dnf. Try to install it manually." + echo " Please visit https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/ for more information." + exit 1 + fi + ;; + "fedora") + if [ -x "$(command -v dnf5)" ]; then + # dnf5 is available + dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/fedora/docker-ce.repo --overwrite >/dev/null 2>&1 + else + # dnf5 is not available, use dnf + dnf config-manager --add-repo=https://download.docker.com/linux/fedora/docker-ce.repo >/dev/null 2>&1 + fi + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + ;; + *) + if [ "$OS_TYPE" = "ubuntu" ] && [ "$OS_VERSION" = "24.10" ]; then + echo "Docker automated installation is not supported on Ubuntu 24.10 (non-LTS release)." + echo "Please install Docker manually." + exit 1 + fi + curl -s https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh 2>&1 + if ! [ -x "$(command -v docker)" ]; then + curl -s https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker installation failed." + echo " Maybe your OS is not supported?" + echo " - Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + fi + ;; + esac + echo " - Docker installed successfully." +else + echo " - Docker is installed." +fi + +echo -e "4. Check Docker Configuration. " +mkdir -p /etc/docker +# shellcheck disable=SC2015 +test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json /etc/docker/daemon.json.original-"$DATE" || cat >/etc/docker/daemon.json </etc/docker/daemon.json.coolify <"$TEMP_FILE"; then + echo "Error merging JSON files" + exit 1 +fi +mv "$TEMP_FILE" /etc/docker/daemon.json + +restart_docker_service() { + # Check if systemctl is available + if command -v systemctl >/dev/null 2>&1; then + echo " - Using systemctl to restart Docker." + systemctl restart docker + + if [ $? -eq 0 ]; then + echo " - Docker restarted successfully using systemctl." + else + echo " - Failed to restart Docker using systemctl." + return 1 + fi + + # Check if service command is available + elif command -v service >/dev/null 2>&1; then + echo " - Using service command to restart Docker." + service docker restart + + if [ $? -eq 0 ]; then + echo " - Docker restarted successfully using service." + else + echo " - Failed to restart Docker using service." + return 1 + fi + + # If neither systemctl nor service is available + else + echo " - Neither systemctl nor service command is available on this system." + return 1 + fi +} + +if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then + DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE")) + if [ "$DIFF" != "" ]; then + echo " - Docker configuration updated, restart docker daemon..." + restart_docker_service + else + echo " - Docker configuration is up to date." + fi +else + echo " - Docker configuration updated, restart docker daemon..." + restart_docker_service +fi + +echo -e "5. Download required files from CDN. " +curl -fsSL $CDN/docker-compose.yml -o /data/coolify/source/docker-compose.yml +curl -fsSL $CDN/docker-compose.prod.yml -o /data/coolify/source/docker-compose.prod.yml +curl -fsSL $CDN/.env.production -o /data/coolify/source/.env.production +curl -fsSL $CDN/upgrade.sh -o /data/coolify/source/upgrade.sh + +echo -e "6. Make backup of .env to .env-$DATE" + +# Copy .env.example if .env does not exist +if [ -f $ENV_FILE ]; then + cp $ENV_FILE $ENV_FILE-$DATE +else + echo " - File does not exist: $ENV_FILE" + echo " - Copying .env.production to .env-$DATE" + cp /data/coolify/source/.env.production $ENV_FILE-$DATE + # Generate a secure APP_ID and APP_KEY + sed -i "s|^APP_ID=.*|APP_ID=$(openssl rand -hex 16)|" "$ENV_FILE-$DATE" + sed -i "s|^APP_KEY=.*|APP_KEY=base64:$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" + + # Generate a secure Postgres DB username and password + # Causes issues: database "random-user" does not exist + # sed -i "s|^DB_USERNAME=.*|DB_USERNAME=$(openssl rand -hex 16)|" "$ENV_FILE-$DATE" + sed -i "s|^DB_PASSWORD=.*|DB_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" + + # Generate a secure Redis password + sed -i "s|^REDIS_PASSWORD=.*|REDIS_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" + + # Generate secure Pusher credentials + sed -i "s|^PUSHER_APP_ID=.*|PUSHER_APP_ID=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" + sed -i "s|^PUSHER_APP_KEY=.*|PUSHER_APP_KEY=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" + sed -i "s|^PUSHER_APP_SECRET=.*|PUSHER_APP_SECRET=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" +fi + +# Add default root user credentials from environment variables +if [ -n "$ROOT_USERNAME" ] && [ -n "$ROOT_USER_EMAIL" ] && [ -n "$ROOT_USER_PASSWORD" ]; then + if grep -q "^ROOT_USERNAME=" "$ENV_FILE-$DATE"; then + sed -i "s|^ROOT_USERNAME=.*|ROOT_USERNAME=$ROOT_USERNAME|" "$ENV_FILE-$DATE" + fi + if grep -q "^ROOT_USER_EMAIL=" "$ENV_FILE-$DATE"; then + sed -i "s|^ROOT_USER_EMAIL=.*|ROOT_USER_EMAIL=$ROOT_USER_EMAIL|" "$ENV_FILE-$DATE" + fi + if grep -q "^ROOT_USER_PASSWORD=" "$ENV_FILE-$DATE"; then + sed -i "s|^ROOT_USER_PASSWORD=.*|ROOT_USER_PASSWORD=$ROOT_USER_PASSWORD|" "$ENV_FILE-$DATE" + fi +fi + +# Merge .env and .env.production. New values will be added to .env +echo -e "7. Propagating .env with new values - if necessary." +awk -F '=' '!seen[$1]++' "$ENV_FILE-$DATE" /data/coolify/source/.env.production >$ENV_FILE + +if [ "$AUTOUPDATE" = "false" ]; then + if ! grep -q "AUTOUPDATE=" /data/coolify/source/.env; then + echo "AUTOUPDATE=false" >>/data/coolify/source/.env + else + sed -i "s|AUTOUPDATE=.*|AUTOUPDATE=false|g" /data/coolify/source/.env + fi +fi +echo -e "8. Checking for SSH key for localhost access." +if [ ! -f ~/.ssh/authorized_keys ]; then + mkdir -p ~/.ssh + chmod 700 ~/.ssh + touch ~/.ssh/authorized_keys + chmod 600 ~/.ssh/authorized_keys +fi + +set +e +IS_COOLIFY_VOLUME_EXISTS=$(docker volume ls | grep coolify-db | wc -l) +set -e + +if [ "$IS_COOLIFY_VOLUME_EXISTS" -eq 0 ]; then + echo " - Generating SSH key." + ssh-keygen -t ed25519 -a 100 -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal -q -N "" -C coolify + chown 9999 /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal + sed -i "/coolify/d" ~/.ssh/authorized_keys + cat /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub >>~/.ssh/authorized_keys + rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub +fi + +chown -R 9999:root /data/coolify +chmod -R 700 /data/coolify + +echo -e "9. Installing Coolify ($LATEST_VERSION)" +echo -e " - It could take a while based on your server's performance, network speed, stars, etc." +echo -e " - Please wait." +getAJoke + +bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" +echo " - Coolify installed successfully." +rm -f $ENV_FILE-$DATE + +echo " - Waiting for 20 seconds for Coolify (database migrations) to be ready." +getAJoke + +sleep 20 +echo -e "\033[0;35m + ____ _ _ _ _ _ + / ___|___ _ __ __ _ _ __ __ _| |_ _ _| | __ _| |_(_) ___ _ __ ___| | + | | / _ \| '_ \ / _\` | '__/ _\` | __| | | | |/ _\` | __| |/ _ \| '_ \/ __| | + | |__| (_) | | | | (_| | | | (_| | |_| |_| | | (_| | |_| | (_) | | | \__ \_| + \____\___/|_| |_|\__, |_| \__,_|\__|\__,_|_|\__,_|\__|_|\___/|_| |_|___(_) + |___/ +\033[0m" +echo -e "\nYour instance is ready to use!\n" +echo -e "You can access Coolify through your Public IP: http://$(curl -4s https://ifconfig.io):8000" + +set +e +DEFAULT_PRIVATE_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p') +PRIVATE_IPS=$(hostname -I 2>/dev/null || ip -o addr show scope global | awk '{print $4}' | cut -d/ -f1) +set -e + +if [ -n "$PRIVATE_IPS" ]; then + echo -e "\nIf your Public IP is not accessible, you can use the following Private IPs:\n" + for IP in $PRIVATE_IPS; do + if [ "$IP" != "$DEFAULT_PRIVATE_IP" ]; then + echo -e "http://$IP:8000" + fi + done +fi +echo -e "\nWARNING: It is highly recommended to backup your Environment variables file (/data/coolify/source/.env) to a safe location, outside of this server (e.g. into a Password Manager).\n" +cp /data/coolify/source/.env /data/coolify/source/.env.backup diff --git a/scripts/install-1.7.sh b/scripts/install-1.7.sh old mode 100644 new mode 100755 index 4c6eba4d6..282ecc669 --- a/scripts/install-1.7.sh +++ b/scripts/install-1.7.sh @@ -1,6 +1,15 @@ #!/bin/bash ## Do not modify this file. You will lose the ability to install and auto-update! +## Environment variables that can be set: +## ROOT_USERNAME - Predefined root username +## ROOT_USER_EMAIL - Predefined root user email +## ROOT_USER_PASSWORD - Predefined root user password +## DOCKER_ADDRESS_POOL_BASE - Custom Docker address pool base (default: 10.0.0.0/8) +## DOCKER_ADDRESS_POOL_SIZE - Custom Docker address pool size (default: 24) +## DOCKER_POOL_FORCE_OVERRIDE - Force override Docker address pool configuration (default: false) +## AUTOUPDATE - Set to "false" to disable auto-updates + set -e # Exit immediately if a command exits with a non-zero status ## $1 could be empty, so we need to disable this check #set -u # Treat unset variables as an error and exit @@ -27,6 +36,144 @@ ROOT_USERNAME=${ROOT_USERNAME:-} ROOT_USER_EMAIL=${ROOT_USER_EMAIL:-} ROOT_USER_PASSWORD=${ROOT_USER_PASSWORD:-} +# Docker address pool configuration defaults +DOCKER_ADDRESS_POOL_BASE_DEFAULT="10.0.0.0/8" +DOCKER_ADDRESS_POOL_SIZE_DEFAULT=24 + +# Check if environment variables were explicitly provided +DOCKER_POOL_BASE_PROVIDED=false +DOCKER_POOL_SIZE_PROVIDED=false +DOCKER_POOL_FORCE_OVERRIDE=${DOCKER_POOL_FORCE_OVERRIDE:-false} + +if [ -n "${DOCKER_ADDRESS_POOL_BASE+x}" ]; then + DOCKER_POOL_BASE_PROVIDED=true +fi + +if [ -n "${DOCKER_ADDRESS_POOL_SIZE+x}" ]; then + DOCKER_POOL_SIZE_PROVIDED=true +fi + +restart_docker_service() { + # Check if systemctl is available + if command -v systemctl >/dev/null 2>&1; then + systemctl restart docker + if [ $? -eq 0 ]; then + echo " - Docker daemon restarted successfully" + else + echo " - Failed to restart Docker daemon" + return 1 + fi + # Check if service command is available + elif command -v service >/dev/null 2>&1; then + service docker restart + if [ $? -eq 0 ]; then + echo " - Docker daemon restarted successfully" + else + echo " - Failed to restart Docker daemon" + return 1 + fi + # If neither systemctl nor service is available + else + echo " - Error: No service management system found" + return 1 + fi +} + +# Function to compare address pools +compare_address_pools() { + local base1="$1" + local size1="$2" + local base2="$3" + local size2="$4" + + # Normalize CIDR notation for comparison + local ip1=$(echo "$base1" | cut -d'/' -f1) + local prefix1=$(echo "$base1" | cut -d'/' -f2) + local ip2=$(echo "$base2" | cut -d'/' -f1) + local prefix2=$(echo "$base2" | cut -d'/' -f2) + + # Compare IPs and prefixes + if [ "$ip1" = "$ip2" ] && [ "$prefix1" = "$prefix2" ] && [ "$size1" = "$size2" ]; then + return 0 # Pools are the same + else + return 1 # Pools are different + fi +} + +# Docker address pool configuration +DOCKER_ADDRESS_POOL_BASE=${DOCKER_ADDRESS_POOL_BASE:-"$DOCKER_ADDRESS_POOL_BASE_DEFAULT"} +DOCKER_ADDRESS_POOL_SIZE=${DOCKER_ADDRESS_POOL_SIZE:-$DOCKER_ADDRESS_POOL_SIZE_DEFAULT} + +# Load Docker address pool configuration from .env file if it exists and environment variables were not provided +if [ -f "/data/coolify/source/.env" ] && [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then + ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2) + ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2) + + if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ]; then + DOCKER_ADDRESS_POOL_BASE="$ENV_DOCKER_ADDRESS_POOL_BASE" + fi + + if [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then + DOCKER_ADDRESS_POOL_SIZE="$ENV_DOCKER_ADDRESS_POOL_SIZE" + fi +fi + +# Check if daemon.json exists and extract existing address pool configuration +EXISTING_POOL_CONFIGURED=false +if [ -f /etc/docker/daemon.json ]; then + if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then + EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) + EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) + + if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then + echo "Found existing Docker network pool: $EXISTING_POOL_BASE/$EXISTING_POOL_SIZE" + EXISTING_POOL_CONFIGURED=true + + # Check if environment variables were explicitly provided + if [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then + DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" + DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" + else + # Check if force override is enabled + if [ "$DOCKER_POOL_FORCE_OVERRIDE" = true ]; then + echo "Force override enabled - network pool will be updated with $DOCKER_ADDRESS_POOL_BASE/$DOCKER_ADDRESS_POOL_SIZE." + else + echo "Custom pool provided but force override not enabled - using existing configuration." + echo "To force override, set DOCKER_POOL_FORCE_OVERRIDE=true" + echo "This won't change the existing docker networks, only the pool configuration for the newly created networks." + DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" + DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" + DOCKER_POOL_BASE_PROVIDED=false + DOCKER_POOL_SIZE_PROVIDED=false + fi + fi + fi + fi +fi + +# Validate Docker address pool configuration +if ! [[ $DOCKER_ADDRESS_POOL_BASE =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]]; then + echo "Warning: Invalid network pool base format: $DOCKER_ADDRESS_POOL_BASE" + if [ "$EXISTING_POOL_CONFIGURED" = true ]; then + echo "Using existing configuration: $EXISTING_POOL_BASE" + DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" + else + echo "Using default configuration: $DOCKER_ADDRESS_POOL_BASE_DEFAULT" + DOCKER_ADDRESS_POOL_BASE="$DOCKER_ADDRESS_POOL_BASE_DEFAULT" + fi +fi + +if ! [[ $DOCKER_ADDRESS_POOL_SIZE =~ ^[0-9]+$ ]] || [ "$DOCKER_ADDRESS_POOL_SIZE" -lt 16 ] || [ "$DOCKER_ADDRESS_POOL_SIZE" -gt 28 ]; then + echo "Warning: Invalid network pool size: $DOCKER_ADDRESS_POOL_SIZE (must be 16-28)" + if [ "$EXISTING_POOL_CONFIGURED" = true ]; then + echo "Using existing configuration: $EXISTING_POOL_SIZE" + DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" + else + echo "Using default configuration: $DOCKER_ADDRESS_POOL_SIZE_DEFAULT" + DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE_DEFAULT + fi +fi + TOTAL_SPACE=$(df -BG / | awk 'NR==2 {print $2}' | sed 's/G//') AVAILABLE_SPACE=$(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//') REQUIRED_TOTAL_SPACE=30 @@ -35,7 +182,7 @@ WARNING_SPACE=false if [ "$TOTAL_SPACE" -lt "$REQUIRED_TOTAL_SPACE" ]; then WARNING_SPACE=true - cat << EOF + cat </dev/null 2>&1 - dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + "almalinux") + dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo >/dev/null 2>&1 + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + ;; + "alpine") + apk add docker docker-cli-compose >/dev/null 2>&1 + rc-update add docker default >/dev/null 2>&1 + service docker start >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with apk. Try to install it manually." + echo " Please visit https://wiki.alpinelinux.org/wiki/Docker for more information." + exit 1 + fi + ;; + "arch") + pacman -Sy docker docker-compose --noconfirm >/dev/null 2>&1 + systemctl enable docker.service >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with pacman. Try to install it manually." + echo " Please visit https://wiki.archlinux.org/title/docker for more information." + exit 1 + fi + ;; + "amzn") + dnf install docker -y >/dev/null 2>&1 + DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} + mkdir -p $DOCKER_CONFIG/cli-plugins >/dev/null 2>&1 + curl -sL https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 + chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Failed to install Docker with dnf. Try to install it manually." + echo " Please visit https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/ for more information." + exit 1 + fi + ;; + "centos" | "fedora" | "rhel") + if [ -x "$(command -v dnf5)" ]; then + # dnf5 is available + dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo --overwrite >/dev/null 2>&1 + else + # dnf5 is not available, use dnf + dnf config-manager --add-repo=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo >/dev/null 2>&1 + fi + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 + if ! [ -x "$(command -v docker)" ]; then + echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker >/dev/null 2>&1 + systemctl enable docker >/dev/null 2>&1 + ;; + *) + if [ "$OS_TYPE" = "ubuntu" ] && [ "$OS_VERSION" = "24.10" ]; then + echo "Docker automated installation is not supported on Ubuntu 24.10 (non-LTS release)." + echo "Please install Docker manually." + exit 1 + fi + curl -s https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh 2>&1 + if ! [ -x "$(command -v docker)" ]; then + curl -s https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} 2>&1 if ! [ -x "$(command -v docker)" ]; then - echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + echo " - Docker installation failed." + echo " Maybe your OS is not supported?" + echo " - Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." exit 1 fi - systemctl start docker >/dev/null 2>&1 - systemctl enable docker >/dev/null 2>&1 - ;; - "alpine") - apk add docker docker-cli-compose >/dev/null 2>&1 - rc-update add docker default >/dev/null 2>&1 - service docker start >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Failed to install Docker with apk. Try to install it manually." - echo " Please visit https://wiki.alpinelinux.org/wiki/Docker for more information." - exit 1 - fi - ;; - "arch") - pacman -Sy docker docker-compose --noconfirm >/dev/null 2>&1 - systemctl enable docker.service >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Failed to install Docker with pacman. Try to install it manually." - echo " Please visit https://wiki.archlinux.org/title/docker for more information." - exit 1 - fi - ;; - "amzn") - dnf install docker -y >/dev/null 2>&1 - DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} - mkdir -p $DOCKER_CONFIG/cli-plugins >/dev/null 2>&1 - curl -sL https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 - chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 - systemctl start docker >/dev/null 2>&1 - systemctl enable docker >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Failed to install Docker with dnf. Try to install it manually." - echo " Please visit https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/ for more information." - exit 1 - fi - ;; - "fedora") - if [ -x "$(command -v dnf5)" ]; then - # dnf5 is available - dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/fedora/docker-ce.repo --overwrite >/dev/null 2>&1 - else - # dnf5 is not available, use dnf - dnf config-manager --add-repo=https://download.docker.com/linux/fedora/docker-ce.repo >/dev/null 2>&1 - fi - dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." - exit 1 - fi - systemctl start docker >/dev/null 2>&1 - systemctl enable docker >/dev/null 2>&1 - ;; - *) - if [ "$OS_TYPE" = "ubuntu" ] && [ "$OS_VERSION" = "24.10" ]; then - echo "Docker automated installation is not supported on Ubuntu 24.10 (non-LTS release)." - echo "Please install Docker manually." - exit 1 - fi - curl -s https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh 2>&1 - if ! [ -x "$(command -v docker)" ]; then - curl -s https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} 2>&1 - if ! [ -x "$(command -v docker)" ]; then - echo " - Docker installation failed." - echo " Maybe your OS is not supported?" - echo " - Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." - exit 1 - fi - fi + fi + ;; esac echo " - Docker installed successfully." else @@ -375,82 +519,132 @@ else fi echo -e "4. Check Docker Configuration. " + +echo " - Network pool configuration: ${DOCKER_ADDRESS_POOL_BASE}/${DOCKER_ADDRESS_POOL_SIZE}" +echo " - To override existing configuration: DOCKER_POOL_FORCE_OVERRIDE=true" + mkdir -p /etc/docker -# shellcheck disable=SC2015 -test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json /etc/docker/daemon.json.original-"$DATE" || cat >/etc/docker/daemon.json </etc/docker/daemon.json.coolify <"$TEMP_FILE"; then - echo "Error merging JSON files" - exit 1 + +# Backup original daemon.json if it exists +if [ -f /etc/docker/daemon.json ]; then + cp /etc/docker/daemon.json /etc/docker/daemon.json.original-"$DATE" fi -mv "$TEMP_FILE" /etc/docker/daemon.json -restart_docker_service() { - # Check if systemctl is available - if command -v systemctl >/dev/null 2>&1; then - echo " - Using systemctl to restart Docker." - systemctl restart docker +# Create coolify configuration with or without address pools based on whether they were explicitly provided +if [ "$DOCKER_POOL_FORCE_OVERRIDE" = true ] || [ "$EXISTING_POOL_CONFIGURED" = false ]; then + # First check if the configuration would actually change anything + if [ -f /etc/docker/daemon.json ]; then + CURRENT_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) + CURRENT_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) - if [ $? -eq 0 ]; then - echo " - Docker restarted successfully using systemctl." + if [ "$CURRENT_POOL_BASE" = "$DOCKER_ADDRESS_POOL_BASE" ] && [ "$CURRENT_POOL_SIZE" = "$DOCKER_ADDRESS_POOL_SIZE" ]; then + echo " - Network pool configuration unchanged, skipping update" + NEED_MERGE=false else - echo " - Failed to restart Docker using systemctl." - return 1 - fi - - # Check if service command is available - elif command -v service >/dev/null 2>&1; then - echo " - Using service command to restart Docker." - service docker restart - - if [ $? -eq 0 ]; then - echo " - Docker restarted successfully using service." - else - echo " - Failed to restart Docker using service." - return 1 - fi - - # If neither systemctl nor service is available - else - echo " - Neither systemctl nor service command is available on this system." - return 1 - fi + # If force override is enabled or no existing configuration exists, + # create a new configuration with the specified address pools + echo " - Creating new Docker configuration with network pool: ${DOCKER_ADDRESS_POOL_BASE}/${DOCKER_ADDRESS_POOL_SIZE}" + cat >/etc/docker/daemon.json </etc/docker/daemon.json </dev/null 2>&1; then + echo " - Log configuration is up to date" + NEED_MERGE=false + else + # Create a configuration without address pools to preserve existing ones + cat >/etc/docker/daemon.json.coolify </etc/docker/daemon.json < $ENV_FILE +awk -F '=' '!seen[$1]++' "$ENV_FILE-$DATE" /data/coolify/source/.env.production >$ENV_FILE if [ "$AUTOUPDATE" = "false" ]; then if ! grep -q "AUTOUPDATE=" /data/coolify/source/.env; then @@ -510,6 +704,26 @@ if [ "$AUTOUPDATE" = "false" ]; then sed -i "s|AUTOUPDATE=.*|AUTOUPDATE=false|g" /data/coolify/source/.env fi fi + +# Save Docker address pool configuration to .env file +if ! grep -q "DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env; then + echo "DOCKER_ADDRESS_POOL_BASE=$DOCKER_ADDRESS_POOL_BASE" >>/data/coolify/source/.env +else + # Only update if explicitly provided + if [ "$DOCKER_POOL_BASE_PROVIDED" = true ]; then + sed -i "s|DOCKER_ADDRESS_POOL_BASE=.*|DOCKER_ADDRESS_POOL_BASE=$DOCKER_ADDRESS_POOL_BASE|g" /data/coolify/source/.env + fi +fi + +if ! grep -q "DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env; then + echo "DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE" >>/data/coolify/source/.env +else + # Only update if explicitly provided + if [ "$DOCKER_POOL_SIZE_PROVIDED" = true ]; then + sed -i "s|DOCKER_ADDRESS_POOL_SIZE=.*|DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE|g" /data/coolify/source/.env + fi +fi + echo -e "8. Checking for SSH key for localhost access." if [ ! -f ~/.ssh/authorized_keys ]; then mkdir -p ~/.ssh @@ -527,7 +741,7 @@ if [ "$IS_COOLIFY_VOLUME_EXISTS" -eq 0 ]; then ssh-keygen -t ed25519 -a 100 -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal -q -N "" -C coolify chown 9999 /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal sed -i "/coolify/d" ~/.ssh/authorized_keys - cat /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub >> ~/.ssh/authorized_keys + cat /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub >>~/.ssh/authorized_keys rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub fi @@ -572,4 +786,4 @@ if [ -n "$PRIVATE_IPS" ]; then done fi echo -e "\nWARNING: It is highly recommended to backup your Environment variables file (/data/coolify/source/.env) to a safe location, outside of this server (e.g. into a Password Manager).\n" -cp /data/coolify/source/.env /data/coolify/source/.env.backup \ No newline at end of file +cp /data/coolify/source/.env /data/coolify/source/.env.backup From 595370df926b722769b453003b54602e1cbb5f22 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 14 Mar 2025 14:55:38 +0100 Subject: [PATCH 92/99] feat(LocalFileVolume): add binary file detection and update UI logic Implemented a new attribute to detect binary files in the LocalFileVolume model, enhancing the file handling capabilities. The isBinary method checks for binary content based on specific criteria, allowing for better management of file types. Additionally, updated the file storage UI to conditionally display conversion options based on the binary status of the file, improving user experience and preventing unintended actions on binary files. These changes contribute to a more robust and user-friendly file management system. --- app/Models/LocalFileVolume.php | 16 ++++++++++++++++ .../project/service/file-storage.blade.php | 19 +++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/app/Models/LocalFileVolume.php b/app/Models/LocalFileVolume.php index 2c223be77..d96f7125e 100644 --- a/app/Models/LocalFileVolume.php +++ b/app/Models/LocalFileVolume.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Events\FileStorageChanged; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; class LocalFileVolume extends BaseModel @@ -11,6 +12,8 @@ class LocalFileVolume extends BaseModel protected $guarded = []; + public $appends = ['is_binary']; + protected static function booted() { static::created(function (LocalFileVolume $fileVolume) { @@ -19,6 +22,15 @@ class LocalFileVolume extends BaseModel }); } + protected function isBinary(): Attribute + { + return Attribute::make( + get: function () { + return $this->content === '[binary file]'; + } + ); + } + public function service() { return $this->morphTo('resource'); @@ -44,6 +56,10 @@ class LocalFileVolume extends BaseModel $isFile = instant_remote_process(["test -f $path && echo OK || echo NOK"], $server); if ($isFile === 'OK') { $content = instant_remote_process(["cat $path"], $server, false); + // Check if content contains binary data by looking for null bytes or non-printable characters + if (str_contains($content, "\0") || preg_match('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', $content)) { + $content = '[binary file]'; + } $this->content = $content; $this->is_directory = false; $this->save(); diff --git a/resources/views/livewire/project/service/file-storage.blade.php b/resources/views/livewire/project/service/file-storage.blade.php index 550b43c20..e17835429 100644 --- a/resources/views/livewire/project/service/file-storage.blade.php +++ b/resources/views/livewire/project/service/file-storage.blade.php @@ -28,12 +28,15 @@ confirmationLabel="Please confirm the execution of the actions by entering the Filepath below" shortConfirmationLabel="Filepath" step3ButtonText="Permanently Delete" /> @else - + @if (!$fileStorage->is_binary) + + @endif - @if (!$fileStorage->is_based_on_git) + readonly="{{ $fileStorage->is_based_on_git || $fileStorage->is_binary }}"> + @if (!$fileStorage->is_based_on_git && !$fileStorage->is_binary) Save @endif @endif From b6cb32c0375a62ebdde318ab53889847a071d284 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 14 Mar 2025 15:23:17 +0100 Subject: [PATCH 93/99] fix(install): handle potential errors in Docker address pool configuration --- other/nightly/install.sh | 8 ++++---- scripts/install.sh | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/other/nightly/install.sh b/other/nightly/install.sh index 72780e045..944012f86 100755 --- a/other/nightly/install.sh +++ b/other/nightly/install.sh @@ -106,8 +106,8 @@ DOCKER_ADDRESS_POOL_SIZE=${DOCKER_ADDRESS_POOL_SIZE:-$DOCKER_ADDRESS_POOL_SIZE_D # Load Docker address pool configuration from .env file if it exists and environment variables were not provided if [ -f "/data/coolify/source/.env" ] && [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then - ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2) - ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2) + ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2 || true) + ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2 || true) if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ]; then DOCKER_ADDRESS_POOL_BASE="$ENV_DOCKER_ADDRESS_POOL_BASE" @@ -122,8 +122,8 @@ fi EXISTING_POOL_CONFIGURED=false if [ -f /etc/docker/daemon.json ]; then if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then - EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) - EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) + EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null || true) + EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null || true) if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then echo "Found existing Docker network pool: $EXISTING_POOL_BASE/$EXISTING_POOL_SIZE" diff --git a/scripts/install.sh b/scripts/install.sh index a19236974..ba5d4ea14 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -106,8 +106,8 @@ DOCKER_ADDRESS_POOL_SIZE=${DOCKER_ADDRESS_POOL_SIZE:-$DOCKER_ADDRESS_POOL_SIZE_D # Load Docker address pool configuration from .env file if it exists and environment variables were not provided if [ -f "/data/coolify/source/.env" ] && [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then - ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2) - ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2) + ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2 || true) + ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2 || true) if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ]; then DOCKER_ADDRESS_POOL_BASE="$ENV_DOCKER_ADDRESS_POOL_BASE" @@ -122,8 +122,8 @@ fi EXISTING_POOL_CONFIGURED=false if [ -f /etc/docker/daemon.json ]; then if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then - EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) - EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) + EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null || true) + EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null || true) if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then echo "Found existing Docker network pool: $EXISTING_POOL_BASE/$EXISTING_POOL_SIZE" From ee93ccd8e7446a6e4d8f531821313bcd5de285e2 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Fri, 14 Mar 2025 15:28:12 +0100 Subject: [PATCH 94/99] fix(backups): retention settings - If you set a low local backup retention, for example 2 backups for local backup retention and 10 backups for S3, then the S3 backups were never deleted, not even after 10 days. This was because we check the file paths based on the backup executions table, and as soon as a backup was deleted locally, the execution was removed, which meant after 10 days for s3 there where no backups older then 10 days just the 2 local backups which is just wrong. Now we only delete a backup execution if it has been removed from both locations. - Also added a nice little UI element to see where your backup is available. --- bootstrap/helpers/databases.php | 28 +++++++++--- ...deletion_tracking_to_backup_executions.php | 19 ++++++++ .../database/backup-executions.blade.php | 43 +++++++++++++++++++ 3 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 database/migrations/2025_03_14_140150_add_storage_deletion_tracking_to_backup_executions.php diff --git a/bootstrap/helpers/databases.php b/bootstrap/helpers/databases.php index f2c069ac4..2fd85337d 100644 --- a/bootstrap/helpers/databases.php +++ b/bootstrap/helpers/databases.php @@ -233,15 +233,29 @@ function deleteEmptyBackupFolder($folderPath, Server $server): void function removeOldBackups($backup): void { try { - $processedBackups = deleteOldBackupsLocally($backup); - - if ($backup->save_s3) { - $processedBackups = $processedBackups->merge(deleteOldBackupsFromS3($backup)); + if ($backup->executions) { + $localBackupsToDelete = deleteOldBackupsLocally($backup); + if ($localBackupsToDelete->isNotEmpty()) { + $backup->executions() + ->whereIn('id', $localBackupsToDelete->pluck('id')) + ->update(['local_storage_deleted' => true]); + } } - if ($processedBackups->isNotEmpty()) { - $backup->executions()->whereIn('id', $processedBackups->pluck('id'))->delete(); + if ($backup->save_s3 && $backup->executions) { + $s3BackupsToDelete = deleteOldBackupsFromS3($backup); + if ($s3BackupsToDelete->isNotEmpty()) { + $backup->executions() + ->whereIn('id', $s3BackupsToDelete->pluck('id')) + ->update(['s3_storage_deleted' => true]); + } } + + $backup->executions() + ->where('local_storage_deleted', true) + ->where('s3_storage_deleted', true) + ->delete(); + } catch (\Exception $e) { throw $e; } @@ -255,6 +269,7 @@ function deleteOldBackupsLocally($backup): Collection $successfulBackups = $backup->executions() ->where('status', 'success') + ->where('local_storage_deleted', false) ->orderBy('created_at', 'desc') ->get(); @@ -338,6 +353,7 @@ function deleteOldBackupsFromS3($backup): Collection $successfulBackups = $backup->executions() ->where('status', 'success') + ->where('s3_storage_deleted', false) ->orderBy('created_at', 'desc') ->get(); diff --git a/database/migrations/2025_03_14_140150_add_storage_deletion_tracking_to_backup_executions.php b/database/migrations/2025_03_14_140150_add_storage_deletion_tracking_to_backup_executions.php new file mode 100644 index 000000000..c6af6fc49 --- /dev/null +++ b/database/migrations/2025_03_14_140150_add_storage_deletion_tracking_to_backup_executions.php @@ -0,0 +1,19 @@ +boolean('local_storage_deleted')->default(false); + $table->boolean('s3_storage_deleted')->default(false); + }); + } +}; diff --git a/resources/views/livewire/project/database/backup-executions.blade.php b/resources/views/livewire/project/database/backup-executions.blade.php index d13f88e37..6420eb040 100644 --- a/resources/views/livewire/project/database/backup-executions.blade.php +++ b/resources/views/livewire/project/database/backup-executions.blade.php @@ -54,6 +54,49 @@
Location: {{ data_get($execution, 'filename', 'N/A') }}
+
+
+ Backup Availability: +
+ !data_get($execution, 'local_storage_deleted', false), + 'bg-gray-100 text-gray-600 dark:bg-gray-800/50 dark:text-gray-400' => data_get($execution, 'local_storage_deleted', false), + ])> + + @if(!data_get($execution, 'local_storage_deleted', false)) + + + + @else + + + + @endif + Local Storage + + + @if($backup->save_s3) + !data_get($execution, 's3_storage_deleted', false), + 'bg-gray-100 text-gray-600 dark:bg-gray-800/50 dark:text-gray-400' => data_get($execution, 's3_storage_deleted', false), + ])> + + @if(!data_get($execution, 's3_storage_deleted', false)) + + + + @else + + + + @endif + S3 Storage + + + @endif +
@if (data_get($execution, 'message'))
{{ data_get($execution, 'message') }}
From 282bb5c4cdcc1cf4080ea6c013040d955a4bcbd5 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 14 Mar 2025 16:11:31 +0100 Subject: [PATCH 95/99] fix(redis): set default redis_username for new instances Added functionality to automatically assign a default 'redis_username' of 'default' when a StandaloneRedis instance is retrieved without an existing username. This ensures that all instances have a valid username, improving consistency and reducing potential errors in subsequent operations. Additionally, updated the redisUsername method to create a runtime environment variable for 'REDIS_USERNAME' with a default value if it does not already exist, enhancing the robustness of the configuration management. --- app/Models/StandaloneRedis.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/app/Models/StandaloneRedis.php b/app/Models/StandaloneRedis.php index ed5cf9870..6037364fe 100644 --- a/app/Models/StandaloneRedis.php +++ b/app/Models/StandaloneRedis.php @@ -38,6 +38,12 @@ class StandaloneRedis extends BaseModel $database->forceFill(['last_online_at' => now()]); } }); + + static::retrieved(function ($database) { + if (! $database->redis_username) { + $database->redis_username = 'default'; + } + }); } protected function serverStatus(): Attribute @@ -193,8 +199,8 @@ class StandaloneRedis extends BaseModel { return Attribute::make( get: fn () => is_null($this->ports_mappings) - ? [] - : explode(',', $this->ports_mappings), + ? [] + : explode(',', $this->ports_mappings), ); } @@ -346,7 +352,12 @@ class StandaloneRedis extends BaseModel get: function () { $username = $this->runtime_environment_variables()->where('key', 'REDIS_USERNAME')->first(); if (! $username) { - return null; + $this->runtime_environment_variables()->create([ + 'key' => 'REDIS_USERNAME', + 'value' => 'default', + ]); + + return 'default'; } return $username->value; From 798aab69559e3373fdf5170a642895ed3bdf4c42 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 14 Mar 2025 16:11:41 +0100 Subject: [PATCH 96/99] refactor(ScheduledTask): clean up code formatting and remove unused import --- app/Livewire/Project/Shared/ScheduledTask/Add.php | 2 +- app/Livewire/Project/Shared/ScheduledTask/All.php | 2 -- app/Notifications/Channels/EmailChannel.php | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/Livewire/Project/Shared/ScheduledTask/Add.php b/app/Livewire/Project/Shared/ScheduledTask/Add.php index 8ab5f9f27..c286fee5a 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/Add.php +++ b/app/Livewire/Project/Shared/ScheduledTask/Add.php @@ -75,7 +75,7 @@ class Add extends Component public function saveScheduledTask() { try { - $task = new ScheduledTask(); + $task = new ScheduledTask; $task->name = $this->name; $task->command = $this->command; $task->frequency = $this->frequency; diff --git a/app/Livewire/Project/Shared/ScheduledTask/All.php b/app/Livewire/Project/Shared/ScheduledTask/All.php index 1782f3f27..b58e4f97a 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/All.php +++ b/app/Livewire/Project/Shared/ScheduledTask/All.php @@ -2,7 +2,6 @@ namespace App\Livewire\Project\Shared\ScheduledTask; -use App\Models\ScheduledTask; use Illuminate\Support\Collection; use Livewire\Attributes\Locked; use Livewire\Attributes\On; @@ -42,5 +41,4 @@ class All extends Component { $this->resource->refresh(); } - } diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php index b8589cd8e..215fae4ea 100644 --- a/app/Notifications/Channels/EmailChannel.php +++ b/app/Notifications/Channels/EmailChannel.php @@ -53,6 +53,7 @@ class EmailChannel if (blank($type)) { throw new Exception('No email settings found.'); } + return; } From 8a11de9b1a8b7cbfdd9ec60cbd419c1cb22ca88c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 15 Mar 2025 22:26:59 +0100 Subject: [PATCH 97/99] fix(core): improve instantSave logic and error handling --- app/Livewire/SettingsEmail.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/app/Livewire/SettingsEmail.php b/app/Livewire/SettingsEmail.php index 15e68306f..4205594a5 100644 --- a/app/Livewire/SettingsEmail.php +++ b/app/Livewire/SettingsEmail.php @@ -114,19 +114,24 @@ class SettingsEmail extends Component public function instantSave(string $type) { try { + $currentSmtpEnabled = $this->settings->smtp_enabled; + $currentResendEnabled = $this->settings->resend_enabled; $this->resetErrorBag(); if ($type === 'SMTP') { $this->submitSmtp(); + $this->resendEnabled = $this->settings->resend_enabled = false; } elseif ($type === 'Resend') { $this->submitResend(); + $this->smtpEnabled = $this->settings->smtp_enabled = false; } + $this->settings->save(); } catch (\Throwable $e) { if ($type === 'SMTP') { - $this->smtpEnabled = false; + $this->smtpEnabled = $currentSmtpEnabled; } elseif ($type === 'Resend') { - $this->resendEnabled = false; + $this->resendEnabled = $currentResendEnabled; } return handleError($e, $this); @@ -156,9 +161,6 @@ class SettingsEmail extends Component 'smtpEncryption.required' => 'Encryption type is required.', ]); - $this->resendEnabled = false; - $this->settings->resend_enabled = false; - $this->settings->smtp_enabled = $this->smtpEnabled; $this->settings->smtp_host = $this->smtpHost; $this->settings->smtp_port = $this->smtpPort; @@ -194,9 +196,6 @@ class SettingsEmail extends Component 'smtpFromName.required' => 'From Name is required.', ]); - $this->smtpEnabled = false; - $this->settings->smtp_enabled = false; - $this->settings->resend_enabled = $this->resendEnabled; $this->settings->resend_api_key = $this->resendApiKey; $this->settings->smtp_from_address = $this->smtpFromAddress; From f77ee1f4ba31d15d9a9875c2f4578e1ebe06bed8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Mon, 17 Mar 2025 11:15:49 +0100 Subject: [PATCH 98/99] fix(general): correct link to framework specific documentation --- resources/views/livewire/project/application/general.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index da806f916..280af2256 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -185,7 +185,7 @@
Nixpacks will detect the required configuration automatically. - Framework + Framework Specific Docs
@endif From b8f99bbda0d3d222c8402e5f15a43865c76535bf Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Mon, 17 Mar 2025 11:28:43 +0100 Subject: [PATCH 99/99] fix(core): redirect healthcheck route for dockercompose applications --- .../Project/Application/Configuration.php | 4 ++++ .../project/application/configuration.blade.php | 16 ++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/app/Livewire/Project/Application/Configuration.php b/app/Livewire/Project/Application/Configuration.php index 56e0caf75..267ca72ad 100644 --- a/app/Livewire/Project/Application/Configuration.php +++ b/app/Livewire/Project/Application/Configuration.php @@ -22,6 +22,7 @@ class Configuration extends Component public function mount() { $this->currentRoute = request()->route()->getName(); + $project = currentTeam() ->projects() ->select('id', 'uuid', 'team_id') @@ -39,6 +40,9 @@ class Configuration extends Component $this->project = $project; $this->environment = $environment; $this->application = $application; + 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]); + } } public function render() diff --git a/resources/views/livewire/project/application/configuration.blade.php b/resources/views/livewire/project/application/configuration.blade.php index 7fcbbd691..3d56a7e8d 100644 --- a/resources/views/livewire/project/application/configuration.blade.php +++ b/resources/views/livewire/project/application/configuration.blade.php @@ -15,8 +15,7 @@ href="{{ route('project.application.advanced', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]) }}" wire:navigate>Advanced @if ($application->destination->server->isSwarm()) - Swarm Configuration @endif @@ -60,21 +59,22 @@ Preview Deployments - Healthcheck + @if ($application->build_pack !== 'dockercompose') + Healthcheck + @endif Rollback Resource Limits - Resource Operations Metrics + href="{{ route('project.application.metrics', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]) }}">Metrics Tags @@ -103,7 +103,7 @@ @elseif ($currentRoute === 'project.application.preview-deployments') - @elseif ($currentRoute === 'project.application.healthcheck') + @elseif ($currentRoute === 'project.application.healthcheck' && $application->build_pack !== 'dockercompose') @elseif ($currentRoute === 'project.application.rollback')