id; $deployment_link = Url::fromString($application->link()."/deployment/{$deployment_uuid}"); $deployment_url = $deployment_link->getPath(); $server_id = $application->destination->server->id; $server_name = $application->destination->server->name; $destination_id = $application->destination->id; if ($server) { $server_id = $server->id; $server_name = $server->name; } if ($destination) { $destination_id = $destination->id; } // Check if there's already a deployment in progress or queued for this application and commit $existing_deployment = ApplicationDeploymentQueue::where('application_id', $application_id) ->where('commit', $commit) ->where('pull_request_id', $pull_request_id) ->whereIn('status', [ApplicationDeploymentStatus::IN_PROGRESS->value, ApplicationDeploymentStatus::QUEUED->value]) ->first(); if ($existing_deployment) { // If force_rebuild is true or rollback is true or no_questions_asked is true, we'll still create a new deployment if (! $force_rebuild && ! $rollback && ! $no_questions_asked) { // Return the existing deployment's details return [ 'status' => 'skipped', 'message' => 'Deployment already queued for this commit.', 'deployment_uuid' => $existing_deployment->deployment_uuid, 'existing_deployment' => $existing_deployment, ]; } } $deployment = ApplicationDeploymentQueue::create([ 'application_id' => $application_id, 'application_name' => $application->name, 'server_id' => $server_id, 'server_name' => $server_name, 'destination_id' => $destination_id, 'deployment_uuid' => $deployment_uuid, 'deployment_url' => $deployment_url, 'pull_request_id' => $pull_request_id, 'force_rebuild' => $force_rebuild, 'is_webhook' => $is_webhook, 'is_api' => $is_api, 'restart_only' => $restart_only, 'commit' => $commit, 'rollback' => $rollback, 'git_type' => $git_type, 'only_this_server' => $only_this_server, ]); if ($no_questions_asked) { ApplicationDeploymentJob::dispatch( application_deployment_queue_id: $deployment->id, ); } elseif (next_queuable($server_id, $application_id, $commit, $pull_request_id)) { ApplicationDeploymentJob::dispatch( application_deployment_queue_id: $deployment->id, ); } return [ 'status' => 'queued', 'message' => 'Deployment queued.', 'deployment_uuid' => $deployment_uuid, ]; } function force_start_deployment(ApplicationDeploymentQueue $deployment) { $deployment->update([ 'status' => ApplicationDeploymentStatus::IN_PROGRESS->value, ]); ApplicationDeploymentJob::dispatch( application_deployment_queue_id: $deployment->id, ); } function queue_next_deployment(Application $application) { $server_id = $application->destination->server_id; $queued_deployments = ApplicationDeploymentQueue::where('server_id', $server_id) ->where('status', ApplicationDeploymentStatus::QUEUED) ->get() ->sortBy('created_at'); foreach ($queued_deployments as $next_deployment) { // Check if this queued deployment can actually run if (next_queuable($next_deployment->server_id, $next_deployment->application_id, $next_deployment->commit, $next_deployment->pull_request_id)) { $next_deployment->update([ 'status' => ApplicationDeploymentStatus::IN_PROGRESS->value, ]); ApplicationDeploymentJob::dispatch( application_deployment_queue_id: $next_deployment->id, ); } } } function next_queuable(string $server_id, string $application_id, string $commit = 'HEAD', int $pull_request_id = 0): bool { // Check if there's already a deployment in progress for this application with the same pull_request_id // This allows normal deployments and PR deployments to run concurrently $in_progress = ApplicationDeploymentQueue::where('application_id', $application_id) ->where('pull_request_id', $pull_request_id) ->where('status', ApplicationDeploymentStatus::IN_PROGRESS->value) ->exists(); if ($in_progress) { return false; } // Check server's concurrent build limit $server = Server::find($server_id); $concurrent_builds = $server->settings->concurrent_builds; $active_deployments = ApplicationDeploymentQueue::where('server_id', $server_id) ->where('status', ApplicationDeploymentStatus::IN_PROGRESS->value) ->count(); if ($active_deployments >= $concurrent_builds) { return false; } return true; } function next_after_cancel(?Server $server = null) { if ($server) { $next_found = ApplicationDeploymentQueue::where('server_id', data_get($server, 'id')) ->where('status', ApplicationDeploymentStatus::QUEUED) ->get() ->sortBy('created_at'); if ($next_found->count() > 0) { foreach ($next_found as $next) { // Use next_queuable to properly check if this deployment can run if (next_queuable($next->server_id, $next->application_id, $next->commit, $next->pull_request_id)) { $next->update([ 'status' => ApplicationDeploymentStatus::IN_PROGRESS->value, ]); ApplicationDeploymentJob::dispatch( application_deployment_queue_id: $next->id, ); } } } } }