2023-05-16 11:11:05 +00:00
< ? php
2023-12-07 18:06:32 +00:00
namespace App\Livewire\Project\Application ;
2023-05-16 11:11:05 +00:00
2024-05-30 10:28:29 +00:00
use App\Actions\Docker\GetContainersStatus ;
2023-05-16 11:11:05 +00:00
use App\Models\Application ;
2023-05-30 13:52:17 +00:00
use App\Models\ApplicationPreview ;
use Illuminate\Support\Collection ;
2023-05-16 11:11:05 +00:00
use Livewire\Component ;
2024-05-30 10:28:29 +00:00
use Spatie\Url\Url ;
2023-05-30 13:52:17 +00:00
use Visus\Cuid2\Cuid2 ;
2023-05-16 11:11:05 +00:00
class Previews extends Component
{
public Application $application ;
2024-06-10 20:43:34 +00:00
2023-05-30 13:52:17 +00:00
public string $deployment_uuid ;
2024-06-10 20:43:34 +00:00
2023-05-30 13:52:17 +00:00
public array $parameters ;
2024-06-10 20:43:34 +00:00
2023-05-30 13:52:17 +00:00
public Collection $pull_requests ;
2024-06-10 20:43:34 +00:00
2023-05-30 13:52:17 +00:00
public int $rate_limit_remaining ;
2024-05-30 10:28:29 +00:00
protected $rules = [
'application.previews.*.fqdn' => 'string|nullable' ,
];
2024-06-10 20:43:34 +00:00
2023-05-30 13:52:17 +00:00
public function mount ()
{
$this -> pull_requests = collect ();
2023-08-09 13:57:53 +00:00
$this -> parameters = get_route_parameters ();
2023-05-30 13:52:17 +00:00
}
2023-08-08 09:51:36 +00:00
2023-05-30 13:52:17 +00:00
public function load_prs ()
{
2023-06-02 10:34:45 +00:00
try {
2023-10-06 11:46:42 +00:00
[ 'rate_limit_remaining' => $rate_limit_remaining , 'data' => $data ] = githubApi ( source : $this -> application -> source , endpoint : " /repos/ { $this -> application -> git_repository } /pulls " );
2023-06-02 10:34:45 +00:00
$this -> rate_limit_remaining = $rate_limit_remaining ;
$this -> pull_requests = $data -> sortBy ( 'number' ) -> values ();
2023-06-09 13:55:21 +00:00
} catch ( \Throwable $e ) {
2023-06-02 10:34:45 +00:00
$this -> rate_limit_remaining = 0 ;
2024-06-10 20:43:34 +00:00
2023-09-15 13:34:25 +00:00
return handleError ( $e , $this );
2023-06-02 10:34:45 +00:00
}
2023-05-30 13:52:17 +00:00
}
2024-06-10 20:43:34 +00:00
2024-05-30 10:28:29 +00:00
public function save_preview ( $preview_id )
{
try {
$success = true ;
$preview = $this -> application -> previews -> find ( $preview_id );
2024-06-05 13:14:44 +00:00
if ( data_get_str ( $preview , 'fqdn' ) -> isNotEmpty ()) {
2024-05-30 10:28:29 +00:00
$preview -> fqdn = str ( $preview -> fqdn ) -> replaceEnd ( ',' , '' ) -> trim ();
$preview -> fqdn = str ( $preview -> fqdn ) -> replaceStart ( ',' , '' ) -> trim ();
$preview -> fqdn = str ( $preview -> fqdn ) -> trim () -> lower ();
2024-06-10 20:43:34 +00:00
if ( ! validate_dns_entry ( $preview -> fqdn , $this -> application -> destination -> server )) {
$this -> dispatch ( 'error' , 'Validating DNS failed.' , " Make sure you have added the DNS records correctly.<br><br> $preview->fqdn -> { $this -> application -> destination -> server -> ip } <br><br>Check this <a target='_blank' class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/dns-configuration'>documentation</a> for further help. " );
2024-05-30 10:28:29 +00:00
$success = false ;
}
check_domain_usage ( resource : $this -> application , domain : $preview -> fqdn );
}
2023-08-08 09:51:36 +00:00
2024-06-10 20:43:34 +00:00
if ( ! $preview ) {
2024-05-30 10:28:29 +00:00
throw new \Exception ( 'Preview not found' );
}
$success && $preview -> save ();
$success && $this -> dispatch ( 'success' , 'Preview saved.<br><br>Do not forget to redeploy the preview to apply the changes.' );
} catch ( \Throwable $e ) {
return handleError ( $e , $this );
}
}
2024-06-10 20:43:34 +00:00
2024-05-30 10:28:29 +00:00
public function generate_preview ( $preview_id )
{
$preview = $this -> application -> previews -> find ( $preview_id );
2024-06-10 20:43:34 +00:00
if ( ! $preview ) {
2024-05-30 10:28:29 +00:00
$this -> dispatch ( 'error' , 'Preview not found.' );
2024-06-10 20:43:34 +00:00
2024-05-30 10:28:29 +00:00
return ;
}
$fqdn = generateFqdn ( $this -> application -> destination -> server , $this -> application -> uuid );
$url = Url :: fromString ( $fqdn );
$template = $this -> application -> preview_url_template ;
$host = $url -> getHost ();
$schema = $url -> getScheme ();
$random = new Cuid2 ( 7 );
$preview_fqdn = str_replace ( '{{random}}' , $random , $template );
$preview_fqdn = str_replace ( '{{domain}}' , $host , $preview_fqdn );
2024-06-05 13:14:44 +00:00
$preview_fqdn = str_replace ( '{{pr_id}}' , $preview -> pull_request_id , $preview_fqdn );
2024-05-30 10:28:29 +00:00
$preview_fqdn = " $schema :// $preview_fqdn " ;
$preview -> fqdn = $preview_fqdn ;
$preview -> save ();
$this -> dispatch ( 'success' , 'Domain generated.' );
}
2024-06-10 20:43:34 +00:00
public function add ( int $pull_request_id , ? string $pull_request_html_url = null )
2024-05-30 10:28:29 +00:00
{
try {
2024-06-05 13:14:44 +00:00
if ( $this -> application -> build_pack === 'dockercompose' ) {
$this -> setDeploymentUuid ();
$found = ApplicationPreview :: where ( 'application_id' , $this -> application -> id ) -> where ( 'pull_request_id' , $pull_request_id ) -> first ();
2024-06-10 20:43:34 +00:00
if ( ! $found && ! is_null ( $pull_request_html_url )) {
2024-06-05 13:14:44 +00:00
$found = ApplicationPreview :: create ([
'application_id' => $this -> application -> id ,
'pull_request_id' => $pull_request_id ,
'pull_request_html_url' => $pull_request_html_url ,
'docker_compose_domains' => $this -> application -> docker_compose_domains ,
]);
}
$found -> generate_preview_fqdn_compose ();
$this -> application -> refresh ();
} else {
$this -> setDeploymentUuid ();
$found = ApplicationPreview :: where ( 'application_id' , $this -> application -> id ) -> where ( 'pull_request_id' , $pull_request_id ) -> first ();
2024-06-10 20:43:34 +00:00
if ( ! $found && ! is_null ( $pull_request_html_url )) {
2024-06-05 13:14:44 +00:00
$found = ApplicationPreview :: create ([
'application_id' => $this -> application -> id ,
'pull_request_id' => $pull_request_id ,
'pull_request_html_url' => $pull_request_html_url ,
]);
}
$this -> application -> generate_preview_fqdn ( $pull_request_id );
$this -> application -> refresh ();
$this -> dispatch ( 'update_links' );
$this -> dispatch ( 'success' , 'Preview added.' );
2024-05-30 10:28:29 +00:00
}
} catch ( \Throwable $e ) {
return handleError ( $e , $this );
}
}
2024-06-10 20:43:34 +00:00
2024-06-12 10:21:47 +00:00
public function add_and_deploy ( int $pull_request_id , ? string $pull_request_html_url = null )
{
2024-06-12 10:20:58 +00:00
$this -> add ( $pull_request_id , $pull_request_html_url );
$this -> deploy ( $pull_request_id , $pull_request_html_url );
}
2024-06-12 10:21:47 +00:00
2024-06-10 20:43:34 +00:00
public function deploy ( int $pull_request_id , ? string $pull_request_html_url = null )
2023-05-30 13:52:17 +00:00
{
try {
2023-06-15 07:15:41 +00:00
$this -> setDeploymentUuid ();
2023-05-30 15:00:11 +00:00
$found = ApplicationPreview :: where ( 'application_id' , $this -> application -> id ) -> where ( 'pull_request_id' , $pull_request_id ) -> first ();
2024-06-10 20:43:34 +00:00
if ( ! $found && ! is_null ( $pull_request_html_url )) {
2023-05-30 15:00:11 +00:00
ApplicationPreview :: create ([
'application_id' => $this -> application -> id ,
'pull_request_id' => $pull_request_id ,
2024-06-10 20:43:34 +00:00
'pull_request_html_url' => $pull_request_html_url ,
2023-05-30 15:00:11 +00:00
]);
}
2023-05-30 13:52:17 +00:00
queue_application_deployment (
2024-01-27 17:44:40 +00:00
application : $this -> application ,
2023-05-30 13:52:17 +00:00
deployment_uuid : $this -> deployment_uuid ,
2024-01-16 14:45:19 +00:00
force_rebuild : false ,
2023-05-30 13:52:17 +00:00
pull_request_id : $pull_request_id ,
2024-01-16 14:45:19 +00:00
git_type : $found -> git_type ? ? null ,
2023-05-30 13:52:17 +00:00
);
2024-06-10 20:43:34 +00:00
2024-01-07 15:23:41 +00:00
return redirect () -> route ( 'project.application.deployment.show' , [
2023-05-31 08:19:29 +00:00
'project_uuid' => $this -> parameters [ 'project_uuid' ],
'application_uuid' => $this -> parameters [ 'application_uuid' ],
2023-05-31 12:42:37 +00:00
'deployment_uuid' => $this -> deployment_uuid ,
2023-05-31 08:19:29 +00:00
'environment_name' => $this -> parameters [ 'environment_name' ],
2023-12-27 15:45:01 +00:00
]);
2023-06-09 13:55:21 +00:00
} catch ( \Throwable $e ) {
2023-09-15 13:34:25 +00:00
return handleError ( $e , $this );
2023-05-30 13:52:17 +00:00
}
}
2023-08-08 09:51:36 +00:00
protected function setDeploymentUuid ()
{
$this -> deployment_uuid = new Cuid2 ( 7 );
$this -> parameters [ 'deployment_uuid' ] = $this -> deployment_uuid ;
}
2023-05-30 13:52:17 +00:00
public function stop ( int $pull_request_id )
2024-05-30 10:28:29 +00:00
{
try {
if ( $this -> application -> destination -> server -> isSwarm ()) {
instant_remote_process ([ " docker stack rm { $this -> application -> uuid } - { $pull_request_id } " ], $this -> application -> destination -> server );
} else {
$containers = getCurrentApplicationContainerStatus ( $this -> application -> destination -> server , $this -> application -> id , $pull_request_id );
foreach ( $containers as $container ) {
$name = str_replace ( '/' , '' , $container [ 'Names' ]);
instant_remote_process ([ " docker rm -f $name " ], $this -> application -> destination -> server , throwError : false );
}
}
2024-06-20 12:52:12 +00:00
GetContainersStatus :: dispatchSync ( $this -> application -> destination -> server ) -> onQueue ( 'high' );
2024-06-05 13:14:44 +00:00
$this -> dispatch ( 'reloadWindow' );
2024-05-30 10:28:29 +00:00
} catch ( \Throwable $e ) {
return handleError ( $e , $this );
}
}
public function delete ( int $pull_request_id )
2023-05-30 13:52:17 +00:00
{
try {
2023-12-18 13:01:25 +00:00
if ( $this -> application -> destination -> server -> isSwarm ()) {
instant_remote_process ([ " docker stack rm { $this -> application -> uuid } - { $pull_request_id } " ], $this -> application -> destination -> server );
} else {
$containers = getCurrentApplicationContainerStatus ( $this -> application -> destination -> server , $this -> application -> id , $pull_request_id );
foreach ( $containers as $container ) {
$name = str_replace ( '/' , '' , $container [ 'Names' ]);
instant_remote_process ([ " docker rm -f $name " ], $this -> application -> destination -> server , throwError : false );
}
2023-11-27 13:28:21 +00:00
}
2023-11-27 14:25:15 +00:00
ApplicationPreview :: where ( 'application_id' , $this -> application -> id ) -> where ( 'pull_request_id' , $pull_request_id ) -> first () -> delete ();
2023-05-30 15:05:27 +00:00
$this -> application -> refresh ();
2024-06-05 13:14:44 +00:00
$this -> dispatch ( 'update_links' );
$this -> dispatch ( 'success' , 'Preview deleted.' );
2023-06-09 13:55:21 +00:00
} catch ( \Throwable $e ) {
2023-09-15 13:34:25 +00:00
return handleError ( $e , $this );
2023-05-30 13:52:17 +00:00
}
}
2023-05-16 11:11:05 +00:00
}