Add ticket pull request visibility

This commit is contained in:
2026-03-26 09:19:56 +01:00
parent 0b95477f4e
commit 789675f83f
11 changed files with 495 additions and 3 deletions
@@ -0,0 +1,161 @@
<?php
namespace App\Actions\Git;
use App\Actions\Git\Data\GitPullRequest;
use App\Models\Project;
use App\Models\RepositoryConnection;
use App\Models\Ticket;
use App\Models\User;
use App\Models\UserGitConnection;
use Illuminate\Support\Collection;
use Throwable;
class ResolveTicketPullRequestMatches
{
public function __construct(
private readonly GitProviderManager $gitProviderManager,
private readonly TicketKeyReferenceMatcher $ticketKeyReferenceMatcher,
) {}
/**
* @return array<int, array{
* error: string|null,
* pull_requests: array<int, array{
* html_url: string,
* number: string,
* source_branch: string,
* status: string,
* title: string
* }>,
* repository_connection: array{
* base_url: string,
* created_at: string|null,
* has_personal_access: bool,
* id: int,
* owner_name: string,
* project_id: int,
* provider: string,
* provider_label: string,
* provider_repository_id: string,
* repository_full_name: string,
* repository_name: string,
* repository_url: string,
* updated_at: string|null
* }
* }>
*/
public function handle(User $user, Project $project, Ticket $ticket): array
{
/** @var Collection<int, RepositoryConnection> $repositoryConnections */
$repositoryConnections = $project->repositoryConnections()
->get();
return $repositoryConnections
->map(function (RepositoryConnection $repositoryConnection) use ($ticket, $user): array {
$userGitConnection = $this->matchingUserGitConnection($user, $repositoryConnection);
$hasPersonalAccess = $userGitConnection !== null;
if ($userGitConnection === null) {
return [
'error' => null,
'pull_requests' => [],
'repository_connection' => $this->repositoryConnectionPayload(
$repositoryConnection,
false,
),
];
}
try {
$pullRequests = collect(
$this->gitProviderManager
->client($userGitConnection->provider)
->listPullRequests(
$userGitConnection->base_url,
$userGitConnection->api_token,
$repositoryConnection->owner_name,
$repositoryConnection->repository_name,
),
)
->filter(fn (GitPullRequest $pullRequest): bool => $this->ticketKeyReferenceMatcher->matches(
$ticket->ticket_key,
$pullRequest->sourceBranch,
))
->map(fn (GitPullRequest $pullRequest): array => [
'html_url' => $pullRequest->htmlUrl,
'number' => $pullRequest->number,
'source_branch' => $pullRequest->sourceBranch,
'status' => $pullRequest->status,
'title' => $pullRequest->title,
])
->values()
->all();
$error = null;
} catch (Throwable) {
$error = 'KanbanGit could not load pull requests from this repository right now.';
$pullRequests = [];
}
return [
'error' => $error,
'pull_requests' => $pullRequests,
'repository_connection' => $this->repositoryConnectionPayload(
$repositoryConnection,
$hasPersonalAccess,
),
];
})
->values()
->all();
}
/**
* @return array{
* base_url: string,
* created_at: string|null,
* has_personal_access: bool,
* id: int,
* owner_name: string,
* project_id: int,
* provider: string,
* provider_label: string,
* provider_repository_id: string,
* repository_full_name: string,
* repository_name: string,
* repository_url: string,
* updated_at: string|null
* }
*/
private function repositoryConnectionPayload(
RepositoryConnection $repositoryConnection,
bool $hasPersonalAccess,
): array {
return [
'base_url' => $repositoryConnection->base_url,
'created_at' => $repositoryConnection->created_at?->toISOString(),
'has_personal_access' => $hasPersonalAccess,
'id' => $repositoryConnection->id,
'owner_name' => $repositoryConnection->owner_name,
'project_id' => $repositoryConnection->project_id,
'provider' => $repositoryConnection->provider->value,
'provider_label' => $repositoryConnection->provider->label(),
'provider_repository_id' => $repositoryConnection->provider_repository_id,
'repository_full_name' => $repositoryConnection->repository_full_name,
'repository_name' => $repositoryConnection->repository_name,
'repository_url' => $repositoryConnection->repository_url,
'updated_at' => $repositoryConnection->updated_at?->toISOString(),
];
}
private function matchingUserGitConnection(
User $user,
RepositoryConnection $repositoryConnection,
): ?UserGitConnection {
return $user->gitConnections()
->where('provider', $repositoryConnection->provider)
->where('base_url', $repositoryConnection->base_url)
->first();
}
}