Merge remote-tracking branch 'origin/next' into 10444-database-healthchecks

This commit is contained in:
Andras Bacsai 2026-06-01 06:55:40 +02:00
commit 4f053bf5b4
4 changed files with 80 additions and 4 deletions

View file

@ -18,9 +18,13 @@ public function handle()
if ($servers->count() > 0) {
foreach ($servers as $server) {
echo "Cleanup unreachable server ($server->id) with name $server->name";
$server->update([
'ip' => '1.2.3.4',
]);
if (isCloud()) {
$server->update([
'ip' => '1.2.3.4',
]);
} else {
$server->forceDisableServer();
}
}
}
}

View file

@ -81,6 +81,10 @@ protected function canonicalManualWebhookRepository(?string $gitRepository): ?st
$path = data_get($parts, 'path');
} elseif (Str::startsWith($gitRepository, 'git@') && str_contains($gitRepository, ':')) {
$path = Str::after($gitRepository, ':');
// scp-style SSH URLs embed a custom port as "git@host:2222/owner/repo".
// Strip the leading numeric port segment so the path matches the webhook
// payload's owner/repo, consistent with convertGitUrl() in shared.php.
$path = preg_replace('#^\d+/#', '', $path) ?? $path;
} else {
$path = $gitRepository;
}

View file

@ -6,7 +6,30 @@
uses(RefreshDatabase::class);
it('cleans up servers with unreachable_count >= 3 after 7 days', function () {
it('disables (non-destructively) self-hosted servers with unreachable_count >= 3 after 7 days', function () {
config(['constants.coolify.self_hosted' => true]);
$team = Team::factory()->create();
$server = Server::factory()->create([
'team_id' => $team->id,
'unreachable_count' => 50,
'unreachable_notification_sent' => true,
'updated_at' => now()->subDays(8),
]);
$originalIp = (string) $server->ip;
$this->artisan('cleanup:unreachable-servers')->assertSuccessful();
$server->refresh();
// IP must be preserved — never overwritten on self-hosted.
expect($server->ip)->toBe($originalIp);
expect($server->settings->force_disabled)->toBeTrue();
});
it('overwrites the IP with 1.2.3.4 on cloud for servers with unreachable_count >= 3 after 7 days', function () {
config(['constants.coolify.self_hosted' => false]);
$team = Team::factory()->create();
$server = Server::factory()->create([
'team_id' => $team->id,
@ -36,6 +59,7 @@
$server->refresh();
expect($server->ip)->toBe($originalIp);
expect($server->settings->force_disabled)->toBeFalse();
});
it('does not clean up servers updated within 7 days', function () {
@ -53,6 +77,7 @@
$server->refresh();
expect($server->ip)->toBe($originalIp);
expect($server->settings->force_disabled)->toBeFalse();
});
it('does not clean up servers without notification sent', function () {
@ -70,4 +95,5 @@
$server->refresh();
expect($server->ip)->toBe($originalIp);
expect($server->settings->force_disabled)->toBeFalse();
});

View file

@ -509,6 +509,48 @@ function createApplicationWithWebhook(string $repo = 'test-org/test-repo', strin
expect($response->getContent())->not->toContain('No applications found');
});
test('gitlab matches scp-style ssh repository URL with custom port', function () {
$app = createApplicationWithWebhook(overrides: [
'git_repository' => 'git@gitlab.example.com:2222/services/xyz.git',
'git_branch' => 'master',
]);
$secret = $app->manual_webhook_secret_gitlab;
$response = $this->postJson('/webhooks/source/gitlab/events/manual', [
'object_kind' => 'push',
'ref' => 'refs/heads/master',
'project' => ['path_with_namespace' => 'services/xyz'],
'after' => 'abc123',
'commits' => [],
], [
'X-Gitlab-Token' => $secret,
]);
$response->assertOk();
expect($response->getContent())->not->toContain('No applications found');
});
test('gitlab matches scp-style ssh repository URL without port', function () {
$app = createApplicationWithWebhook(overrides: [
'git_repository' => 'git@gitlab.example.com:services/xyz.git',
'git_branch' => 'master',
]);
$secret = $app->manual_webhook_secret_gitlab;
$response = $this->postJson('/webhooks/source/gitlab/events/manual', [
'object_kind' => 'push',
'ref' => 'refs/heads/master',
'project' => ['path_with_namespace' => 'services/xyz'],
'after' => 'abc123',
'commits' => [],
], [
'X-Gitlab-Token' => $secret,
]);
$response->assertOk();
expect($response->getContent())->not->toContain('No applications found');
});
test('github matches repository case-insensitively', function () {
$app = createApplicationWithWebhook(overrides: [
'git_repository' => 'https://github.com/Test-Org/Test-Repo.git',