diff --git a/app/Http/Middleware/DecideWhatToDoWithUser.php b/app/Http/Middleware/DecideWhatToDoWithUser.php index 441f47175..30780910b 100644 --- a/app/Http/Middleware/DecideWhatToDoWithUser.php +++ b/app/Http/Middleware/DecideWhatToDoWithUser.php @@ -25,14 +25,14 @@ class DecideWhatToDoWithUser if ($request->path() === 'verify' || in_array($request->path(), allowedPathsForInvalidAccounts()) || $request->routeIs('verify.verify')) { return $next($request); } - return redirect()-route('verify.email'); + return redirect()->route('verify.email'); } if (!isSubscriptionActive() && !isSubscriptionOnGracePeriod()) { if (!in_array($request->path(), allowedPathsForUnsubscribedAccounts())) { if (Str::startsWith($request->path(), 'invitations')) { return $next($request); } - return redirect()->route('subscription'); + return redirect()->route('subscription.index'); } } if (showBoarding() && !in_array($request->path(), allowedPathsForBoardingAccounts())) { diff --git a/app/Livewire/Project/EnvironmentEdit.php b/app/Livewire/Project/EnvironmentEdit.php new file mode 100644 index 000000000..a87e2092b --- /dev/null +++ b/app/Livewire/Project/EnvironmentEdit.php @@ -0,0 +1,41 @@ + 'required|min:3|max:255', + 'environment.description' => 'nullable|min:3|max:255', + ]; + public function mount() { + $this->parameters = get_route_parameters(); + + $this->project = Project::ownedByCurrentTeam()->where('uuid', request()->route('project_uuid'))->first(); + $this->environment = $this->project->environments()->where('name', request()->route('environment_name'))->first(); + } + + public function submit() + { + $this->validate(); + try { + $this->environment->save(); + return redirect()->route('project.environment.edit', ['project_uuid' => $this->project->uuid, 'environment_name' => $this->environment->name]); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function render() + { + return view('livewire.project.environment-edit'); + } +} diff --git a/app/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php b/app/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php index aab0df3db..ba403ca1c 100644 --- a/app/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php +++ b/app/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php @@ -55,7 +55,11 @@ class GithubPrivateRepositoryDeployKey extends Component } $this->parameters = get_route_parameters(); $this->query = request()->query(); - $this->private_keys = PrivateKey::where('team_id', currentTeam()->id)->where('id', '!=', 0)->get(); + if (isDev()) { + $this->private_keys = PrivateKey::where('team_id', currentTeam()->id)->get(); + } else { + $this->private_keys = PrivateKey::where('team_id', currentTeam()->id)->where('id', '!=', 0)->get(); + } } public function instantSave() diff --git a/app/Models/Application.php b/app/Models/Application.php index 7247411ef..018d6ec91 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -382,6 +382,9 @@ class Application extends BaseModel public function deploymentType() { + if (isDev() && data_get($this, 'private_key_id') === 0) { + return 'deploy_key'; + } if (data_get($this, 'private_key_id')) { return 'deploy_key'; } else if (data_get($this, 'source')) { @@ -859,9 +862,12 @@ class Application extends BaseModel } $private_key = base64_encode($private_key); $git_clone_command_base = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$customRepository} {$baseDir}"; - if (!$only_checkout) { + if ($only_checkout) { + $git_clone_command = $git_clone_command_base; + } else { $git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base); } + ray($git_clone_command); if ($exec_in_docker) { $commands = collect([ executeInDocker($deployment_uuid, "mkdir -p /root/.ssh"), @@ -979,6 +985,7 @@ class Application extends BaseModel // $fileList->push(".$prComposeFile"); // } $commands = collect([ + "rm -rf /tmp/{$uuid}", "mkdir -p /tmp/{$uuid} && cd /tmp/{$uuid}", $cloneCommand, "git sparse-checkout init --cone", diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 19b3d5b18..21dfe3e3c 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -216,55 +216,60 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ $labels = collect([]); $labels->push('traefik.enable=true'); foreach ($domains as $loop => $domain) { - $uuid = new Cuid2(7); - $url = Url::fromString($domain); - $host = $url->getHost(); - $path = $url->getPath(); - $schema = $url->getScheme(); - $port = $url->getPort(); - if (is_null($port) && !is_null($onlyPort)) { - $port = $onlyPort; + try { + $uuid = new Cuid2(7); + $url = Url::fromString($domain); + $host = $url->getHost(); + $path = $url->getPath(); + $schema = $url->getScheme(); + $port = $url->getPort(); + if (is_null($port) && !is_null($onlyPort)) { + $port = $onlyPort; + } + $http_label = "{$uuid}-{$loop}-http"; + $https_label = "{$uuid}-{$loop}-https"; + + if ($schema === 'https') { + // Set labels for https + $labels->push("traefik.http.routers.{$https_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)"); + $labels->push("traefik.http.routers.{$https_label}.entryPoints=https"); + $labels->push("traefik.http.routers.{$https_label}.middlewares=gzip"); + if ($port) { + $labels->push("traefik.http.routers.{$https_label}.service={$https_label}"); + $labels->push("traefik.http.services.{$https_label}.loadbalancer.server.port=$port"); + } + if ($path !== '/') { + $labels->push("traefik.http.routers.{$https_label}.middlewares={$https_label}-stripprefix"); + $labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}"); + } + + $labels->push("traefik.http.routers.{$https_label}.tls=true"); + $labels->push("traefik.http.routers.{$https_label}.tls.certresolver=letsencrypt"); + + // Set labels for http (redirect to https) + $labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)"); + $labels->push("traefik.http.routers.{$http_label}.entryPoints=http"); + if ($is_force_https_enabled) { + $labels->push("traefik.http.routers.{$http_label}.middlewares=redirect-to-https"); + } + } else { + // Set labels for http + $labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)"); + $labels->push("traefik.http.routers.{$http_label}.entryPoints=http"); + $labels->push("traefik.http.routers.{$http_label}.middlewares=gzip"); + if ($port) { + $labels->push("traefik.http.routers.{$http_label}.service={$http_label}"); + $labels->push("traefik.http.services.{$http_label}.loadbalancer.server.port=$port"); + } + if ($path !== '/') { + $labels->push("traefik.http.routers.{$http_label}.middlewares={$http_label}-stripprefix"); + $labels->push("traefik.http.middlewares.{$http_label}-stripprefix.stripprefix.prefixes={$path}"); + } + } + } catch(\Throwable $e) { + continue; } - $http_label = "{$uuid}-{$loop}-http"; - $https_label = "{$uuid}-{$loop}-https"; - if ($schema === 'https') { - // Set labels for https - $labels->push("traefik.http.routers.{$https_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)"); - $labels->push("traefik.http.routers.{$https_label}.entryPoints=https"); - $labels->push("traefik.http.routers.{$https_label}.middlewares=gzip"); - if ($port) { - $labels->push("traefik.http.routers.{$https_label}.service={$https_label}"); - $labels->push("traefik.http.services.{$https_label}.loadbalancer.server.port=$port"); - } - if ($path !== '/') { - $labels->push("traefik.http.routers.{$https_label}.middlewares={$https_label}-stripprefix"); - $labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}"); - } - - $labels->push("traefik.http.routers.{$https_label}.tls=true"); - $labels->push("traefik.http.routers.{$https_label}.tls.certresolver=letsencrypt"); - - // Set labels for http (redirect to https) - $labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)"); - $labels->push("traefik.http.routers.{$http_label}.entryPoints=http"); - if ($is_force_https_enabled) { - $labels->push("traefik.http.routers.{$http_label}.middlewares=redirect-to-https"); - } - } else { - // Set labels for http - $labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)"); - $labels->push("traefik.http.routers.{$http_label}.entryPoints=http"); - $labels->push("traefik.http.routers.{$http_label}.middlewares=gzip"); - if ($port) { - $labels->push("traefik.http.routers.{$http_label}.service={$http_label}"); - $labels->push("traefik.http.services.{$http_label}.loadbalancer.server.port=$port"); - } - if ($path !== '/') { - $labels->push("traefik.http.routers.{$http_label}.middlewares={$http_label}-stripprefix"); - $labels->push("traefik.http.middlewares.{$http_label}-stripprefix.stripprefix.prefixes={$path}"); - } - } } return $labels; diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index a00727c10..2bb619aa8 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -102,6 +102,7 @@ function refreshSession(?Team $team = null): void } function handleError(?Throwable $error = null, ?Livewire\Component $livewire = null, ?string $customErrorMessage = null) { + ray($error); if ($error instanceof TooManyRequestsException) { if (isset($livewire)) { return $livewire->dispatch('error', "Too many requests. Please try again in {$error->secondsUntilAvailable} seconds."); @@ -227,11 +228,15 @@ function base_ip(): string } function getFqdnWithoutPort(String $fqdn) { - $url = Url::fromString($fqdn); - $host = $url->getHost(); - $scheme = $url->getScheme(); - $path = $url->getPath(); - return "$scheme://$host$path"; + try { + $url = Url::fromString($fqdn); + $host = $url->getHost(); + $scheme = $url->getScheme(); + $path = $url->getPath(); + return "$scheme://$host$path"; + } catch (\Throwable $e) { + return $fqdn; + } } /** * If fqdn is set, return it, otherwise return public ip. @@ -1520,6 +1525,9 @@ function parseEnvVariable(Str|string $value) $command = $value->after('SERVICE_')->before('_'); $forService = $value->after('SERVICE_')->after('_')->before('_'); $port = $value->afterLast('_'); + if (filter_var($port, FILTER_VALIDATE_INT) === false) { + $port = null; + } } else { // SERVICE_BASE64_64_UMAMI $command = $value->after('SERVICE_')->beforeLast('_'); diff --git a/config/sentry.php b/config/sentry.php index ff9cafff0..150fd9d8b 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ return [ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => '4.0.0-beta.174', + 'release' => '4.0.0-beta.175', // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/config/version.php b/config/version.php index 24294cc83..6b0870bf8 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ string('description')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('environments', function (Blueprint $table) { + $table->dropColumn('description'); + }); + } +}; diff --git a/resources/views/livewire/project/environment-edit.blade.php b/resources/views/livewire/project/environment-edit.blade.php new file mode 100644 index 000000000..f88bbdb05 --- /dev/null +++ b/resources/views/livewire/project/environment-edit.blade.php @@ -0,0 +1,44 @@ +
+
+
+

