217 lines
7.2 KiB
PHP
217 lines
7.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Actions\Git\Data\GitBranch;
|
|
use App\Actions\Git\GitProviderManager;
|
|
use App\Actions\Git\ValidateGitBranchName;
|
|
use App\Actions\Permissions\PermissionService;
|
|
use App\Enums\Permission;
|
|
use App\Http\Requests\StoreProjectTicketBranchRequest;
|
|
use App\Http\Requests\ValidateProjectTicketBranchRequest;
|
|
use App\Models\Project;
|
|
use App\Models\RepositoryConnection;
|
|
use App\Models\Ticket;
|
|
use App\Models\UserGitConnection;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Validation\ValidationException;
|
|
use Throwable;
|
|
|
|
class ProjectTicketBranchController extends Controller
|
|
{
|
|
public function __construct(
|
|
private readonly GitProviderManager $gitProviderManager,
|
|
private readonly ValidateGitBranchName $validateGitBranchName,
|
|
private readonly PermissionService $permissionService,
|
|
) {}
|
|
|
|
public function validate(
|
|
ValidateProjectTicketBranchRequest $request,
|
|
Project $project,
|
|
Ticket $ticket,
|
|
): JsonResponse {
|
|
$user = $request->user();
|
|
|
|
abort_unless(
|
|
$this->permissionService->allows($user, Permission::ProjectWrite, $project),
|
|
403,
|
|
);
|
|
|
|
$validated = $request->validated();
|
|
$repositoryConnectionId = Arr::get($validated, 'repository_connection_id');
|
|
$branchName = trim((string) Arr::get($validated, 'branch_name'));
|
|
|
|
$repositoryConnection = $this->projectRepositoryConnection(
|
|
$project,
|
|
$repositoryConnectionId,
|
|
);
|
|
$userGitConnection = $this->matchingUserGitConnection(
|
|
$user->id,
|
|
$repositoryConnection,
|
|
);
|
|
|
|
if ($userGitConnection === null) {
|
|
return response()->json([
|
|
'is_valid' => false,
|
|
'message' => 'Connect a matching Git connection in your user settings first.',
|
|
]);
|
|
}
|
|
|
|
$syntaxMessage = $this->validateGitBranchName->message($branchName);
|
|
|
|
if ($syntaxMessage !== null) {
|
|
return response()->json([
|
|
'is_valid' => false,
|
|
'message' => $syntaxMessage,
|
|
]);
|
|
}
|
|
|
|
try {
|
|
$branchAlreadyExists = collect(
|
|
$this->gitProviderManager
|
|
->client($userGitConnection->provider)
|
|
->listBranches(
|
|
$userGitConnection->base_url,
|
|
$userGitConnection->api_token,
|
|
$repositoryConnection->owner_name,
|
|
$repositoryConnection->repository_name,
|
|
),
|
|
)
|
|
->contains(
|
|
fn (GitBranch $branch): bool => $branch->name === $branchName,
|
|
);
|
|
} catch (Throwable) {
|
|
return response()->json([
|
|
'is_valid' => false,
|
|
'message' => 'KanbanGit could not validate this branch name right now.',
|
|
]);
|
|
}
|
|
|
|
if ($branchAlreadyExists) {
|
|
return response()->json([
|
|
'is_valid' => false,
|
|
'message' => 'This branch name already exists in the selected repository.',
|
|
]);
|
|
}
|
|
|
|
return response()->json([
|
|
'is_valid' => true,
|
|
'message' => "Branch name is available for {$ticket->ticket_key}.",
|
|
]);
|
|
}
|
|
|
|
public function store(
|
|
StoreProjectTicketBranchRequest $request,
|
|
Project $project,
|
|
Ticket $ticket,
|
|
): RedirectResponse {
|
|
|
|
$user = $request->user();
|
|
|
|
abort_unless(
|
|
$this->permissionService->allows($user, Permission::ProjectWrite, $project),
|
|
403,
|
|
);
|
|
|
|
$validated = $request->validated();
|
|
$repositoryConnectionId = Arr::get($validated, 'repository_connection_id');
|
|
$branchName = trim((string) Arr::get($validated, 'branch_name'));
|
|
|
|
$repositoryConnection = $this->projectRepositoryConnection(
|
|
$project,
|
|
$repositoryConnectionId,
|
|
);
|
|
$userGitConnection = $this->matchingUserGitConnection(
|
|
$user->id,
|
|
$repositoryConnection,
|
|
);
|
|
|
|
if ($userGitConnection === null) {
|
|
throw ValidationException::withMessages([
|
|
'repository_connection_id' => 'Connect a matching Git connection in your user settings first.',
|
|
]);
|
|
}
|
|
|
|
$syntaxMessage = $this->validateGitBranchName->message($branchName);
|
|
|
|
if ($syntaxMessage !== null) {
|
|
throw ValidationException::withMessages([
|
|
'branch_name' => $syntaxMessage,
|
|
]);
|
|
}
|
|
|
|
$gitProvider = $this->gitProviderManager->client($userGitConnection->provider);
|
|
|
|
try {
|
|
$branchAlreadyExists = collect(
|
|
$gitProvider->listBranches(
|
|
$userGitConnection->base_url,
|
|
$userGitConnection->api_token,
|
|
$repositoryConnection->owner_name,
|
|
$repositoryConnection->repository_name,
|
|
),
|
|
)
|
|
->contains(
|
|
fn (GitBranch $branch): bool => $branch->name === $branchName,
|
|
);
|
|
} catch (Throwable) {
|
|
throw ValidationException::withMessages([
|
|
'branch_name' => 'KanbanGit could not validate this branch name right now.',
|
|
]);
|
|
}
|
|
|
|
if ($branchAlreadyExists) {
|
|
throw ValidationException::withMessages([
|
|
'branch_name' => 'This branch name already exists in the selected repository.',
|
|
]);
|
|
}
|
|
|
|
try {
|
|
$repository = $gitProvider->getRepository(
|
|
$userGitConnection->base_url,
|
|
$userGitConnection->api_token,
|
|
$repositoryConnection->owner_name,
|
|
$repositoryConnection->repository_name,
|
|
);
|
|
|
|
$gitProvider->createBranch(
|
|
$userGitConnection->base_url,
|
|
$userGitConnection->api_token,
|
|
$repositoryConnection->owner_name,
|
|
$repositoryConnection->repository_name,
|
|
$branchName,
|
|
$repository->defaultBranch,
|
|
);
|
|
} catch (Throwable) {
|
|
throw ValidationException::withMessages([
|
|
'branch_name' => 'KanbanGit could not create this branch right now.',
|
|
]);
|
|
}
|
|
|
|
return to_route('projects.tickets.show', [$project, $ticket])
|
|
->with(
|
|
'status',
|
|
"{$branchName} was created in {$repositoryConnection->repository_full_name}.",
|
|
);
|
|
}
|
|
|
|
private function projectRepositoryConnection(Project $project, int $repositoryConnectionId): RepositoryConnection
|
|
{
|
|
return $project->repositoryConnections()
|
|
->findOrFail($repositoryConnectionId);
|
|
}
|
|
|
|
private function matchingUserGitConnection(
|
|
int $userId,
|
|
RepositoryConnection $repositoryConnection,
|
|
): ?UserGitConnection {
|
|
return UserGitConnection::query()
|
|
->where('user_id', $userId)
|
|
->where('provider', $repositoryConnection->provider)
|
|
->where('base_url', $repositoryConnection->base_url)
|
|
->first();
|
|
}
|
|
}
|