mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-14 20:17:05 +00:00
Merge remote-tracking branch 'origin/next' into mcp-server-instance-toggle
This commit is contained in:
commit
d057ce5172
8 files changed
+237
-18
No files matched your search
@@ -0,0 +1,107 @@
|
||||
<?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;
|
||||
use Illuminate\Support\Facades\Bus;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
Bus::fake([ApplicationDeploymentJob::class]);
|
||||
|
||||
$this->team = Team::factory()->create();
|
||||
$this->server = Server::factory()->create(['team_id' => $this->team->id]);
|
||||
$this->destination = StandaloneDocker::factory()->create([
|
||||
'server_id' => $this->server->id,
|
||||
'network' => 'test-network-'.fake()->unique()->word(),
|
||||
]);
|
||||
$this->project = Project::factory()->create(['team_id' => $this->team->id]);
|
||||
$this->environment = Environment::factory()->create(['project_id' => $this->project->id]);
|
||||
});
|
||||
|
||||
function makeApplication(int $environmentId, int $destinationId, ?string $gitCommitSha): Application
|
||||
{
|
||||
$attributes = [
|
||||
'environment_id' => $environmentId,
|
||||
'destination_id' => $destinationId,
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
];
|
||||
|
||||
if ($gitCommitSha !== null) {
|
||||
$attributes['git_commit_sha'] = $gitCommitSha;
|
||||
}
|
||||
|
||||
return Application::factory()->create($attributes);
|
||||
}
|
||||
|
||||
describe('queue_application_deployment commit resolution', function () {
|
||||
test('uses application git_commit_sha when commit parameter omitted', function () {
|
||||
$pinnedSha = 'abc123def456abc123def456abc123def456abc1';
|
||||
$application = makeApplication($this->environment->id, $this->destination->id, $pinnedSha);
|
||||
|
||||
$result = queue_application_deployment(
|
||||
application: $application,
|
||||
deployment_uuid: 'test-deploy-uuid-1',
|
||||
);
|
||||
|
||||
expect($result['status'])->toBe('queued');
|
||||
|
||||
$deployment = ApplicationDeploymentQueue::where('deployment_uuid', 'test-deploy-uuid-1')->first();
|
||||
expect($deployment)->not->toBeNull();
|
||||
expect($deployment->commit)->toBe($pinnedSha);
|
||||
});
|
||||
|
||||
test('falls back to HEAD when both commit parameter and git_commit_sha are unset', function () {
|
||||
$application = makeApplication($this->environment->id, $this->destination->id, 'HEAD');
|
||||
|
||||
$result = queue_application_deployment(
|
||||
application: $application,
|
||||
deployment_uuid: 'test-deploy-uuid-2',
|
||||
);
|
||||
|
||||
expect($result['status'])->toBe('queued');
|
||||
|
||||
$deployment = ApplicationDeploymentQueue::where('deployment_uuid', 'test-deploy-uuid-2')->first();
|
||||
expect($deployment->commit)->toBe('HEAD');
|
||||
});
|
||||
|
||||
test('explicit commit parameter overrides application git_commit_sha', function () {
|
||||
$pinnedSha = 'abc123def456abc123def456abc123def456abc1';
|
||||
$webhookSha = '111222333444555666777888999000aaabbbccc1';
|
||||
$application = makeApplication($this->environment->id, $this->destination->id, $pinnedSha);
|
||||
|
||||
$result = queue_application_deployment(
|
||||
application: $application,
|
||||
deployment_uuid: 'test-deploy-uuid-3',
|
||||
commit: $webhookSha,
|
||||
);
|
||||
|
||||
expect($result['status'])->toBe('queued');
|
||||
|
||||
$deployment = ApplicationDeploymentQueue::where('deployment_uuid', 'test-deploy-uuid-3')->first();
|
||||
expect($deployment->commit)->toBe($webhookSha);
|
||||
});
|
||||
|
||||
test('treats empty string commit parameter as unset and uses git_commit_sha', function () {
|
||||
$pinnedSha = 'abc123def456abc123def456abc123def456abc1';
|
||||
$application = makeApplication($this->environment->id, $this->destination->id, $pinnedSha);
|
||||
|
||||
$result = queue_application_deployment(
|
||||
application: $application,
|
||||
deployment_uuid: 'test-deploy-uuid-4',
|
||||
commit: '',
|
||||
);
|
||||
|
||||
expect($result['status'])->toBe('queued');
|
||||
|
||||
$deployment = ApplicationDeploymentQueue::where('deployment_uuid', 'test-deploy-uuid-4')->first();
|
||||
expect($deployment->commit)->toBe($pinnedSha);
|
||||
});
|
||||
});
|
||||
@@ -4,6 +4,7 @@ use App\Models\Server;
|
||||
use App\Models\ServerSetting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
@@ -78,11 +79,73 @@ describe('ServerSetting::isValidSentinelToken', function () {
|
||||
expect(ServerSetting::isValidSentinelToken(''))->toBeFalse();
|
||||
});
|
||||
|
||||
it('returns false for null sentinel token', function () {
|
||||
expect(ServerSetting::isValidSentinelToken(null))->toBeFalse();
|
||||
});
|
||||
|
||||
it('rejects the reported PoC payload', function () {
|
||||
expect(ServerSetting::isValidSentinelToken('abc" ; id >/tmp/coolify_poc_sentinel ; echo "'))->toBeFalse();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ServerSetting::ensureValidSentinelToken', function () {
|
||||
it('regenerates empty sentinel token via ensureValidSentinelToken', function () {
|
||||
$settings = $this->server->settings;
|
||||
DB::table('server_settings')->where('id', $settings->id)->update(['sentinel_token' => '']);
|
||||
|
||||
$settings->refresh();
|
||||
$token = $settings->ensureValidSentinelToken();
|
||||
|
||||
expect($token)->not->toBeEmpty();
|
||||
expect(ServerSetting::isValidSentinelToken($token))->toBeTrue();
|
||||
expect($settings->fresh()->sentinel_token)->toBe($token);
|
||||
});
|
||||
|
||||
it('regenerates token when stored value cannot be decrypted', function () {
|
||||
$settings = $this->server->settings;
|
||||
DB::table('server_settings')->where('id', $settings->id)->update(['sentinel_token' => 'not-encrypted-junk']);
|
||||
|
||||
$settings->refresh();
|
||||
$token = $settings->ensureValidSentinelToken();
|
||||
|
||||
expect(ServerSetting::isValidSentinelToken($token))->toBeTrue();
|
||||
expect($settings->fresh()->sentinel_token)->toBe($token);
|
||||
});
|
||||
|
||||
it('returns existing valid token without regenerating', function () {
|
||||
$settings = $this->server->settings;
|
||||
$original = $settings->sentinel_token;
|
||||
|
||||
$token = $settings->ensureValidSentinelToken();
|
||||
|
||||
expect($token)->toBe($original);
|
||||
});
|
||||
|
||||
it('throws RuntimeException only when regeneration also fails', function () {
|
||||
$settings = $this->server->settings;
|
||||
DB::table('server_settings')->where('id', $settings->id)->update(['sentinel_token' => '']);
|
||||
|
||||
$stub = new class extends ServerSetting
|
||||
{
|
||||
protected $table = 'server_settings';
|
||||
|
||||
public function generateSentinelToken(bool $save = true, bool $ignoreEvent = false): string
|
||||
{
|
||||
DB::table('server_settings')->where('id', $this->id)->update([
|
||||
'sentinel_token' => encrypt('invalid token with spaces!'),
|
||||
]);
|
||||
|
||||
return '';
|
||||
}
|
||||
};
|
||||
$stub->setRawAttributes($settings->fresh()->getAttributes(), true);
|
||||
$stub->exists = true;
|
||||
|
||||
expect(fn () => $stub->ensureValidSentinelToken())
|
||||
->toThrow(RuntimeException::class, 'Sentinel token invalid after regeneration');
|
||||
});
|
||||
});
|
||||
|
||||
describe('generated sentinel tokens are valid', function () {
|
||||
it('generates tokens that pass format validation', function () {
|
||||
$settings = $this->server->settings;
|
||||
@@ -92,4 +155,11 @@ describe('generated sentinel tokens are valid', function () {
|
||||
expect($token)->not->toBeEmpty();
|
||||
expect(ServerSetting::isValidSentinelToken($token))->toBeTrue();
|
||||
});
|
||||
|
||||
it('returns the same value the cast reads back', function () {
|
||||
$settings = $this->server->settings;
|
||||
$returned = $settings->generateSentinelToken(save: true, ignoreEvent: true);
|
||||
|
||||
expect($settings->fresh()->sentinel_token)->toBe($returned);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user