Allow explicit runtime channel selection
This commit is contained in:
@@ -276,8 +276,11 @@ it('updates existing frontend Coolify applications away from legacy Nixpacks det
|
||||
expect($payload['build_pack'])->toBe('dockerfile');
|
||||
expect($payload['ports_exposes'])->toBe('80');
|
||||
expect($payload['dockerfile_location'])->toBe('/Dockerfile.coolify-frontend');
|
||||
expect($payload)->not->toHaveKey('publish_directory');
|
||||
expect($payload)->not->toHaveKey('is_static');
|
||||
expect($payload['install_command'])->toBe('');
|
||||
expect($payload['build_command'])->toBe('');
|
||||
expect($payload['publish_directory'])->toBe('');
|
||||
expect($payload['is_static'])->toBeFalse();
|
||||
expect($payload['is_spa'])->toBeFalse();
|
||||
});
|
||||
|
||||
it('can use the Coolify instance default GitHub App when source targets do not store it yet', function (): void {
|
||||
@@ -654,6 +657,77 @@ it('normalizes channel-prefixed API ingress paths before route dispatch', functi
|
||||
}
|
||||
});
|
||||
|
||||
it('allows explicit runtime selection of any enabled release channel', function (): void {
|
||||
$db = $GLOBALS['db'] ?? null;
|
||||
|
||||
try {
|
||||
$GLOBALS['db'] = new class {
|
||||
public function prepare(string $sql): object
|
||||
{
|
||||
return new class {
|
||||
/** @var array<int,mixed> */
|
||||
private array $params = [];
|
||||
|
||||
public function bind_param(string $types, mixed &...$params): void
|
||||
{
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
public function execute(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function get_result(): object
|
||||
{
|
||||
$slug = (string)($this->params[0] ?? '');
|
||||
|
||||
return new class($slug) {
|
||||
public function __construct(private readonly string $slug)
|
||||
{
|
||||
}
|
||||
|
||||
public function fetch_all(int $mode): array
|
||||
{
|
||||
if ($this->slug !== 'internal') {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [[
|
||||
'id' => 4,
|
||||
'slug' => 'internal',
|
||||
'name' => 'Internal',
|
||||
'enabled' => 1,
|
||||
'default_channel' => 0,
|
||||
'deleted_at' => null,
|
||||
]];
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
$manager = new release_manager();
|
||||
$chooseRuntimeChannel = new ReflectionMethod(release_manager::class, 'chooseRuntimeChannel');
|
||||
$chooseRuntimeChannel->setAccessible(true);
|
||||
|
||||
$channel = $chooseRuntimeChannel->invoke($manager, [
|
||||
'id' => 1,
|
||||
'slug' => 'stable',
|
||||
'enabled' => 1,
|
||||
'default_channel' => 1,
|
||||
], [], 'internal');
|
||||
|
||||
expect($channel['slug'])->toBe('internal');
|
||||
} finally {
|
||||
if ($db === null) {
|
||||
unset($GLOBALS['db']);
|
||||
} else {
|
||||
$GLOBALS['db'] = $db;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('requires non-default release channel runtime URLs and preserves load balancer paths', function (): void {
|
||||
$manager = new release_manager();
|
||||
$availability = new ReflectionMethod(release_manager::class, 'channelAvailability');
|
||||
@@ -808,7 +882,8 @@ it('exposes release version git commit metadata for runtime channel cards', func
|
||||
expect($version['deployed_at'])->toBe('2026-05-19 10:20:00');
|
||||
});
|
||||
|
||||
it('chooses a requested runtime channel only when it is available to the principal', function (): void {
|
||||
it('chooses requested runtime channels from available channels or enabled channel slugs', function (): void {
|
||||
$db = $GLOBALS['db'] ?? null;
|
||||
$manager = new release_manager();
|
||||
$choose = new ReflectionMethod(release_manager::class, 'chooseRuntimeChannel');
|
||||
$choose->setAccessible(true);
|
||||
@@ -826,9 +901,42 @@ it('chooses a requested runtime channel only when it is available to the princip
|
||||
'default_channel' => 0,
|
||||
];
|
||||
|
||||
expect($choose->invoke($manager, $stable, [$stable, $canary], 'canary'))->toBe($canary);
|
||||
expect($choose->invoke($manager, $stable, [$stable, $canary], 'unknown'))->toBe($stable);
|
||||
expect($choose->invoke($manager, $canary, [$stable, $canary], ''))->toBe($canary);
|
||||
try {
|
||||
$GLOBALS['db'] = new class {
|
||||
public function prepare(string $sql): object
|
||||
{
|
||||
return new class {
|
||||
public function bind_param(string $types, mixed &...$params): void
|
||||
{
|
||||
}
|
||||
|
||||
public function execute(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function get_result(): object
|
||||
{
|
||||
return new class {
|
||||
public function fetch_all(int $mode): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
expect($choose->invoke($manager, $stable, [$stable, $canary], 'canary'))->toBe($canary);
|
||||
expect($choose->invoke($manager, $stable, [$stable, $canary], 'unknown'))->toBe($stable);
|
||||
expect($choose->invoke($manager, $canary, [$stable, $canary], ''))->toBe($canary);
|
||||
} finally {
|
||||
if ($db === null) {
|
||||
unset($GLOBALS['db']);
|
||||
} else {
|
||||
$GLOBALS['db'] = $db;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('normalizes release assignment subject suggestions without leaking private fields', function (): void {
|
||||
|
||||
Reference in New Issue
Block a user