fix(github): require opt-in custom webhook endpoint
This commit is contained in:
parent
a07cee7ad6
commit
9d1ede0733
3 changed files with 49 additions and 29 deletions
|
|
@ -23,6 +23,8 @@ class Change extends Component
|
||||||
|
|
||||||
public string $custom_webhook_endpoint = '';
|
public string $custom_webhook_endpoint = '';
|
||||||
|
|
||||||
|
public bool $use_custom_webhook_endpoint = false;
|
||||||
|
|
||||||
public ?string $ipv4 = null;
|
public ?string $ipv4 = null;
|
||||||
|
|
||||||
public ?string $ipv6 = null;
|
public ?string $ipv6 = null;
|
||||||
|
|
@ -101,6 +103,7 @@ protected function rules(): array
|
||||||
'privateKeyId' => 'nullable|int',
|
'privateKeyId' => 'nullable|int',
|
||||||
'webhook_endpoint' => ['required', 'string', 'url'],
|
'webhook_endpoint' => ['required', 'string', 'url'],
|
||||||
'custom_webhook_endpoint' => ['nullable', 'string', 'url'],
|
'custom_webhook_endpoint' => ['nullable', 'string', 'url'],
|
||||||
|
'use_custom_webhook_endpoint' => ['required', 'bool'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,7 @@ class="bg-transparent border-transparent hover:bg-transparent hover:border-trans
|
||||||
<section class="box-without-bg flex-col gap-4 p-6 h-full transition-all duration-200"
|
<section class="box-without-bg flex-col gap-4 p-6 h-full transition-all duration-200"
|
||||||
x-data="{
|
x-data="{
|
||||||
webhookEndpoint: $wire.entangle('webhook_endpoint').live,
|
webhookEndpoint: $wire.entangle('webhook_endpoint').live,
|
||||||
|
useCustomWebhookEndpoint: $wire.entangle('use_custom_webhook_endpoint').live,
|
||||||
customWebhookEndpoint: $wire.entangle('custom_webhook_endpoint').live,
|
customWebhookEndpoint: $wire.entangle('custom_webhook_endpoint').live,
|
||||||
}">
|
}">
|
||||||
<div class="flex flex-col gap-4 text-left h-full">
|
<div class="flex flex-col gap-4 text-left h-full">
|
||||||
|
|
@ -262,27 +263,35 @@ class="px-2 py-1 text-xs font-bold uppercase tracking-wide bg-coollabs/10 dark:b
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-3 pt-4 border-t border-neutral-200 dark:border-coolgray-400">
|
<div class="flex flex-col gap-3 pt-4 border-t border-neutral-200 dark:border-coolgray-400">
|
||||||
@if (!isCloud() || isDev())
|
@if (!isCloud() || isDev())
|
||||||
<x-forms.select canGate="create" :canResource="$github_app"
|
<x-forms.checkbox canGate="create" :canResource="$github_app"
|
||||||
wire:model.live='webhook_endpoint' x-model="webhookEndpoint"
|
x-model="useCustomWebhookEndpoint" id="use_custom_webhook_endpoint"
|
||||||
label="Webhook Endpoint"
|
label="Use custom webhook endpoint"
|
||||||
helper="All Git webhooks will be sent to this endpoint unless a custom endpoint is set below.">
|
helper="Enable this when the public URL GitHub should call differs from Coolify's configured URL, for example behind Cloudflare Tunnel." />
|
||||||
@if ($fqdn)
|
<div x-show="!useCustomWebhookEndpoint">
|
||||||
<option value="{{ $fqdn }}">Use {{ $fqdn }}</option>
|
<x-forms.select canGate="create" :canResource="$github_app"
|
||||||
@endif
|
wire:model.live='webhook_endpoint' x-model="webhookEndpoint"
|
||||||
@if ($ipv4)
|
label="Selected endpoint"
|
||||||
<option value="{{ $ipv4 }}">Use {{ $ipv4 }}</option>
|
helper="GitHub will use this endpoint unless custom mode is enabled.">
|
||||||
@endif
|
@if ($fqdn)
|
||||||
@if ($ipv6)
|
<option value="{{ $fqdn }}">Use {{ $fqdn }}</option>
|
||||||
<option value="{{ $ipv6 }}">Use {{ $ipv6 }}</option>
|
@endif
|
||||||
@endif
|
@if ($ipv4)
|
||||||
@if (config('app.url'))
|
<option value="{{ $ipv4 }}">Use {{ $ipv4 }}</option>
|
||||||
<option value="{{ config('app.url') }}">Use {{ config('app.url') }}</option>
|
@endif
|
||||||
@endif
|
@if ($ipv6)
|
||||||
</x-forms.select>
|
<option value="{{ $ipv6 }}">Use {{ $ipv6 }}</option>
|
||||||
<x-forms.input canGate="create" :canResource="$github_app"
|
@endif
|
||||||
x-model="customWebhookEndpoint" id="custom_webhook_endpoint" type="url"
|
@if (config('app.url'))
|
||||||
label="Custom Webhook Endpoint" placeholder="https://coolify.example.com"
|
<option value="{{ config('app.url') }}">Use {{ config('app.url') }}</option>
|
||||||
helper="Use a custom URL only when it should override the selected endpoint. Useful when a tunnel or proxy terminates HTTPS while Coolify itself is configured with HTTP. Do not include /webhooks." />
|
@endif
|
||||||
|
</x-forms.select>
|
||||||
|
</div>
|
||||||
|
<div x-cloak x-show="useCustomWebhookEndpoint">
|
||||||
|
<x-forms.input canGate="create" :canResource="$github_app"
|
||||||
|
x-model="customWebhookEndpoint" id="custom_webhook_endpoint" type="url"
|
||||||
|
label="Custom endpoint" placeholder="https://coolify.example.com"
|
||||||
|
helper="GitHub will use this custom public URL. Do not include /webhooks." />
|
||||||
|
</div>
|
||||||
@else
|
@else
|
||||||
<div class="text-sm dark:text-neutral-400">You need to register a GitHub App before using this source.</div>
|
<div class="text-sm dark:text-neutral-400">You need to register a GitHub App before using this source.</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
@ -296,7 +305,7 @@ class="px-2 py-1 text-xs font-bold uppercase tracking-wide bg-coollabs/10 dark:b
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-auto pt-2">
|
<div class="mt-auto pt-2">
|
||||||
<x-forms.button canGate="create" :canResource="$github_app" class="w-full justify-center" isHighlighted
|
<x-forms.button canGate="create" :canResource="$github_app" class="w-full justify-center" isHighlighted
|
||||||
x-on:click.prevent="createGithubApp(webhookEndpoint, customWebhookEndpoint, {{ Illuminate\Support\Js::from($preview_deployment_permissions) }}, {{ Illuminate\Support\Js::from($administration) }})">
|
x-on:click.prevent="createGithubApp(webhookEndpoint, useCustomWebhookEndpoint, customWebhookEndpoint, {{ Illuminate\Support\Js::from($preview_deployment_permissions) }}, {{ Illuminate\Support\Js::from($administration) }})">
|
||||||
Register Now
|
Register Now
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -339,7 +348,7 @@ class="px-2 py-1 text-xs font-bold uppercase tracking-wide bg-neutral-100 dark:b
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
function createGithubApp(webhook_endpoint, custom_webhook_endpoint, preview_deployment_permissions, administration) {
|
function createGithubApp(webhook_endpoint, use_custom_webhook_endpoint, custom_webhook_endpoint, preview_deployment_permissions, administration) {
|
||||||
const {
|
const {
|
||||||
organization,
|
organization,
|
||||||
html_url,
|
html_url,
|
||||||
|
|
@ -347,11 +356,15 @@ function createGithubApp(webhook_endpoint, custom_webhook_endpoint, preview_depl
|
||||||
} = @js($github_app->only(['organization', 'html_url', 'uuid']));
|
} = @js($github_app->only(['organization', 'html_url', 'uuid']));
|
||||||
const selectedEndpoint = webhook_endpoint ? webhook_endpoint.trim() : '';
|
const selectedEndpoint = webhook_endpoint ? webhook_endpoint.trim() : '';
|
||||||
const customEndpoint = custom_webhook_endpoint ? custom_webhook_endpoint.trim() : '';
|
const customEndpoint = custom_webhook_endpoint ? custom_webhook_endpoint.trim() : '';
|
||||||
if (!customEndpoint && !selectedEndpoint) {
|
if (use_custom_webhook_endpoint && !customEndpoint) {
|
||||||
|
alert('Please enter a custom webhook endpoint.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!use_custom_webhook_endpoint && !selectedEndpoint) {
|
||||||
alert('Please enter a webhook endpoint.');
|
alert('Please enter a webhook endpoint.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let baseUrl = (customEndpoint || selectedEndpoint).replace(/\/+$/, '');
|
let baseUrl = (use_custom_webhook_endpoint ? customEndpoint : selectedEndpoint).replace(/\/+$/, '');
|
||||||
const name = @js($name);
|
const name = @js($name);
|
||||||
const manifestState = @js($manifestState);
|
const manifestState = @js($manifestState);
|
||||||
const isDev = @js(config('app.env')) ===
|
const isDev = @js(config('app.env')) ===
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ function validPrivateKey(): string
|
||||||
->assertSet('webhook_endpoint', 'http://localhost:8000');
|
->assertSet('webhook_endpoint', 'http://localhost:8000');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('custom webhook endpoint input is used as an override for selected endpoint', function () {
|
test('custom webhook endpoint is selected explicitly with a checkbox', function () {
|
||||||
config(['app.url' => 'http://localhost:8000']);
|
config(['app.url' => 'http://localhost:8000']);
|
||||||
|
|
||||||
InstanceSettings::findOrFail(0)->update([
|
InstanceSettings::findOrFail(0)->update([
|
||||||
|
|
@ -131,12 +131,16 @@ function validPrivateKey(): string
|
||||||
Livewire::withQueryParams(['github_app_uuid' => $githubApp->uuid])
|
Livewire::withQueryParams(['github_app_uuid' => $githubApp->uuid])
|
||||||
->test(Change::class)
|
->test(Change::class)
|
||||||
->assertSuccessful()
|
->assertSuccessful()
|
||||||
|
->assertSet('use_custom_webhook_endpoint', false)
|
||||||
->set('custom_webhook_endpoint', 'https://staging.example.com')
|
->set('custom_webhook_endpoint', 'https://staging.example.com')
|
||||||
|
->set('use_custom_webhook_endpoint', true)
|
||||||
->assertSet('webhook_endpoint', 'http://staging.example.com')
|
->assertSet('webhook_endpoint', 'http://staging.example.com')
|
||||||
->assertSet('custom_webhook_endpoint', 'https://staging.example.com')
|
->assertSet('custom_webhook_endpoint', 'https://staging.example.com')
|
||||||
->assertSee('Use a custom URL only when it should override the selected endpoint.', false)
|
->assertSet('use_custom_webhook_endpoint', true)
|
||||||
->assertSee('Custom Webhook Endpoint')
|
->assertSee('Use custom webhook endpoint')
|
||||||
->assertSee('createGithubApp(webhookEndpoint, customWebhookEndpoint');
|
->assertSee('Selected endpoint')
|
||||||
|
->assertSee('Custom endpoint')
|
||||||
|
->assertSee('createGithubApp(webhookEndpoint, useCustomWebhookEndpoint, customWebhookEndpoint');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('can mount with fully configured github app', function () {
|
test('can mount with fully configured github app', function () {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue