mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
Merge remote-tracking branch 'origin/main' into release/v4.5
This commit is contained in:
@@ -3053,6 +3053,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->reuse_commit_message();
|
||||
$this->set_coolify_variables();
|
||||
|
||||
// Restart helper container with actual SOURCE_COMMIT value
|
||||
@@ -3062,6 +3063,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);
|
||||
|
||||
@@ -83,14 +83,16 @@
|
||||
<x-reicon name="projects" class="size-4" />
|
||||
@endif
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="min-w-0 flex-1 self-center">
|
||||
<h3
|
||||
class="truncate text-[13px]! leading-4! font-semibold! text-black dark:text-fg">
|
||||
{{ $project->name }}
|
||||
</h3>
|
||||
<p class="mt-0.5 truncate text-[11px] text-neutral-500 dark:text-fg-faint">
|
||||
{{ $project->description }}
|
||||
</p>
|
||||
@if (filled($project->description))
|
||||
<p class="mt-0.5 truncate text-[11px] text-neutral-500 dark:text-fg-faint">
|
||||
{{ $project->description }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -204,14 +206,16 @@
|
||||
class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.1] dark:bg-white/[0.04] dark:text-fg-dim">
|
||||
<x-reicon name="servers" class="size-4" />
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="min-w-0 flex-1 self-center">
|
||||
<h3
|
||||
class="truncate text-[13px]! leading-4! font-semibold! text-black dark:text-fg">
|
||||
{{ $server->name }}
|
||||
</h3>
|
||||
<p class="mt-0.5 truncate text-[11px] text-neutral-500 dark:text-fg-faint">
|
||||
{{ $server->description }}
|
||||
</p>
|
||||
@if (filled($server->description))
|
||||
<p class="mt-0.5 truncate text-[11px] text-neutral-500 dark:text-fg-faint">
|
||||
{{ $server->description }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
@if ($serverStatusType !== 'success')
|
||||
<span data-tooltip="{{ $serverStatus }}"
|
||||
|
||||
@@ -116,12 +116,13 @@
|
||||
<x-reicon name="projects" class="size-4" />
|
||||
</template>
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="min-w-0 flex-1 self-center">
|
||||
<h2
|
||||
class="truncate text-[13px]! leading-4! font-semibold! text-black dark:text-fg"
|
||||
x-text="project.name"></h2>
|
||||
<p class="mt-0.5 truncate text-[11px] text-neutral-500 dark:text-fg-faint"
|
||||
x-text="project.description || ''"></p>
|
||||
x-show="project.description?.trim()"
|
||||
x-text="project.description"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -147,13 +147,15 @@
|
||||
class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.1] dark:bg-white/[0.04] dark:text-fg-dim">
|
||||
<x-reicon name="servers" class="size-4" />
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="min-w-0 flex-1 self-center">
|
||||
<h2 class="truncate text-[13px]! leading-4! font-semibold! text-black dark:text-fg">
|
||||
{{ $serverRow['name'] }}
|
||||
</h2>
|
||||
<p class="mt-0.5 truncate text-[11px] text-neutral-500 dark:text-fg-faint">
|
||||
{{ $serverRow['description'] }}
|
||||
</p>
|
||||
@if (filled($serverRow['description']))
|
||||
<p class="mt-0.5 truncate text-[11px] text-neutral-500 dark:text-fg-faint">
|
||||
{{ $serverRow['description'] }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
@if ($serverRow['statusType'] !== 'success')
|
||||
<span data-tooltip="{{ $serverRow['status'] }}"
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
class="flex size-9 shrink-0 items-center justify-center rounded-lg bg-neutral-100 text-neutral-500 dark:bg-white/[0.06] dark:text-fg-dim">
|
||||
<x-reicon name="keys" class="size-4" />
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<div class="min-w-0 self-center">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<p class="truncate text-sm font-medium text-neutral-950 dark:text-fg">
|
||||
{{ $privateKey->name }}
|
||||
@@ -77,9 +77,11 @@
|
||||
<x-status-badge status="Active" type="success" />
|
||||
@endif
|
||||
</div>
|
||||
<p class="mt-1 text-xs text-neutral-500 dark:text-fg-dim">
|
||||
{{ $privateKey->description }}
|
||||
</p>
|
||||
@if (filled($privateKey->description))
|
||||
<p class="mt-1 text-xs text-neutral-500 dark:text-fg-dim">
|
||||
{{ $privateKey->description }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex shrink-0 items-center gap-2">
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
href="{{ route('shared-variables.environment.show', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid]) }}" {{ wireNavigate() }}>
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.08] dark:bg-white/[0.04] dark:text-fg-dim"><x-reicon name="layers" class="size-4" /></div>
|
||||
<div class="min-w-0 flex-1"><h3 class="truncate text-[13px]! leading-4! font-semibold! text-black dark:text-fg">{{ $environment->name }}</h3><p class="mt-0.5 truncate text-[11px] text-neutral-500 dark:text-fg-faint">{{ $environment->description }}</p></div>
|
||||
<div class="min-w-0 flex-1 self-center"><h3 class="truncate text-[13px]! leading-4! font-semibold! text-black dark:text-fg">{{ $environment->name }}</h3>@if (filled($environment->description))<p class="mt-0.5 truncate text-[11px] text-neutral-500 dark:text-fg-faint">{{ $environment->description }}</p>@endif</div>
|
||||
</div>
|
||||
</a>
|
||||
@endforeach
|
||||
|
||||
@@ -31,9 +31,11 @@
|
||||
<x-reicon name="projects" class="size-4" />
|
||||
@endif
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="min-w-0 flex-1 self-center">
|
||||
<h2 class="truncate text-[13px]! leading-4! font-semibold! text-black dark:text-fg">{{ $project->name }}</h2>
|
||||
<p class="mt-0.5 truncate text-[11px] text-neutral-500 dark:text-fg-faint">{{ $project->description }}</p>
|
||||
@if (filled($project->description))
|
||||
<p class="mt-0.5 truncate text-[11px] text-neutral-500 dark:text-fg-faint">{{ $project->description }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-auto pt-4 text-[11px] text-neutral-500 dark:text-fg-dim">
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
use App\Jobs\ApplicationDeploymentJob;
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use App\Models\Environment;
|
||||
use App\Models\Project;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use App\Models\Team;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
$team = Team::factory()->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();
|
||||
});
|
||||
Reference in New Issue
Block a user