Add ticket pull request visibility
This commit is contained in:
@@ -4,6 +4,7 @@ namespace App\Actions\Git\Contracts;
|
||||
|
||||
use App\Actions\Git\Data\GitAuthenticatedUser;
|
||||
use App\Actions\Git\Data\GitBranch;
|
||||
use App\Actions\Git\Data\GitPullRequest;
|
||||
use App\Actions\Git\Data\GitRepository;
|
||||
use App\Actions\Git\GitProviderKey;
|
||||
|
||||
@@ -27,4 +28,14 @@ interface GitProviderClient
|
||||
string $owner,
|
||||
string $repository,
|
||||
): array;
|
||||
|
||||
/**
|
||||
* @return array<int, GitPullRequest>
|
||||
*/
|
||||
public function listPullRequests(
|
||||
string $baseUrl,
|
||||
string $token,
|
||||
string $owner,
|
||||
string $repository,
|
||||
): array;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Git\Data;
|
||||
|
||||
/**
|
||||
* Provider-agnostic representation of a pull request.
|
||||
*/
|
||||
final readonly class GitPullRequest
|
||||
{
|
||||
public function __construct(
|
||||
public string $number,
|
||||
public string $title,
|
||||
public string $status,
|
||||
public string $sourceBranch,
|
||||
public string $htmlUrl,
|
||||
) {}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ namespace App\Actions\Git\Gitea;
|
||||
use App\Actions\Git\Contracts\GitProviderClient;
|
||||
use App\Actions\Git\Data\GitAuthenticatedUser;
|
||||
use App\Actions\Git\Data\GitBranch;
|
||||
use App\Actions\Git\Data\GitPullRequest;
|
||||
use App\Actions\Git\Data\GitRepository;
|
||||
use App\Actions\Git\GitProviderKey;
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
@@ -113,6 +114,58 @@ class GiteaProviderClient implements GitProviderClient
|
||||
return $branches;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, GitPullRequest>
|
||||
*/
|
||||
public function listPullRequests(
|
||||
string $baseUrl,
|
||||
string $token,
|
||||
string $owner,
|
||||
string $repository,
|
||||
): array {
|
||||
$page = 1;
|
||||
$pullRequests = [];
|
||||
|
||||
do {
|
||||
/** @var array<int, array{
|
||||
* html_url: string,
|
||||
* merged?: bool,
|
||||
* number: int|string,
|
||||
* state: string,
|
||||
* title: string,
|
||||
* head: array{ref: string}
|
||||
* }> $payload
|
||||
*/
|
||||
$payload = $this->request($baseUrl, $token)
|
||||
->get(
|
||||
'/repos/'.rawurlencode($owner).'/'.rawurlencode($repository).'/pulls',
|
||||
[
|
||||
'limit' => 100,
|
||||
'page' => $page,
|
||||
'state' => 'all',
|
||||
],
|
||||
)
|
||||
->throw()
|
||||
->json();
|
||||
|
||||
foreach ($payload as $pullRequest) {
|
||||
$status = ($pullRequest['merged'] ?? false) ? 'merged' : $pullRequest['state'];
|
||||
|
||||
$pullRequests[] = new GitPullRequest(
|
||||
number: (string) $pullRequest['number'],
|
||||
title: $pullRequest['title'],
|
||||
status: $status,
|
||||
sourceBranch: $pullRequest['head']['ref'],
|
||||
htmlUrl: $pullRequest['html_url'],
|
||||
);
|
||||
}
|
||||
|
||||
$page++;
|
||||
} while (count($payload) === 100);
|
||||
|
||||
return $pullRequests;
|
||||
}
|
||||
|
||||
private function request(string $baseUrl, string $token): PendingRequest
|
||||
{
|
||||
return Http::acceptJson()
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user