feat(dev): add Lima testing server fixtures (#10844)
This commit is contained in:
parent
bf37db3b5f
commit
58f6f9e05b
14 changed files with 600 additions and 38 deletions
|
|
@ -219,8 +219,13 @@ # Development Guides
|
|||
## Local Development
|
||||
To build and run Coolify locally, see: [Development](./DEVELOPMENT.md)
|
||||
|
||||
### macOS Development with Lima
|
||||
Mac users can use [Lima](https://lima-vm.io/) to run a lightweight Linux virtual machine for local Coolify development. This is useful if you prefer a Linux-based Docker environment on macOS.
|
||||
|
||||
After creating and starting a Lima VM, run the normal local development commands from inside the VM as described in [Development](./DEVELOPMENT.md).
|
||||
|
||||
## Adding a New Service
|
||||
To add a new one-click service, follow: https://coolify.io/docs/get-started/contribute/service
|
||||
|
||||
## Contributing to Documentation
|
||||
To contribute to documentation, see: https://coolify.io/docs/get-started/contribute/documentation
|
||||
To contribute to documentation, see: https://coolify.io/docs/get-started/contribute/documentation
|
||||
|
|
|
|||
|
|
@ -537,6 +537,20 @@ public function loadHetznerTokens(): void
|
|||
->get();
|
||||
}
|
||||
|
||||
#[Computed]
|
||||
public function limaStartCommand(): ?string
|
||||
{
|
||||
if (! isDev()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return match ($this->server->uuid) {
|
||||
'lima-ubuntu-2404' => 'limactl start --yes --name=coolify-lima-ubuntu-2404 docker/lima/ubuntu-2404.yaml',
|
||||
'lima-ubuntu-2604' => 'limactl start --yes --name=coolify-lima-ubuntu-2604 docker/lima/ubuntu-2604.yaml',
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
public function searchHetznerServer(): void
|
||||
{
|
||||
$this->hetznerSearchError = null;
|
||||
|
|
|
|||
|
|
@ -20,14 +20,33 @@ class DevelopmentRailpackExamplesSeeder extends Seeder
|
|||
{
|
||||
public const PROJECT_UUID = 'railpack-examples';
|
||||
|
||||
public const ENVIRONMENT_UUID = 'railpack-examples-production';
|
||||
|
||||
public const GIT_REPOSITORY = 'coollabsio/coolify-examples';
|
||||
|
||||
public const GIT_BRANCH = 'next';
|
||||
|
||||
public const REPOSITORY_PROJECT_ID = 603035348;
|
||||
|
||||
public const LIMA_SERVERS = [
|
||||
[
|
||||
'server_uuid' => 'lima-ubuntu-2404',
|
||||
'server_name' => 'lima-ubuntu-2404',
|
||||
'port' => 2222,
|
||||
'environment_name' => 'ubuntu24',
|
||||
'environment_uuid' => 'railpack-examples-ubuntu24',
|
||||
'uuid_prefix' => 'ubuntu24-',
|
||||
],
|
||||
[
|
||||
'server_uuid' => 'lima-ubuntu-2604',
|
||||
'server_name' => 'lima-ubuntu-2604',
|
||||
'port' => 2223,
|
||||
'environment_name' => 'ubuntu26',
|
||||
'environment_uuid' => 'railpack-examples-ubuntu26',
|
||||
'uuid_prefix' => 'ubuntu26-',
|
||||
],
|
||||
];
|
||||
|
||||
private const LIMA_SENTINEL_URL = 'http://host.lima.internal:8000';
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
if (! $this->isDevelopmentEnvironment()) {
|
||||
|
|
@ -37,16 +56,22 @@ public function run(): void
|
|||
}
|
||||
|
||||
$this->ensureDevelopmentPrerequisitesExist();
|
||||
$destination = StandaloneDocker::query()->find(0);
|
||||
|
||||
if (! $destination) {
|
||||
if (! StandaloneDocker::query()->find(0)) {
|
||||
throw new RuntimeException('StandaloneDocker with id=0 is required before running DevelopmentRailpackExamplesSeeder.');
|
||||
}
|
||||
|
||||
$environment = $this->prepareEnvironment();
|
||||
$this->cleanupLegacyLimaProjects();
|
||||
$this->cleanupLegacyProductionExamples();
|
||||
|
||||
foreach (self::examples() as $example) {
|
||||
$this->upsertApplication($environment, $destination, $example);
|
||||
foreach (self::LIMA_SERVERS as $limaServer) {
|
||||
$this->seedEnvironment(
|
||||
environmentUuid: $limaServer['environment_uuid'],
|
||||
environmentName: $limaServer['environment_name'],
|
||||
destination: $this->limaDestination($limaServer['server_uuid']),
|
||||
uuidPrefix: $limaServer['uuid_prefix'],
|
||||
nameSuffix: " ({$limaServer['environment_name']})",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -440,6 +465,37 @@ private function ensureDevelopmentPrerequisitesExist(): void
|
|||
],
|
||||
);
|
||||
|
||||
foreach (self::LIMA_SERVERS as $limaServer) {
|
||||
$server = Server::query()->firstOrCreate(
|
||||
['uuid' => $limaServer['server_uuid']],
|
||||
[
|
||||
'name' => $limaServer['server_name'],
|
||||
'description' => 'This is a Lima VM for local development testing',
|
||||
'ip' => 'host.docker.internal',
|
||||
'port' => $limaServer['port'],
|
||||
'team_id' => 0,
|
||||
'private_key_id' => 1,
|
||||
'proxy' => [
|
||||
'type' => ProxyTypes::TRAEFIK->value,
|
||||
'status' => ProxyStatus::EXITED->value,
|
||||
],
|
||||
],
|
||||
);
|
||||
|
||||
$server->settings->forceFill([
|
||||
'sentinel_custom_url' => self::LIMA_SENTINEL_URL,
|
||||
])->saveQuietly();
|
||||
|
||||
StandaloneDocker::query()->firstOrCreate(
|
||||
['server_id' => $server->id],
|
||||
[
|
||||
'uuid' => "{$limaServer['server_uuid']}-docker",
|
||||
'name' => "{$limaServer['server_name']} Docker",
|
||||
'network' => 'coolify',
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
StandaloneDocker::query()->firstOrCreate(
|
||||
['id' => 0],
|
||||
[
|
||||
|
|
@ -489,7 +545,71 @@ private function isDevelopmentEnvironment(): bool
|
|||
return in_array(config('app.env'), ['local', 'development', 'dev'], true);
|
||||
}
|
||||
|
||||
private function prepareEnvironment(): Environment
|
||||
private function limaDestination(string $serverUuid): StandaloneDocker
|
||||
{
|
||||
$limaDestination = Server::query()
|
||||
->where('uuid', $serverUuid)
|
||||
->first()
|
||||
?->standaloneDockers()
|
||||
->first();
|
||||
|
||||
if (! $limaDestination) {
|
||||
throw new RuntimeException("Lima StandaloneDocker destination is required for {$serverUuid} before running DevelopmentRailpackExamplesSeeder.");
|
||||
}
|
||||
|
||||
return $limaDestination;
|
||||
}
|
||||
|
||||
private function cleanupLegacyLimaProjects(): void
|
||||
{
|
||||
Project::query()
|
||||
->whereIn('uuid', [
|
||||
'railpack-examples-lima-ubuntu-2404',
|
||||
'railpack-examples-lima-ubuntu-2604',
|
||||
])
|
||||
->get()
|
||||
->each(function (Project $project): void {
|
||||
Application::withTrashed()
|
||||
->whereIn('environment_id', $project->environments()->pluck('id'))
|
||||
->get()
|
||||
->each
|
||||
->forceDelete();
|
||||
|
||||
$project->delete();
|
||||
});
|
||||
}
|
||||
|
||||
private function cleanupLegacyProductionExamples(): void
|
||||
{
|
||||
$project = Project::query()->where('uuid', self::PROJECT_UUID)->first();
|
||||
|
||||
if (! $project) {
|
||||
return;
|
||||
}
|
||||
|
||||
Application::withTrashed()
|
||||
->whereIn('environment_id', $project->environments()->pluck('id'))
|
||||
->whereIn('uuid', collect(self::examples())->pluck('uuid'))
|
||||
->get()
|
||||
->each
|
||||
->forceDelete();
|
||||
}
|
||||
|
||||
private function seedEnvironment(
|
||||
string $environmentUuid,
|
||||
string $environmentName,
|
||||
StandaloneDocker $destination,
|
||||
string $uuidPrefix = '',
|
||||
string $nameSuffix = '',
|
||||
): void {
|
||||
$environment = $this->prepareEnvironment($environmentUuid, $environmentName);
|
||||
|
||||
foreach (self::examples() as $example) {
|
||||
$this->upsertApplication($environment, $destination, $example, $uuidPrefix, $nameSuffix);
|
||||
}
|
||||
}
|
||||
|
||||
private function prepareEnvironment(string $environmentUuid, string $environmentName): Environment
|
||||
{
|
||||
$project = Project::query()->firstOrNew(['uuid' => self::PROJECT_UUID]);
|
||||
$project->fill([
|
||||
|
|
@ -499,17 +619,29 @@ private function prepareEnvironment(): Environment
|
|||
]);
|
||||
$project->save();
|
||||
|
||||
$environment = $project->environments()->first();
|
||||
$environment = $project->environments()
|
||||
->where(function ($query) use ($environmentName, $environmentUuid): void {
|
||||
$query
|
||||
->where('name', $environmentName)
|
||||
->orWhere('uuid', $environmentUuid);
|
||||
})
|
||||
->first();
|
||||
|
||||
$existingEnvironment = $project->environments()->first();
|
||||
|
||||
if (! $environment && $project->environments()->count() === 1 && $existingEnvironment?->name === 'production') {
|
||||
$environment = $existingEnvironment;
|
||||
}
|
||||
|
||||
if (! $environment) {
|
||||
$environment = $project->environments()->create([
|
||||
'name' => 'production',
|
||||
'uuid' => self::ENVIRONMENT_UUID,
|
||||
'name' => $environmentName,
|
||||
'uuid' => $environmentUuid,
|
||||
]);
|
||||
} else {
|
||||
$environment->update([
|
||||
'name' => 'production',
|
||||
'uuid' => self::ENVIRONMENT_UUID,
|
||||
'name' => $environmentName,
|
||||
'uuid' => $environmentUuid,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -519,13 +651,15 @@ private function prepareEnvironment(): Environment
|
|||
/**
|
||||
* @param array<string, mixed> $example
|
||||
*/
|
||||
private function upsertApplication(Environment $environment, StandaloneDocker $destination, array $example): void
|
||||
private function upsertApplication(Environment $environment, StandaloneDocker $destination, array $example, string $uuidPrefix = '', string $nameSuffix = ''): void
|
||||
{
|
||||
$application = Application::withTrashed()->firstOrNew(['uuid' => $example['uuid']]);
|
||||
$uuid = $uuidPrefix.$example['uuid'];
|
||||
$name = $example['name'].$nameSuffix;
|
||||
$application = Application::withTrashed()->firstOrNew(['uuid' => $uuid]);
|
||||
$application->fill([
|
||||
'name' => $example['name'],
|
||||
'description' => $example['name'],
|
||||
'fqdn' => "http://{$example['uuid']}.127.0.0.1.sslip.io",
|
||||
'name' => $name,
|
||||
'description' => $name,
|
||||
'fqdn' => "http://{$uuid}.127.0.0.1.sslip.io",
|
||||
'repository_project_id' => $example['repository_project_id'] ?? self::REPOSITORY_PROJECT_ID,
|
||||
'git_repository' => $example['git_repository'] ?? self::GIT_REPOSITORY,
|
||||
'git_branch' => $example['git_branch'] ?? self::GIT_BRANCH,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@
|
|||
|
||||
class ProjectSeeder extends Seeder
|
||||
{
|
||||
private const LIMA_ENVIRONMENTS = [
|
||||
['name' => 'ubuntu24', 'uuid' => 'ubuntu24'],
|
||||
['name' => 'ubuntu26', 'uuid' => 'ubuntu26'],
|
||||
];
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$project = Project::create([
|
||||
|
|
@ -16,7 +21,14 @@ public function run(): void
|
|||
'team_id' => 0,
|
||||
]);
|
||||
|
||||
// Update the auto-created environment with a deterministic UUID
|
||||
$project->environments()->first()->update(['uuid' => 'production']);
|
||||
foreach (self::LIMA_ENVIRONMENTS as $index => $environment) {
|
||||
if ($index === 0) {
|
||||
$project->environments()->first()->update($environment);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$project->environments()->create($environment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,13 @@
|
|||
|
||||
class ServerSeeder extends Seeder
|
||||
{
|
||||
private const LIMA_SENTINEL_URL = 'http://host.lima.internal:8000';
|
||||
|
||||
private const LIMA_SERVERS = [
|
||||
['uuid' => 'lima-ubuntu-2404', 'name' => 'lima-ubuntu-2404', 'port' => 2222],
|
||||
['uuid' => 'lima-ubuntu-2604', 'name' => 'lima-ubuntu-2604', 'port' => 2223],
|
||||
];
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
Server::create([
|
||||
|
|
@ -24,5 +31,25 @@ public function run(): void
|
|||
'status' => ProxyStatus::EXITED->value,
|
||||
],
|
||||
]);
|
||||
|
||||
foreach (self::LIMA_SERVERS as $limaServer) {
|
||||
$server = Server::create([
|
||||
'uuid' => $limaServer['uuid'],
|
||||
'name' => $limaServer['name'],
|
||||
'description' => 'This is a Lima VM for local development testing',
|
||||
'ip' => 'host.docker.internal',
|
||||
'port' => $limaServer['port'],
|
||||
'team_id' => 0,
|
||||
'private_key_id' => 1,
|
||||
'proxy' => [
|
||||
'type' => ProxyTypes::TRAEFIK->value,
|
||||
'status' => ProxyStatus::EXITED->value,
|
||||
],
|
||||
]);
|
||||
|
||||
$server->settings->forceFill([
|
||||
'sentinel_custom_url' => self::LIMA_SENTINEL_URL,
|
||||
])->saveQuietly();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ services:
|
|||
- GROUP_ID=${GROUPID:-1000}
|
||||
ports:
|
||||
- "${APP_PORT:-8000}:8080"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
environment:
|
||||
AUTORUN_ENABLED: false
|
||||
PUSHER_HOST: "${PUSHER_HOST}"
|
||||
|
|
@ -70,6 +72,8 @@ services:
|
|||
ports:
|
||||
- "${FORWARD_SOKETI_PORT:-6001}:6001"
|
||||
- "6002:6002"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
volumes:
|
||||
- ./storage:/var/www/html/storage
|
||||
- ./docker/coolify-realtime/terminal-server.js:/terminal/terminal-server.js
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ services:
|
|||
- GROUP_ID=${GROUPID:-1000}
|
||||
ports:
|
||||
- "${APP_PORT:-8000}:8080"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
environment:
|
||||
AUTORUN_ENABLED: false
|
||||
PUSHER_HOST: "${PUSHER_HOST}"
|
||||
|
|
@ -70,6 +72,8 @@ services:
|
|||
ports:
|
||||
- "${FORWARD_SOKETI_PORT:-6001}:6001"
|
||||
- "6002:6002"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
volumes:
|
||||
- ./storage:/var/www/html/storage
|
||||
- ./docker/coolify-realtime/terminal-server.js:/terminal/terminal-server.js
|
||||
|
|
|
|||
35
docker/lima/ubuntu-2404.yaml
Normal file
35
docker/lima/ubuntu-2404.yaml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
images:
|
||||
- location: https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-amd64.img
|
||||
arch: x86_64
|
||||
- location: https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-arm64.img
|
||||
arch: aarch64
|
||||
|
||||
cpus: 2
|
||||
memory: 2GiB
|
||||
disk: 20GiB
|
||||
|
||||
containerd:
|
||||
system: false
|
||||
user: false
|
||||
|
||||
mounts: []
|
||||
|
||||
ssh:
|
||||
localPort: 2222
|
||||
loadDotSSHPubKeys: false
|
||||
|
||||
provision:
|
||||
- mode: system
|
||||
script: |
|
||||
#!/bin/bash
|
||||
set -euxo pipefail
|
||||
|
||||
install -d -m 700 /root/.ssh
|
||||
cat >/root/.ssh/authorized_keys <<'EOF'
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFuGmoeGq/pojrsyP1pszcNVuZx9iFkCELtxrh31QJ68 sail@76ff66d2e2dd
|
||||
EOF
|
||||
chmod 600 /root/.ssh/authorized_keys
|
||||
|
||||
sed -i 's/^#\?PermitRootLogin .*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
|
||||
sed -i 's/^#\?PubkeyAuthentication .*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
|
||||
systemctl restart ssh
|
||||
35
docker/lima/ubuntu-2604.yaml
Normal file
35
docker/lima/ubuntu-2604.yaml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
images:
|
||||
- location: https://cloud-images.ubuntu.com/releases/26.04/release/ubuntu-26.04-server-cloudimg-amd64.img
|
||||
arch: x86_64
|
||||
- location: https://cloud-images.ubuntu.com/releases/26.04/release/ubuntu-26.04-server-cloudimg-arm64.img
|
||||
arch: aarch64
|
||||
|
||||
cpus: 2
|
||||
memory: 2GiB
|
||||
disk: 20GiB
|
||||
|
||||
containerd:
|
||||
system: false
|
||||
user: false
|
||||
|
||||
mounts: []
|
||||
|
||||
ssh:
|
||||
localPort: 2223
|
||||
loadDotSSHPubKeys: false
|
||||
|
||||
provision:
|
||||
- mode: system
|
||||
script: |
|
||||
#!/bin/bash
|
||||
set -euxo pipefail
|
||||
|
||||
install -d -m 700 /root/.ssh
|
||||
cat >/root/.ssh/authorized_keys <<'EOF'
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFuGmoeGq/pojrsyP1pszcNVuZx9iFkCELtxrh31QJ68 sail@76ff66d2e2dd
|
||||
EOF
|
||||
chmod 600 /root/.ssh/authorized_keys
|
||||
|
||||
sed -i 's/^#\?PermitRootLogin .*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
|
||||
sed -i 's/^#\?PubkeyAuthentication .*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
|
||||
systemctl restart ssh
|
||||
|
|
@ -120,6 +120,19 @@ class="flex items-center gap-1.5 px-2 py-1 text-xs font-semibold rounded bg-warn
|
|||
@else
|
||||
You can't use this server until it is validated.
|
||||
@endif
|
||||
@if ($this->limaStartCommand)
|
||||
<div
|
||||
class="mt-4 rounded border border-coolgray-200 bg-coolgray-100 p-3 text-sm dark:border-coolgray-300 dark:bg-coolgray-100">
|
||||
<div class="font-semibold">Start this Lima VM locally</div>
|
||||
<div class="mt-1 dark:text-neutral-400">
|
||||
Run this from the Coolify repository root before validating this server:
|
||||
</div>
|
||||
<code
|
||||
class="mt-2 block overflow-x-auto rounded bg-black px-3 py-2 font-mono text-xs text-white">
|
||||
{{ $this->limaStartCommand }}
|
||||
</code>
|
||||
</div>
|
||||
@endif
|
||||
@if ($isValidating)
|
||||
<div x-data="{ slideOverOpen: true }">
|
||||
<x-slide-over closeWithX fullScreen>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
use Database\Seeders\TeamSeeder;
|
||||
use Database\Seeders\UserSeeder;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
|
|
@ -33,6 +34,11 @@ function seedRailpackExamplePrerequisites(): void
|
|||
]);
|
||||
}
|
||||
|
||||
function limaServers(): Collection
|
||||
{
|
||||
return collect(DevelopmentRailpackExamplesSeeder::LIMA_SERVERS);
|
||||
}
|
||||
|
||||
it('can seed the railpack examples directly on a clean development database', function () {
|
||||
config()->set('app.env', 'local');
|
||||
|
||||
|
|
@ -44,14 +50,51 @@ function seedRailpackExamplePrerequisites(): void
|
|||
expect(StandaloneDocker::query()->find(0))->not->toBeNull();
|
||||
expect(GithubApp::query()->find(0))->not->toBeNull();
|
||||
expect(GitlabApp::query()->find(1))->not->toBeNull();
|
||||
expect(Project::query()->where('uuid', DevelopmentRailpackExamplesSeeder::PROJECT_UUID)->exists())->toBeTrue();
|
||||
expect(Application::query()->count())->toBe(count(DevelopmentRailpackExamplesSeeder::examples()));
|
||||
expect(Application::query()->count())->toBe(count(DevelopmentRailpackExamplesSeeder::examples()) * limaServers()->count());
|
||||
|
||||
$project = Project::query()
|
||||
->where('uuid', DevelopmentRailpackExamplesSeeder::PROJECT_UUID)
|
||||
->first();
|
||||
|
||||
expect($project)
|
||||
->not->toBeNull()
|
||||
->and($project->environments)->toHaveCount(limaServers()->count());
|
||||
|
||||
foreach (limaServers() as $limaServer) {
|
||||
$server = Server::query()->where('uuid', $limaServer['server_uuid'])->first();
|
||||
|
||||
expect($server)->not->toBeNull();
|
||||
expect($server->settings->sentinel_custom_url)->toBe('http://host.lima.internal:8000');
|
||||
expect(StandaloneDocker::query()->whereRelation('server', 'uuid', $limaServer['server_uuid'])->exists())->toBeTrue();
|
||||
expect($project->environments()->where('uuid', $limaServer['environment_uuid'])->exists())->toBeTrue();
|
||||
}
|
||||
});
|
||||
|
||||
it('seeds the railpack examples in development mode', function () {
|
||||
config()->set('app.env', 'local');
|
||||
|
||||
seedRailpackExamplePrerequisites();
|
||||
$legacyProject = Project::query()->create([
|
||||
'uuid' => 'railpack-examples-lima-ubuntu-2404',
|
||||
'name' => 'Railpack Examples - lima-ubuntu-2404',
|
||||
'description' => 'Legacy generated Railpack examples project',
|
||||
'team_id' => 0,
|
||||
]);
|
||||
Application::query()->create([
|
||||
'uuid' => 'lima-ubuntu-2404-railpack-nextjs-ssr',
|
||||
'name' => 'Legacy Railpack Next.js SSR Example',
|
||||
'repository_project_id' => DevelopmentRailpackExamplesSeeder::REPOSITORY_PROJECT_ID,
|
||||
'git_repository' => DevelopmentRailpackExamplesSeeder::GIT_REPOSITORY,
|
||||
'git_branch' => DevelopmentRailpackExamplesSeeder::GIT_BRANCH,
|
||||
'build_pack' => 'railpack',
|
||||
'ports_exposes' => '3000',
|
||||
'environment_id' => $legacyProject->environments()->first()->id,
|
||||
'destination_id' => 0,
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
'source_id' => 0,
|
||||
'source_type' => GithubApp::class,
|
||||
]);
|
||||
|
||||
$this->seed(DevelopmentRailpackExamplesSeeder::class);
|
||||
|
||||
$project = Project::query()
|
||||
|
|
@ -61,30 +104,58 @@ function seedRailpackExamplePrerequisites(): void
|
|||
expect($project)
|
||||
->not->toBeNull()
|
||||
->and($project->name)->toBe('Railpack Examples')
|
||||
->and($project->environments)->toHaveCount(1)
|
||||
->and($project->environments->first()->uuid)->toBe(DevelopmentRailpackExamplesSeeder::ENVIRONMENT_UUID);
|
||||
->and($project->environments)->toHaveCount(limaServers()->count());
|
||||
expect(Project::query()->pluck('uuid')->sort()->values()->all())->toBe([
|
||||
'project',
|
||||
DevelopmentRailpackExamplesSeeder::PROJECT_UUID,
|
||||
]);
|
||||
expect(Application::query()->where('uuid', 'lima-ubuntu-2404-railpack-nextjs-ssr')->exists())->toBeFalse();
|
||||
|
||||
$applications = $project->applications()->with('settings')->orderBy('uuid')->get();
|
||||
|
||||
expect($applications)->toHaveCount(count(DevelopmentRailpackExamplesSeeder::examples()));
|
||||
expect($applications)->toHaveCount(count(DevelopmentRailpackExamplesSeeder::examples()) * limaServers()->count());
|
||||
expect($applications->every(fn (Application $application) => $application->build_pack === 'railpack'))->toBeTrue();
|
||||
|
||||
$examples = collect(DevelopmentRailpackExamplesSeeder::examples())->keyBy('uuid');
|
||||
expect($applications->every(
|
||||
fn (Application $application) => $application->git_repository === ($examples->get($application->uuid)['git_repository'] ?? DevelopmentRailpackExamplesSeeder::GIT_REPOSITORY)
|
||||
fn (Application $application) => $application->git_repository === ($examples->get(str($application->uuid)->after('-')->value())['git_repository'] ?? DevelopmentRailpackExamplesSeeder::GIT_REPOSITORY)
|
||||
))->toBeTrue();
|
||||
expect($applications->every(
|
||||
fn (Application $application) => $application->git_branch === ($examples->get($application->uuid)['git_branch'] ?? DevelopmentRailpackExamplesSeeder::GIT_BRANCH)
|
||||
fn (Application $application) => $application->git_branch === ($examples->get(str($application->uuid)->after('-')->value())['git_branch'] ?? DevelopmentRailpackExamplesSeeder::GIT_BRANCH)
|
||||
))->toBeTrue();
|
||||
|
||||
$nestjs = $applications->firstWhere('uuid', 'railpack-nestjs');
|
||||
$angularStatic = $applications->firstWhere('uuid', 'railpack-angular-static');
|
||||
$eleventyStatic = $applications->firstWhere('uuid', 'railpack-eleventy-static');
|
||||
$pythonFlask = $applications->firstWhere('uuid', 'railpack-python-flask');
|
||||
$goGin = $applications->firstWhere('uuid', 'railpack-go-gin');
|
||||
$rust = $applications->firstWhere('uuid', 'railpack-rust');
|
||||
$githubDeployKey = $applications->firstWhere('uuid', 'railpack-github-deploy-key');
|
||||
$gitlabDeployKey = $applications->firstWhere('uuid', 'railpack-gitlab-deploy-key');
|
||||
$gitlabPublic = $applications->firstWhere('uuid', 'railpack-gitlab-public-example');
|
||||
foreach (limaServers() as $limaServer) {
|
||||
$limaEnvironment = $project->environments()
|
||||
->where('uuid', $limaServer['environment_uuid'])
|
||||
->first();
|
||||
|
||||
expect($limaEnvironment)
|
||||
->not->toBeNull()
|
||||
->and($limaEnvironment->name)->toBe($limaServer['environment_name']);
|
||||
|
||||
$limaApplications = $limaEnvironment->applications()->with('settings', 'destination.server')->orderBy('uuid')->get();
|
||||
|
||||
expect($limaApplications)->toHaveCount(count(DevelopmentRailpackExamplesSeeder::examples()));
|
||||
expect($limaApplications->every(fn (Application $application) => $application->build_pack === 'railpack'))->toBeTrue();
|
||||
expect($limaApplications->every(fn (Application $application) => str($application->uuid)->startsWith($limaServer['uuid_prefix'])))->toBeTrue();
|
||||
expect($limaApplications->every(fn (Application $application) => $application->destination->server->uuid === $limaServer['server_uuid']))->toBeTrue();
|
||||
expect($limaApplications->every(
|
||||
fn (Application $application) => $application->git_repository === ($examples->get(str($application->uuid)->after($limaServer['uuid_prefix'])->value())['git_repository'] ?? DevelopmentRailpackExamplesSeeder::GIT_REPOSITORY)
|
||||
))->toBeTrue();
|
||||
expect($limaApplications->every(
|
||||
fn (Application $application) => $application->git_branch === ($examples->get(str($application->uuid)->after($limaServer['uuid_prefix'])->value())['git_branch'] ?? DevelopmentRailpackExamplesSeeder::GIT_BRANCH)
|
||||
))->toBeTrue();
|
||||
}
|
||||
|
||||
$nestjs = $applications->firstWhere('uuid', 'ubuntu24-railpack-nestjs');
|
||||
$angularStatic = $applications->firstWhere('uuid', 'ubuntu24-railpack-angular-static');
|
||||
$eleventyStatic = $applications->firstWhere('uuid', 'ubuntu24-railpack-eleventy-static');
|
||||
$pythonFlask = $applications->firstWhere('uuid', 'ubuntu24-railpack-python-flask');
|
||||
$goGin = $applications->firstWhere('uuid', 'ubuntu24-railpack-go-gin');
|
||||
$rust = $applications->firstWhere('uuid', 'ubuntu24-railpack-rust');
|
||||
$githubDeployKey = $applications->firstWhere('uuid', 'ubuntu24-railpack-github-deploy-key');
|
||||
$gitlabDeployKey = $applications->firstWhere('uuid', 'ubuntu24-railpack-gitlab-deploy-key');
|
||||
$gitlabPublic = $applications->firstWhere('uuid', 'ubuntu24-railpack-gitlab-public-example');
|
||||
|
||||
expect($nestjs)
|
||||
->not->toBeNull()
|
||||
|
|
@ -156,6 +227,12 @@ function seedRailpackExamplePrerequisites(): void
|
|||
|
||||
expect(Project::query()->where('uuid', DevelopmentRailpackExamplesSeeder::PROJECT_UUID)->exists())->toBeFalse();
|
||||
expect(Application::query()->where('uuid', 'railpack-nextjs-ssr')->exists())->toBeFalse();
|
||||
|
||||
foreach (limaServers() as $limaServer) {
|
||||
expect(Project::query()->where('uuid', 'railpack-examples-lima-ubuntu-2404')->exists())->toBeFalse();
|
||||
expect(Project::query()->where('uuid', 'railpack-examples-lima-ubuntu-2604')->exists())->toBeFalse();
|
||||
expect(Application::query()->where('uuid', $limaServer['uuid_prefix'].'railpack-nextjs-ssr')->exists())->toBeFalse();
|
||||
}
|
||||
});
|
||||
|
||||
it('is idempotent when run multiple times', function () {
|
||||
|
|
@ -170,5 +247,14 @@ function seedRailpackExamplePrerequisites(): void
|
|||
->first();
|
||||
|
||||
expect($project)->not->toBeNull();
|
||||
expect($project->applications()->count())->toBe(count(DevelopmentRailpackExamplesSeeder::examples()));
|
||||
expect($project->applications()->count())->toBe(count(DevelopmentRailpackExamplesSeeder::examples()) * limaServers()->count());
|
||||
|
||||
foreach (limaServers() as $limaServer) {
|
||||
$limaEnvironment = $project->environments()
|
||||
->where('uuid', $limaServer['environment_uuid'])
|
||||
->first();
|
||||
|
||||
expect($limaEnvironment)->not->toBeNull();
|
||||
expect($limaEnvironment->applications()->count())->toBe(count(DevelopmentRailpackExamplesSeeder::examples()));
|
||||
}
|
||||
});
|
||||
|
|
|
|||
31
tests/Feature/ProjectSeederTest.php
Normal file
31
tests/Feature/ProjectSeederTest.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Project;
|
||||
use Database\Seeders\PrivateKeySeeder;
|
||||
use Database\Seeders\ProjectSeeder;
|
||||
use Database\Seeders\TeamSeeder;
|
||||
use Database\Seeders\UserSeeder;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('seeds the first project with lima environments', function () {
|
||||
$this->seed([
|
||||
UserSeeder::class,
|
||||
TeamSeeder::class,
|
||||
PrivateKeySeeder::class,
|
||||
ProjectSeeder::class,
|
||||
]);
|
||||
|
||||
$project = Project::query()
|
||||
->where('uuid', 'project')
|
||||
->first();
|
||||
|
||||
expect($project)
|
||||
->not->toBeNull()
|
||||
->and($project->name)->toBe('My first project')
|
||||
->and($project->environments()->pluck('uuid', 'name')->all())->toBe([
|
||||
'ubuntu24' => 'ubuntu24',
|
||||
'ubuntu26' => 'ubuntu26',
|
||||
]);
|
||||
});
|
||||
96
tests/Feature/ServerLimaStartCommandTest.php
Normal file
96
tests/Feature/ServerLimaStartCommandTest.php
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\ProxyStatus;
|
||||
use App\Enums\ProxyTypes;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\PrivateKey;
|
||||
use App\Models\Server;
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
InstanceSettings::unguarded(function () {
|
||||
InstanceSettings::query()->create([
|
||||
'id' => 0,
|
||||
'is_registration_enabled' => true,
|
||||
]);
|
||||
});
|
||||
|
||||
$this->user = User::factory()->create();
|
||||
$this->team = Team::factory()->create(['show_boarding' => false]);
|
||||
$this->team->members()->attach($this->user->id, ['role' => 'owner']);
|
||||
|
||||
$this->actingAs($this->user);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
$this->privateKey = PrivateKey::create([
|
||||
'team_id' => $this->team->id,
|
||||
'name' => 'Test Key',
|
||||
'private_key' => '-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk
|
||||
hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA
|
||||
AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV
|
||||
uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
||||
-----END OPENSSH PRIVATE KEY-----',
|
||||
]);
|
||||
});
|
||||
|
||||
it('shows the lima start command on lima server general pages in development', function () {
|
||||
config()->set('app.env', 'local');
|
||||
|
||||
foreach (limaStartCommandDefinitions() as $definition) {
|
||||
$server = createServerForLimaStartCommandTest($definition['uuid'], $definition['port']);
|
||||
|
||||
$this->get(route('server.show', ['server_uuid' => $server->uuid]))
|
||||
->assertSuccessful()
|
||||
->assertSee('Start this Lima VM locally')
|
||||
->assertSee($definition['command']);
|
||||
}
|
||||
});
|
||||
|
||||
it('does not show the lima start command outside development', function () {
|
||||
config()->set('app.env', 'testing');
|
||||
|
||||
$server = createServerForLimaStartCommandTest('lima-ubuntu-2404', 2222);
|
||||
|
||||
$this->get(route('server.show', ['server_uuid' => $server->uuid]))
|
||||
->assertSuccessful()
|
||||
->assertDontSee('Start this Lima VM locally')
|
||||
->assertDontSee('limactl start --yes --name=coolify-lima-ubuntu-2404 docker/lima/ubuntu-2404.yaml');
|
||||
});
|
||||
|
||||
function createServerForLimaStartCommandTest(string $uuid, int $port): Server
|
||||
{
|
||||
return Server::factory()->create([
|
||||
'uuid' => $uuid,
|
||||
'name' => $uuid,
|
||||
'ip' => 'host.docker.internal',
|
||||
'port' => $port,
|
||||
'team_id' => test()->team->id,
|
||||
'private_key_id' => test()->privateKey->id,
|
||||
'proxy' => [
|
||||
'type' => ProxyTypes::TRAEFIK->value,
|
||||
'status' => ProxyStatus::EXITED->value,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
function limaStartCommandDefinitions(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'uuid' => 'lima-ubuntu-2404',
|
||||
'port' => 2222,
|
||||
'command' => 'limactl start --yes --name=coolify-lima-ubuntu-2404 docker/lima/ubuntu-2404.yaml',
|
||||
],
|
||||
[
|
||||
'uuid' => 'lima-ubuntu-2604',
|
||||
'port' => 2223,
|
||||
'command' => 'limactl start --yes --name=coolify-lima-ubuntu-2604 docker/lima/ubuntu-2604.yaml',
|
||||
],
|
||||
];
|
||||
}
|
||||
66
tests/Feature/ServerSeederTest.php
Normal file
66
tests/Feature/ServerSeederTest.php
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Server;
|
||||
use Database\Seeders\PrivateKeySeeder;
|
||||
use Database\Seeders\ServerSeeder;
|
||||
use Database\Seeders\TeamSeeder;
|
||||
use Database\Seeders\UserSeeder;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
function limaServerDefinitions(): array
|
||||
{
|
||||
return [
|
||||
['uuid' => 'lima-ubuntu-2404', 'port' => 2222, 'template' => 'ubuntu-2404.yaml', 'memory' => '2GiB', 'disk' => '20GiB'],
|
||||
['uuid' => 'lima-ubuntu-2604', 'port' => 2223, 'template' => 'ubuntu-2604.yaml', 'memory' => '2GiB', 'disk' => '20GiB'],
|
||||
];
|
||||
}
|
||||
|
||||
it('seeds the development testing host and lima servers', function () {
|
||||
$this->seed([
|
||||
UserSeeder::class,
|
||||
TeamSeeder::class,
|
||||
PrivateKeySeeder::class,
|
||||
ServerSeeder::class,
|
||||
]);
|
||||
|
||||
$testingHost = Server::query()->where('uuid', 'localhost')->first();
|
||||
|
||||
expect($testingHost)
|
||||
->not->toBeNull()
|
||||
->and($testingHost->ip)->toBe('coolify-testing-host');
|
||||
|
||||
foreach (limaServerDefinitions() as $definition) {
|
||||
$limaServer = Server::query()->where('uuid', $definition['uuid'])->first();
|
||||
|
||||
expect($limaServer)
|
||||
->not->toBeNull()
|
||||
->and($limaServer->name)->toBe($definition['uuid'])
|
||||
->and($limaServer->ip)->toBe('host.docker.internal')
|
||||
->and($limaServer->port)->toBe($definition['port'])
|
||||
->and($limaServer->user)->toBe('root')
|
||||
->and($limaServer->team_id)->toBe(0)
|
||||
->and($limaServer->private_key_id)->toBe(1)
|
||||
->and($limaServer->settings)->not->toBeNull()
|
||||
->and($limaServer->settings->sentinel_custom_url)->toBe('http://host.lima.internal:8000')
|
||||
->and($limaServer->destinations())->toHaveCount(1);
|
||||
}
|
||||
});
|
||||
|
||||
it('keeps the lima templates aligned with the seeded servers', function () {
|
||||
foreach (limaServerDefinitions() as $definition) {
|
||||
$template = Yaml::parseFile(base_path("docker/lima/{$definition['template']}"));
|
||||
$script = data_get($template, 'provision.0.script');
|
||||
|
||||
expect(data_get($template, 'ssh.localPort'))
|
||||
->toBe($definition['port'])
|
||||
->and(data_get($template, 'memory'))->toBe($definition['memory'])
|
||||
->and(data_get($template, 'disk'))->toBe($definition['disk'])
|
||||
->and(data_get($template, 'containerd.system'))->toBeFalse()
|
||||
->and(data_get($template, 'containerd.user'))->toBeFalse()
|
||||
->and(data_get($template, 'networks'))->toBeNull()
|
||||
->and($script)->toContain('ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFuGmoeGq/pojrsyP1pszcNVuZx9iFkCELtxrh31QJ68');
|
||||
}
|
||||
});
|
||||
Loading…
Reference in a new issue