- Updated dashboard, destination, project, and server views to replace 'box' class with 'coolbox' for improved visual consistency. - Modified links and buttons in shared variables and scheduled tasks views to utilize 'coolbox' class. - Ensured all relevant components reflect the new styling approach, enhancing user experience and interface coherence.
354 lines
22 KiB
PHP
354 lines
22 KiB
PHP
<div>
|
|
@if (data_get($github_app, 'app_id'))
|
|
<form wire:submit='submit'>
|
|
<div class="flex flex-col sm:flex-row sm:items-center gap-2">
|
|
<h1>GitHub App</h1>
|
|
<div class="flex gap-2">
|
|
@if (data_get($github_app, 'installation_id'))
|
|
<x-forms.button canGate="update" :canResource="$github_app" type="submit">Save</x-forms.button>
|
|
@endif
|
|
@can('delete', $github_app)
|
|
@if ($applications->count() > 0)
|
|
<x-modal-confirmation title="Confirm GitHub App Deletion?" isErrorButton buttonTitle="Delete"
|
|
submitAction="delete" :actions="['The selected GitHub App will be permanently deleted.']" confirmationText="{{ data_get($github_app, 'name') }}"
|
|
confirmationLabel="Please confirm the execution of the actions by entering the GitHub App Name below"
|
|
shortConfirmationLabel="GitHub App Name" :confirmWithPassword="false"
|
|
step2ButtonText="Permanently Delete" />
|
|
@else
|
|
<x-modal-confirmation title="Confirm GitHub App Deletion?" isErrorButton buttonTitle="Delete"
|
|
submitAction="delete" :actions="['The selected GitHub App will be permanently deleted.']"
|
|
confirmationLabel="Please confirm the execution of the actions by entering the GitHub App Name below"
|
|
shortConfirmationLabel="GitHub App Name"
|
|
confirmationText="{{ data_get($github_app, 'name') }}" :confirmWithPassword="false"
|
|
step2ButtonText="Permanently Delete" />
|
|
@endif
|
|
@endcan
|
|
</div>
|
|
</div>
|
|
<div class="subtitle">Your Private GitHub App for private repositories.</div>
|
|
@if (!data_get($github_app, 'installation_id'))
|
|
<div class="mb-10 rounded-sm alert-error">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none"
|
|
viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
</svg>
|
|
<span>You must complete this step before you can use this source!</span>
|
|
</div>
|
|
<a class="items-center justify-center coolbox" href="{{ getInstallationPath($github_app) }}">
|
|
Install Repositories on GitHub
|
|
</a>
|
|
@else
|
|
<div class="flex flex-col gap-2">
|
|
<div class="flex flex-col sm:flex-row gap-2">
|
|
<div class="flex flex-col sm:flex-row items-start sm:items-end gap-2 w-full">
|
|
<x-forms.input canGate="update" :canResource="$github_app" id="name" label="App Name" />
|
|
<x-forms.button canGate="update" :canResource="$github_app" wire:click.prevent="updateGithubAppName">
|
|
Sync Name
|
|
</x-forms.button>
|
|
@can('update', $github_app)
|
|
<a href="{{ $this->getGithubAppNameUpdatePath() }}">
|
|
<x-forms.button
|
|
class="bg-transparent border-transparent hover:bg-transparent hover:border-transparent hover:underline">
|
|
Rename
|
|
<x-external-link />
|
|
</x-forms.button>
|
|
</a>
|
|
<a href="{{ getInstallationPath($github_app) }}" class="w-fit">
|
|
<x-forms.button
|
|
class="bg-transparent border-transparent hover:bg-transparent hover:border-transparent hover:underline whitespace-nowrap">
|
|
Update Repositories
|
|
<x-external-link />
|
|
</x-forms.button>
|
|
</a>
|
|
@endcan
|
|
</div>
|
|
</div>
|
|
<x-forms.input canGate="update" :canResource="$github_app" id="organization" label="Organization"
|
|
placeholder="If empty, personal user will be used" />
|
|
@if (!isCloud())
|
|
<div class="w-48">
|
|
<x-forms.checkbox canGate="update" :canResource="$github_app" label="System Wide?"
|
|
helper="If checked, this GitHub App will be available for everyone in this Coolify instance."
|
|
instantSave id="isSystemWide" />
|
|
</div>
|
|
@if ($isSystemWide)
|
|
<x-callout type="warning" title="Not Recommended">
|
|
System-wide GitHub Apps are shared across all teams on this Coolify instance. This means any team can use this GitHub App to deploy applications from your repositories. For better security and isolation, it's recommended to create team-specific GitHub Apps instead.
|
|
</x-callout>
|
|
@endif
|
|
@endif
|
|
<div class="flex flex-col sm:flex-row gap-2">
|
|
<x-forms.input canGate="update" :canResource="$github_app" id="htmlUrl" label="HTML Url" />
|
|
<x-forms.input canGate="update" :canResource="$github_app" id="apiUrl" label="API Url" />
|
|
</div>
|
|
<div class="flex flex-col sm:flex-row gap-2">
|
|
<x-forms.input canGate="update" :canResource="$github_app" id="customUser" label="User"
|
|
required />
|
|
<x-forms.input canGate="update" :canResource="$github_app" type="number" id="customPort"
|
|
label="Port" required />
|
|
</div>
|
|
<div class="flex flex-col sm:flex-row gap-2">
|
|
<x-forms.input canGate="update" :canResource="$github_app" type="number" id="appId"
|
|
label="App Id" required />
|
|
<x-forms.input canGate="update" :canResource="$github_app" type="number"
|
|
id="installationId" label="Installation Id" required />
|
|
</div>
|
|
<div class="flex flex-col sm:flex-row gap-2">
|
|
<x-forms.input canGate="update" :canResource="$github_app" id="clientId" label="Client Id"
|
|
type="password" required />
|
|
<x-forms.input canGate="update" :canResource="$github_app" id="clientSecret"
|
|
label="Client Secret" type="password" required />
|
|
<x-forms.input canGate="update" :canResource="$github_app" id="webhookSecret"
|
|
label="Webhook Secret" type="password" required />
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<x-forms.select canGate="update" :canResource="$github_app" id="privateKeyId"
|
|
label="Private Key" required>
|
|
@if (blank($github_app->private_key_id))
|
|
<option value="0" selected>Select a private key</option>
|
|
@endif
|
|
@foreach ($privateKeys as $privateKey)
|
|
<option value="{{ $privateKey->id }}">{{ $privateKey->name }}</option>
|
|
@endforeach
|
|
</x-forms.select>
|
|
</div>
|
|
<div class="flex flex-col sm:flex-row items-start sm:items-end gap-2">
|
|
<h2 class="pt-4">Permissions</h2>
|
|
@can('view', $github_app)
|
|
<x-forms.button wire:click.prevent="checkPermissions">Refetch</x-forms.button>
|
|
<a href="{{ getPermissionsPath($github_app) }}">
|
|
<x-forms.button>
|
|
Update
|
|
<x-external-link />
|
|
</x-forms.button>
|
|
</a>
|
|
@endcan
|
|
</div>
|
|
<div class="flex flex-col sm:flex-row gap-2">
|
|
<x-forms.input id="contents" helper="read - mandatory." label="Content" readonly
|
|
placeholder="N/A" />
|
|
<x-forms.input id="metadata" helper="read - mandatory." label="Metadata" readonly
|
|
placeholder="N/A" />
|
|
{{-- <x-forms.input id="administration"
|
|
helper="read:write access needed to setup servers as GitHub Runner." label="Administration"
|
|
readonly placeholder="N/A" /> --}}
|
|
<x-forms.input id="pullRequests"
|
|
helper="write access needed to use deployment status update in previews."
|
|
label="Pull Request" readonly placeholder="N/A" />
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</form>
|
|
@if (data_get($github_app, 'installation_id'))
|
|
<div class="w-full pt-10">
|
|
<div class="h-full">
|
|
<div class="flex flex-col">
|
|
<div class="flex gap-2">
|
|
<h2>Resources</h2>
|
|
</div>
|
|
<div class="pb-4 title">Here you can find all resources that are using this source.</div>
|
|
</div>
|
|
@if ($applications->isEmpty())
|
|
<div class="py-4 text-sm opacity-70">
|
|
No resources are currently using this GitHub App.
|
|
</div>
|
|
@else
|
|
<div class="flex flex-col">
|
|
<div class="flex flex-col">
|
|
<div class="overflow-x-auto">
|
|
<div class="inline-block min-w-full">
|
|
<div class="overflow-hidden">
|
|
<table class="min-w-full">
|
|
<thead>
|
|
<tr>
|
|
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
|
Project
|
|
</th>
|
|
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
|
Environment</th>
|
|
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Name
|
|
</th>
|
|
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Type
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y">
|
|
@foreach ($applications->sortBy('name',SORT_NATURAL) as $resource)
|
|
<tr>
|
|
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
|
{{ data_get($resource->project(), 'name') }}
|
|
</td>
|
|
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
|
{{ data_get($resource, 'environment.name') }}
|
|
</td>
|
|
<td class="px-5 py-4 text-sm whitespace-nowrap"><a
|
|
class=""
|
|
href="{{ $resource->link() }}">{{ $resource->name }}
|
|
<x-internal-link /></a>
|
|
</td>
|
|
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
|
{{ str($resource->type())->headline() }}</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endif
|
|
@else
|
|
<div class="flex flex-col sm:flex-row sm:items-center gap-2 pb-4">
|
|
<h1>GitHub App</h1>
|
|
<div class="flex gap-2">
|
|
@can('delete', $github_app)
|
|
<x-modal-confirmation title="Confirm GitHub App Deletion?" isErrorButton buttonTitle="Delete"
|
|
submitAction="delete" :actions="['The selected GitHub App will be permanently deleted.']" confirmationText="{{ data_get($github_app, 'name') }}"
|
|
confirmationLabel="Please confirm the execution of the actions by entering the GitHub App Name below"
|
|
shortConfirmationLabel="GitHub App Name" :confirmWithPassword="false"
|
|
step2ButtonText="Permanently Delete" />
|
|
@endcan
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-col gap-2">
|
|
@can('create', $github_app)
|
|
<h3>Manual Installation</h3>
|
|
<div class="flex gap-2 items-center">
|
|
If you want to fill the form manually, you can continue below. Only for advanced users.
|
|
<x-forms.button wire:click.prevent="createGithubAppManually">
|
|
Continue
|
|
</x-forms.button>
|
|
</div>
|
|
<h3>Automated Installation</h3>
|
|
<div class=" pb-5 rounded-sm alert-error">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none"
|
|
viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
</svg>
|
|
<span>You must complete this step before you can use this source!</span>
|
|
</div>
|
|
@endcan
|
|
<div class="flex flex-col">
|
|
<div class="pb-10">
|
|
@can('create', $github_app)
|
|
@if (!isCloud() || isDev())
|
|
<div class="flex flex-col sm:flex-row items-start sm:items-end gap-2">
|
|
<x-forms.select wire:model.live='webhook_endpoint' label="Webhook Endpoint"
|
|
helper="All Git webhooks will be sent to this endpoint. <br><br>If you would like to use domain instead of IP address, set your Coolify instance's FQDN in the Settings menu.">
|
|
@if ($ipv4)
|
|
<option value="{{ $ipv4 }}">Use {{ $ipv4 }}</option>
|
|
@endif
|
|
@if ($ipv6)
|
|
<option value="{{ $ipv6 }}">Use {{ $ipv6 }}</option>
|
|
@endif
|
|
@if ($fqdn)
|
|
<option value="{{ $fqdn }}">Use {{ $fqdn }}</option>
|
|
@endif
|
|
@if (config('app.url'))
|
|
<option value="{{ config('app.url') }}">Use {{ config('app.url') }}</option>
|
|
@endif
|
|
</x-forms.select>
|
|
<x-forms.button isHighlighted
|
|
x-on:click.prevent="createGithubApp('{{ $webhook_endpoint }}','{{ $preview_deployment_permissions }}',{{ $administration }})">
|
|
Register Now
|
|
</x-forms.button>
|
|
</div>
|
|
@else
|
|
<div class="flex flex-col sm:flex-row gap-2">
|
|
<h2>Register a GitHub App</h2>
|
|
<x-forms.button isHighlighted
|
|
x-on:click.prevent="createGithubApp('{{ $webhook_endpoint }}','{{ $preview_deployment_permissions }}',{{ $administration }})">
|
|
Register Now
|
|
</x-forms.button>
|
|
</div>
|
|
<div>You need to register a GitHub App before using this source.</div>
|
|
@endif
|
|
|
|
<div class="flex flex-col gap-2 pt-4 w-96">
|
|
<x-forms.checkbox disabled id="default_permissions" label="Mandatory"
|
|
helper="Contents: read<br>Metadata: read<br>Email: read" />
|
|
<x-forms.checkbox id="preview_deployment_permissions" label="Preview Deployments "
|
|
helper="Necessary for updating pull requests with useful comments (deployment status, links, etc.)<br><br>Pull Request: read & write" />
|
|
{{-- <x-forms.checkbox id="administration" label="Administration (for Github Runners)"
|
|
helper="Necessary for adding Github Runners to repositories.<br><br>Administration: read & write" /> --}}
|
|
</div>
|
|
@else
|
|
<x-callout type="danger" title="Insufficient Permissions">
|
|
You don't have permission to create new GitHub Apps. Please contact your team administrator.
|
|
</x-callout>
|
|
@endcan
|
|
</div>
|
|
</div>
|
|
<script>
|
|
function createGithubApp(webhook_endpoint, preview_deployment_permissions, administration) {
|
|
const {
|
|
organization,
|
|
uuid,
|
|
html_url
|
|
} = @json($github_app);
|
|
if (!webhook_endpoint) {
|
|
alert('Please select a webhook endpoint.');
|
|
return;
|
|
}
|
|
let baseUrl = webhook_endpoint;
|
|
const name = @js($name);
|
|
const isDev = @js(config('app.env')) ===
|
|
'local';
|
|
const devWebhook = @js(config('constants.webhooks.dev_webhook'));
|
|
if (isDev && devWebhook) {
|
|
baseUrl = devWebhook;
|
|
}
|
|
const webhookBaseUrl = `${baseUrl}/webhooks`;
|
|
const path = organization ? `organizations/${organization}/settings/apps/new` : 'settings/apps/new';
|
|
const default_permissions = {
|
|
contents: 'read',
|
|
metadata: 'read',
|
|
emails: 'read',
|
|
administration: 'read'
|
|
};
|
|
const default_events = ['push'];
|
|
if (preview_deployment_permissions) {
|
|
default_permissions.pull_requests = 'write';
|
|
default_events.push('pull_request');
|
|
}
|
|
if (administration) {
|
|
default_permissions.administration = 'write';
|
|
}
|
|
|
|
const data = {
|
|
name,
|
|
url: baseUrl,
|
|
hook_attributes: {
|
|
url: `${webhookBaseUrl}/source/github/events`,
|
|
active: true,
|
|
},
|
|
redirect_url: `${webhookBaseUrl}/source/github/redirect`,
|
|
callback_urls: [`${baseUrl}/login/github/app`],
|
|
public: false,
|
|
request_oauth_on_install: false,
|
|
setup_url: `${webhookBaseUrl}/source/github/install?source=${uuid}`,
|
|
setup_on_update: true,
|
|
default_permissions,
|
|
default_events
|
|
};
|
|
const form = document.createElement('form');
|
|
form.setAttribute('method', 'post');
|
|
form.setAttribute('action', `${html_url}/${path}?state=${uuid}`);
|
|
const input = document.createElement('input');
|
|
input.setAttribute('id', 'manifest');
|
|
input.setAttribute('name', 'manifest');
|
|
input.setAttribute('type', 'hidden');
|
|
input.setAttribute('value', JSON.stringify(data));
|
|
form.appendChild(input);
|
|
document.getElementsByTagName('body')[0].appendChild(form);
|
|
form.submit();
|
|
}
|
|
</script>
|
|
@endif
|
|
</div>
|