new deployer command

This commit is contained in:
Mark Gregory
2026-09-16 12:32:50 +01:00
parent 856038c762
commit a137ffe852
3 changed files with 87 additions and 45 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ use Modules\Countries\Http\Controllers\CountriesController;
use Modules\Countries\Http\Controllers\CountrySyncController;
use Modules\Countries\Http\Controllers\ReferenceDataController;
const COUNTRY_ROUTE = COUNTRY_ROUTE;
const COUNTRY_ROUTE = '/{country}';
Route::prefix('countries')->name('countries.')->middleware(['web', 'auth'])->group(function (): void {
Route::get('/', CountriesController::class)->name('index');
+1 -1
View File
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Route;
use Modules\Documentation\Http\Controllers\DocumentationCategoryController;
use Modules\Documentation\Http\Controllers\DocumentationController;
const DOCUMENT_ROUTE = DOCUMENT_ROUTE;
const DOCUMENT_ROUTE = '/documents/{document}';
Route::middleware(['web', 'auth'])
->prefix('documentation')
@@ -22,6 +22,12 @@ final class GitWebhookController
private const SHA256_PREFIX = 'sha256=';
private const SHA1_PREFIX = 'sha1=';
private const REQUEST_ID_HEADER = 'X-Request-Id';
private const GITHUB_DELIVERY_HEADER = 'X-GitHub-Delivery';
private const GITHUB_EVENT_HEADER = 'X-GitHub-Event';
/**
* Ingest a signed Git provider webhook for a registered Helpdesk repository.
*/
@@ -235,43 +241,11 @@ final class GitWebhookController
return null;
}
$payloadValues = array_values(array_filter([
Arr::get($payload, 'repository.full_name'),
Arr::get($payload, 'repository.name'),
Arr::get($payload, 'repository.html_url'),
Arr::get($payload, 'repository.clone_url'),
Arr::get($payload, 'repository.ssh_url'),
Arr::get($payload, 'repository.url'),
Arr::get($payload, 'repository.owner.username') && Arr::get($payload, 'repository.name')
? Arr::get($payload, 'repository.owner.username') . '/' . Arr::get($payload, 'repository.name')
: null,
], static fn (mixed $value): bool => is_scalar($value) && trim((string) $value) !== ''));
$normalisedPayloadValues = array_values(array_filter(array_map(
fn (mixed $value): ?string => $this->normaliseRepositoryIdentity((string) $value),
$payloadValues,
)));
$normalisedPayloadValues = $this->normalisedPayloadRepositoryValues($payload);
foreach ($repositories as $repository) {
$repositoryValues = array_filter([
$repository->remote_url,
$repository->name,
Str::of((string) $repository->remote_url)->afterLast(':')->beforeLast('.git')->value(),
], static fn (mixed $value): bool => is_scalar($value) && trim((string) $value) !== '');
$normalisedRepositoryValues = array_values(array_filter(array_map(
fn (mixed $value): ?string => $this->normaliseRepositoryIdentity((string) $value),
$repositoryValues,
)));
foreach ($normalisedPayloadValues as $payloadValue) {
foreach ($normalisedRepositoryValues as $repositoryValue) {
if ($payloadValue === $repositoryValue
|| str_ends_with($repositoryValue, '/' . $payloadValue)
|| str_ends_with($payloadValue, '/' . $repositoryValue)) {
return $repository;
}
}
if ($this->repositoryMatchesPayload($repository, $normalisedPayloadValues)) {
return $repository;
}
}
@@ -287,6 +261,74 @@ final class GitWebhookController
return null;
}
/** @param array<string, mixed> $payload
* @return list<string>
*/
private function normalisedPayloadRepositoryValues(array $payload): array
{
$name = Arr::get($payload, 'repository.name');
$owner = Arr::get($payload, 'repository.owner.username');
return $this->normaliseRepositoryValues([
Arr::get($payload, 'repository.full_name'),
$name,
Arr::get($payload, 'repository.html_url'),
Arr::get($payload, 'repository.clone_url'),
Arr::get($payload, 'repository.ssh_url'),
Arr::get($payload, 'repository.url'),
$owner && $name ? $owner . '/' . $name : null,
]);
}
/** @param list<string> $payloadValues */
private function repositoryMatchesPayload(GitRepository $repository, array $payloadValues): bool
{
$repositoryValues = $this->normaliseRepositoryValues([
$repository->remote_url,
$repository->name,
Str::of((string) $repository->remote_url)->afterLast(':')->beforeLast('.git')->value(),
]);
foreach ($payloadValues as $payloadValue) {
foreach ($repositoryValues as $repositoryValue) {
if ($this->repositoryIdentitiesMatch($payloadValue, $repositoryValue)) {
return true;
}
}
}
return false;
}
/** @param array<int, mixed> $values
* @return list<string>
*/
private function normaliseRepositoryValues(array $values): array
{
$normalised = [];
foreach ($values as $value) {
if (! is_scalar($value) || trim((string) $value) === '') {
continue;
}
$identity = $this->normaliseRepositoryIdentity((string) $value);
if ($identity !== null) {
$normalised[] = $identity;
}
}
return $normalised;
}
private function repositoryIdentitiesMatch(string $payloadValue, string $repositoryValue): bool
{
return $payloadValue === $repositoryValue
|| str_ends_with($repositoryValue, '/' . $payloadValue)
|| str_ends_with($payloadValue, '/' . $repositoryValue);
}
/**
* Normalise a repository name or URL so Gitea payloads match local settings reliably.
*/
@@ -341,11 +383,11 @@ final class GitWebhookController
private function eventName(Request $request, string $provider): ?string
{
return match ($provider) {
'github' => $request->header('X-GitHub-Event'),
'github' => $request->header(self::GITHUB_EVENT_HEADER),
'gitlab' => $request->header('X-Gitlab-Event'),
'gitea' => $request->header('X-Gitea-Event') ?: $request->header('X-Gitea-Event-Type') ?: $request->header('X-GitHub-Event'),
'gitea' => $request->header('X-Gitea-Event') ?: $request->header('X-Gitea-Event-Type') ?: $request->header(self::GITHUB_EVENT_HEADER),
'bitbucket' => $request->header('X-Event-Key'),
default => $request->header('X-Helpdesk-Event') ?: $request->header('X-GitHub-Event') ?: $request->header('X-Gitlab-Event') ?: 'push',
default => $request->header('X-Helpdesk-Event') ?: $request->header(self::GITHUB_EVENT_HEADER) ?: $request->header('X-Gitlab-Event') ?: 'push',
};
}
@@ -355,11 +397,11 @@ final class GitWebhookController
private function deliveryId(Request $request, string $provider): ?string
{
return match ($provider) {
'github' => $request->header('X-GitHub-Delivery'),
'gitlab' => $request->header('X-Gitlab-Event-UUID') ?: $request->header('X-Request-Id'),
'gitea' => $request->header('X-Gitea-Delivery') ?: $request->header('X-GitHub-Delivery') ?: $request->header('X-Request-Id'),
'bitbucket' => $request->header('X-Request-UUID') ?: $request->header('X-Request-Id'),
default => $request->header('X-Helpdesk-Delivery') ?: $request->header('X-GitHub-Delivery') ?: $request->header('X-Request-Id'),
'github' => $request->header(self::GITHUB_DELIVERY_HEADER),
'gitlab' => $request->header('X-Gitlab-Event-UUID') ?: $request->header(self::REQUEST_ID_HEADER),
'gitea' => $request->header('X-Gitea-Delivery') ?: $request->header(self::GITHUB_DELIVERY_HEADER) ?: $request->header(self::REQUEST_ID_HEADER),
'bitbucket' => $request->header('X-Request-UUID') ?: $request->header(self::REQUEST_ID_HEADER),
default => $request->header('X-Helpdesk-Delivery') ?: $request->header(self::GITHUB_DELIVERY_HEADER) ?: $request->header(self::REQUEST_ID_HEADER),
};
}
}