Environment: {{ data_get($environment, 'name') }}

+ Save +
+ +
+ + +
+
+
diff --git a/resources/views/project/resources.blade.php b/resources/views/project/resources.blade.php index 2b93f5377..8e97bf324 100644 --- a/resources/views/project/resources.blade.php +++ b/resources/views/project/resources.blade.php @@ -3,13 +3,13 @@

Resources

@if ($environment->isEmpty()) - Clone @else - + New
@if ($environment->isEmpty()) - + Add New Resource @endif
@foreach ($environment->applications->sortBy('name') as $application) -
{{ $application->name }}
@@ -62,7 +62,7 @@
@endforeach @foreach ($environment->databases()->sortBy('name') as $database) -
{{ $database->name }}
@@ -78,7 +78,7 @@
@endforeach @foreach ($environment->services->sortBy('name') as $service) -
{{ $service->name }}
diff --git a/resources/views/project/show.blade.php b/resources/views/project/show.blade.php index db3abb069..98da15b32 100644 --- a/resources/views/project/show.blade.php +++ b/resources/views/project/show.blade.php @@ -10,12 +10,35 @@
{{ $project->name }}
@forelse ($project->environments as $environment) - - {{ $environment->name }} - + @empty

No environments found.

@endforelse +
diff --git a/routes/web.php b/routes/web.php index e27bca3d2..ffd907344 100644 --- a/routes/web.php +++ b/routes/web.php @@ -13,6 +13,7 @@ use App\Livewire\Project\Service\Show as ServiceShow; use App\Livewire\Dev\Compose as Compose; use App\Livewire\Dashboard; use App\Livewire\Project\CloneProject; +use App\Livewire\Project\EnvironmentEdit; use App\Livewire\Project\Shared\ExecuteContainerCommand; use App\Livewire\Project\Shared\Logs; use App\Livewire\Security\ApiTokens; @@ -113,6 +114,7 @@ Route::middleware(['auth', 'verified'])->group(function () { Route::get('/project/{project_uuid}/{environment_name}/new', [ProjectController::class, 'new'])->name('project.resources.new'); Route::get('/project/{project_uuid}/{environment_name}', [ProjectController::class, 'resources'])->name('project.resources'); + Route::get('/project/{project_uuid}/{environment_name}/edit', EnvironmentEdit::class)->name('project.environment.edit'); // Applications Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}', ApplicationConfiguration::class)->name('project.application.configuration'); diff --git a/versions.json b/versions.json index fe4045b16..388e28aac 100644 --- a/versions.json +++ b/versions.json @@ -4,7 +4,7 @@ "version": "3.12.36" }, "v4": { - "version": "4.0.0-beta.174" + "version": "4.0.0-beta.175" } } }