feat(deployment): implement cancellation checks during deployment process to enhance user control and prevent unnecessary execution

This commit is contained in:
Andras Bacsai
2025-09-16 13:40:51 +02:00
parent f9ed02a0b7
commit 9e8fb36bc8
3 changed files with 84 additions and 6 deletions

View File

@@ -250,6 +250,14 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
public function handle(): void
{
// Check if deployment was cancelled before we even started
$this->application_deployment_queue->refresh();
if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::CANCELLED_BY_USER->value) {
$this->application_deployment_queue->addLogEntry('Deployment was cancelled before starting.');
return;
}
$this->application_deployment_queue->update([
'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
'horizon_job_worker' => gethostname(),
@@ -1146,6 +1154,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
private function rolling_update()
{
$this->checkForCancellation();
if ($this->server->isSwarm()) {
$this->application_deployment_queue->addLogEntry('Rolling update started.');
$this->execute_remote_command(
@@ -1342,6 +1351,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
private function prepare_builder_image()
{
$this->checkForCancellation();
$settings = instanceSettings();
$helperImage = config('constants.coolify.helper_image');
$helperImage = "{$helperImage}:{$settings->helper_version}";
@@ -1813,6 +1823,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
private function generate_compose_file()
{
$this->checkForCancellation();
$this->create_workdir();
$ports = $this->application->main_port();
$persistent_storages = $this->generate_local_persistent_volumes();
@@ -2546,8 +2557,23 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
throw new RuntimeException('Post-deployment command: Could not find a valid container. Is the container name correct?');
}
/**
* Check if the deployment was cancelled and abort if it was
*/
private function checkForCancellation(): void
{
$this->application_deployment_queue->refresh();
if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::CANCELLED_BY_USER->value) {
$this->application_deployment_queue->addLogEntry('Deployment cancelled by user, stopping execution.');
throw new \RuntimeException('Deployment cancelled by user', 69420);
}
}
private function next(string $status)
{
// Refresh to get latest status
$this->application_deployment_queue->refresh();
// Never allow changing status from FAILED or CANCELLED_BY_USER to anything else
if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::FAILED->value) {
$this->application->environment->project->team?->notify(new DeploymentFailed($this->application, $this->deployment_uuid, $this->preview));
@@ -2555,7 +2581,9 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
return;
}
if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::CANCELLED_BY_USER->value) {
return;
// Job was cancelled, stop execution
$this->application_deployment_queue->addLogEntry('Deployment cancelled by user, stopping execution.');
throw new \RuntimeException('Deployment cancelled by user', 69420);
}
$this->application_deployment_queue->update([