diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index b93a94a95c..4077d311c9 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -3044,6 +3044,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue } } } + $this->reuse_commit_message(); $this->set_coolify_variables(); // Restart helper container with actual SOURCE_COMMIT value @@ -3053,6 +3054,29 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue } } + /** + * The commit message is read from the cloned repository. Deployments that skip the build or fail + * before the clone reuse the message stored by an earlier deployment of the same commit. + */ + private function reuse_commit_message(): void + { + if (filled($this->application_deployment_queue->commit_message) || $this->shouldResolveBranchHeadCommit()) { + return; + } + + $commitMessage = ApplicationDeploymentQueue::query() + ->where('application_id', $this->application->id) + ->where('commit', $this->commit) + ->whereNotNull('commit_message') + ->where('commit_message', '!=', '') + ->latest('id') + ->value('commit_message'); + + if (filled($commitMessage)) { + $this->application_deployment_queue->update(['commit_message' => $commitMessage]); + } + } + private function shouldResolveBranchHeadCommit(): bool { $commit = trim($this->commit); diff --git a/tests/Feature/DeploymentCommitMessageReuseTest.php b/tests/Feature/DeploymentCommitMessageReuseTest.php new file mode 100644 index 0000000000..52a05e71ad --- /dev/null +++ b/tests/Feature/DeploymentCommitMessageReuseTest.php @@ -0,0 +1,84 @@ +create(); + $this->server = Server::factory()->create(['team_id' => $team->id]); + $destination = StandaloneDocker::where('server_id', $this->server->id)->firstOrFail(); + $project = Project::factory()->create(['team_id' => $team->id]); + $environment = $project->environments()->first() ?? Environment::factory()->create(['project_id' => $project->id]); + + $this->application = Application::factory()->create([ + 'environment_id' => $environment->id, + 'destination_id' => $destination->id, + 'destination_type' => $destination->getMorphClass(), + ]); +}); + +function createCommitMessageDeployment(Application $application, Server $server, string $commit, ?string $commitMessage = null): ApplicationDeploymentQueue +{ + return ApplicationDeploymentQueue::create([ + 'application_id' => $application->id, + 'deployment_uuid' => new_public_id(), + 'server_id' => $server->id, + 'commit' => $commit, + 'commit_message' => $commitMessage, + ]); +} + +function reuseCommitMessage(ApplicationDeploymentQueue $deployment, Application $application, string $commit): void +{ + $reflection = new ReflectionClass(ApplicationDeploymentJob::class); + $job = $reflection->newInstanceWithoutConstructor(); + $reflection->getProperty('application')->setValue($job, $application); + $reflection->getProperty('application_deployment_queue')->setValue($job, $deployment); + $reflection->getProperty('commit')->setValue($job, $commit); + + $reflection->getMethod('reuse_commit_message')->invoke($job); +} + +test('copies the commit message from an earlier deployment of the same commit', function () { + $commit = str_repeat('a', 40); + createCommitMessageDeployment($this->application, $this->server, $commit, 'feat: add portfolio work page'); + $deployment = createCommitMessageDeployment($this->application, $this->server, $commit); + + reuseCommitMessage($deployment, $this->application, $commit); + + expect($deployment->fresh()->commit_message)->toBe('feat: add portfolio work page'); +}); + +test('does not copy a commit message from another commit or application', function () { + $commit = str_repeat('a', 40); + createCommitMessageDeployment($this->application, $this->server, str_repeat('b', 40), 'other commit'); + $otherApplication = Application::factory()->create([ + 'environment_id' => $this->application->environment_id, + 'destination_id' => $this->application->destination_id, + 'destination_type' => $this->application->destination_type, + ]); + createCommitMessageDeployment($otherApplication, $this->server, $commit, 'other application'); + $deployment = createCommitMessageDeployment($this->application, $this->server, $commit); + + reuseCommitMessage($deployment, $this->application, $commit); + + expect($deployment->fresh()->commit_message)->toBeNull(); +}); + +test('does not look up a commit message for an unresolved HEAD commit', function () { + createCommitMessageDeployment($this->application, $this->server, 'HEAD', 'stale message'); + $deployment = createCommitMessageDeployment($this->application, $this->server, 'HEAD'); + + reuseCommitMessage($deployment, $this->application, 'HEAD'); + + expect($deployment->fresh()->commit_message)->toBeNull(); +});