Merge remote-tracking branch 'origin/next' into feat/railpack

This commit is contained in:
Andras Bacsai
2026-04-28 14:36:54 +02:00
153 changed files with 5603 additions and 773 deletions
@@ -2,6 +2,7 @@
namespace App\Http\Controllers\Api;
use App\Actions\Application\CleanupPreviewDeployment;
use App\Actions\Application\LoadComposeFile;
use App\Actions\Application\StopApplication;
use App\Actions\Service\StartService;
@@ -9,6 +10,7 @@ use App\Enums\BuildPackTypes;
use App\Http\Controllers\Controller;
use App\Jobs\DeleteResourceJob;
use App\Models\Application;
use App\Models\ApplicationPreview;
use App\Models\EnvironmentVariable;
use App\Models\GithubApp;
use App\Models\LocalFileVolume;
@@ -1058,7 +1060,7 @@ class ApplicationsController extends Controller
$connectToDockerNetwork = $request->connect_to_docker_network;
$customNginxConfiguration = $request->custom_nginx_configuration;
$isContainerLabelEscapeEnabled = $request->boolean('is_container_label_escape_enabled', true);
$isPreserveRepositoryEnabled = $request->boolean('is_preserve_repository_enabled',false);
$isPreserveRepositoryEnabled = $request->boolean('is_preserve_repository_enabled', false);
if (! is_null($customNginxConfiguration)) {
if (! isBase64Encoded($customNginxConfiguration)) {
@@ -4119,7 +4121,7 @@ class ApplicationsController extends Controller
'is_preview_suffix_enabled' => 'boolean',
'name' => ['string', 'regex:'.ValidationPatterns::VOLUME_NAME_PATTERN],
'mount_path' => 'string',
'host_path' => 'string|nullable',
'host_path' => ['string', 'nullable', 'regex:'.ValidationPatterns::DIRECTORY_PATH_PATTERN],
'content' => 'string|nullable',
]);
@@ -4297,7 +4299,7 @@ class ApplicationsController extends Controller
'type' => 'required|string|in:persistent,file',
'name' => ['string', 'regex:'.ValidationPatterns::VOLUME_NAME_PATTERN],
'mount_path' => 'required|string',
'host_path' => 'string|nullable',
'host_path' => ['string', 'nullable', 'regex:'.ValidationPatterns::DIRECTORY_PATH_PATTERN],
'content' => 'string|nullable',
'is_directory' => 'boolean',
'fs_path' => 'string',
@@ -4474,4 +4476,73 @@ class ApplicationsController extends Controller
return response()->json(['message' => 'Storage deleted.']);
}
#[OA\Delete(
summary: 'Delete Preview Deployment',
description: 'Delete a preview deployment for a pull request. Cancels active deployments, stops containers, removes volumes/networks, and deletes the preview record.',
path: '/applications/{uuid}/previews/{pull_request_id}',
operationId: 'delete-preview-deployment-by-pull-request-id',
security: [
['bearerAuth' => []],
],
tags: ['Applications'],
parameters: [
new OA\Parameter(
name: 'uuid',
in: 'path',
description: 'UUID of the application.',
required: true,
schema: new OA\Schema(type: 'string')
),
new OA\Parameter(
name: 'pull_request_id',
in: 'path',
description: 'Pull request ID of the preview to delete.',
required: true,
schema: new OA\Schema(type: 'integer')
),
],
responses: [
new OA\Response(response: 200, description: 'Preview deletion queued.', content: new OA\JsonContent(
properties: [new OA\Property(property: 'message', type: 'string')],
)),
new OA\Response(response: 401, ref: '#/components/responses/401'),
new OA\Response(response: 400, ref: '#/components/responses/400'),
new OA\Response(response: 404, ref: '#/components/responses/404'),
new OA\Response(response: 422, ref: '#/components/responses/422'),
]
)]
public function delete_preview_by_pull_request_id(Request $request): JsonResponse
{
$teamId = getTeamIdFromToken();
if (is_null($teamId)) {
return invalidTokenResponse();
}
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first();
if (! $application) {
return response()->json(['message' => 'Application not found.'], 404);
}
$this->authorize('delete', $application);
$pullRequestIdRaw = $request->route('pull_request_id');
if (! is_numeric($pullRequestIdRaw) || (int) $pullRequestIdRaw <= 0) {
return response()->json(['message' => 'Invalid pull_request_id.'], 422);
}
$pullRequestId = (int) $pullRequestIdRaw;
$preview = ApplicationPreview::where('application_id', $application->id)
->where('pull_request_id', $pullRequestId)
->first();
if (! $preview) {
return response()->json(['message' => 'Preview not found.'], 404);
}
$preview->delete();
CleanupPreviewDeployment::run($application, $pullRequestId, $preview);
return response()->json(['message' => 'Preview deletion request queued.']);
}
}