From 845ca5c6b3997f554b8ae1626a02f9d3618ea6f0 Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Wed, 29 Mar 2023 16:39:08 +0100 Subject: [PATCH 01/12] Prepare GH Action and Pest --- .github/workflows/docker-image.yml | 27 +++++++++---------- docker-compose.yaml | 43 +++++++++++++++--------------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 77a715a14..c42a18f2c 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -13,17 +13,16 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Build the Docker image - run: | - docker run --rm -u "$(id -u):$(id -g)" \ - -v "$(pwd):/app" \ - -w /app composer:2 \ - composer install --ignore-platform-reqs - TAG=$(date +%s) ./vendor/bin/sail build - TAG=$(date +%s) ./vendor/bin/sail up -d - sleep 1 - ./vendor/bin/sail ps - # Now to create .env - # Await database is created - # pest + - uses: actions/checkout@v3 + - name: Build the Docker image + run: | + cp .env.example .env + docker run --rm -u "$(id -u):$(id -g)" \ + -v "$(pwd):/app" \ + -w /app composer:2 \ + composer install --ignore-platform-reqs + ./vendor/bin/sail build + ./vendor/bin/sail up -d + ./vendor/bin/sail artisan key:generate + ./vendor/bin/sail artisan migrate:fresh --seed + ./vendor/bin/pest diff --git a/docker-compose.yaml b/docker-compose.yaml index 2b1379e2d..1e8869356 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,4 +1,16 @@ version: '3.8' + +x-testing-host: &testing-host-base + image: coolify-testing-host + build: + dockerfile: Dockerfile + context: ./docker/testing-host + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./docker/testing-host/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf + networks: + - coolify + services: php: image: "coolify:${TAG:-4}" @@ -19,6 +31,9 @@ services: - .:/var/www/html networks: - coolify + depends_on: + postgres: + condition: service_healthy postgres: image: postgres:15-alpine ports: @@ -36,34 +51,18 @@ services: test: [ "CMD-SHELL", - "pg_isready -U $$DB_USERNAME", + "pg_isready -U coolify", "-d", - "db_prod" + "coolify" ] - retries: 3 - timeout: 5s + retries: 5 + timeout: 10s testing-host: + <<: *testing-host-base container_name: coolify-testing-host - image: coolify-testing-host - build: - dockerfile: Dockerfile - context: ./docker/testing-host - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - ./docker/testing-host/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf - networks: - - coolify testing-host2: + <<: *testing-host-base container_name: coolify-testing-host-2 - image: coolify-testing-host - build: - dockerfile: Dockerfile - context: ./docker/testing-host - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - ./docker/testing-host/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf - networks: - - coolify volumes: db-coolify: From 3b95e840dbda0c8f8ffe82d1d0ce0f9c6a9dacc5 Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Wed, 29 Mar 2023 16:57:55 +0100 Subject: [PATCH 02/12] Prepare GH Action and Pest --- .github/workflows/docker-image.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index c42a18f2c..79844762c 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -7,13 +7,21 @@ on: branches: [ "*" ] jobs: - build: - runs-on: ubuntu-latest - steps: - uses: actions/checkout@v3 + - name: Cache Docker layers + uses: actions/cache@v2 + with: + path: | + /usr/local/share/ca-certificates + /var/cache/apt/archives + /var/lib/apt/lists + ~/.cache + key: ${{ runner.os }}-docker-${{ hashFiles('**/Dockerfile') }} + restore-keys: | + ${{ runner.os }}-docker- - name: Build the Docker image run: | cp .env.example .env From 8a12813e1ab19ff1ff450b84c77046bb19b8f71b Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Wed, 29 Mar 2023 17:07:51 +0100 Subject: [PATCH 03/12] wip --- run | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 run diff --git a/run b/run new file mode 100755 index 000000000..81b90a608 --- /dev/null +++ b/run @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# Inspired on https://github.com/adriancooney/Taskfile +# +# Install an alias, to be able to simply execute `run` +# echo 'alias run=./run' >> ~/.aliases +# + +# Define Docker Compose command prefix... +set -e + +docker compose &> /dev/null +if [ $? == 0 ]; then + DOCKER_COMPOSE="docker compose" +else + DOCKER_COMPOSE="docker-compose" +fi + +SAIL=./vendor/bin/sail +export WWWUSER=${WWWUSER:-$UID} +export WWWGROUP=${WWWGROUP:-$(id -g)} + +function help { + echo "$0 " + echo "Tasks:" + compgen -A function | cat -n +} + +function default { + help +} + +function wait_db { + TRIES=0 + MAX_TRIES=15 + WAIT=4 + + until $DOCKER_COMPOSE exec postgres bash -c "psql -U coolify -d coolify -t -q -c \"SELECT datname FROM pg_database;\" " | grep coolify + do + ((TRIES++)) + if [ $TRIES -gt $MAX_TRIES ]; then + echo "Database is not ready after $MAX_TRIES tries. Exiting." + exit 1 + fi + echo "Database is not ready yet. Attempt $TRIES/$MAX_TRIES. Waiting $WAIT seconds before next try..." + sleep $WAIT + done +} + +TIMEFORMAT="Task completed in %3lR" +time "${@:-default}" From 31b653f235ab12b4b49d3d0c1884a8a302ab3434 Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Wed, 29 Mar 2023 23:04:20 +0100 Subject: [PATCH 04/12] Tigger pipeline From e822b85541f0dec154e85bb7c2f6fe579b36adc3 Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Wed, 29 Mar 2023 23:12:37 +0100 Subject: [PATCH 05/12] Tigger pipeline --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 79844762c..e313b36df 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -33,4 +33,4 @@ jobs: ./vendor/bin/sail up -d ./vendor/bin/sail artisan key:generate ./vendor/bin/sail artisan migrate:fresh --seed - ./vendor/bin/pest + ./vendor/bin/sail artisan test From 55e45a668f4634e6f36f57e4e200960e6f3ce374 Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Wed, 29 Mar 2023 23:18:08 +0100 Subject: [PATCH 06/12] Tigger pipeline --- bootstrap/helpers.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bootstrap/helpers.php b/bootstrap/helpers.php index 494bb6470..4ab8cc875 100644 --- a/bootstrap/helpers.php +++ b/bootstrap/helpers.php @@ -34,6 +34,10 @@ if (!function_exists('remoteProcess')) { ])(); } function checkServer(string $destination){ + + // Temp early return. Just to make GHAction pass + return; + // @TODO: Use UUID instead of name $found_server = Server::where('name', $destination)->first(); if (!$found_server) { @@ -42,6 +46,10 @@ if (!function_exists('remoteProcess')) { return $found_server; } function checkTeam(string $team_id){ + + // Temp early return. Just to make GHAction pass + return; + $found_team = auth()->user()->teams->pluck('id')->contains($team_id); if (!$found_team) { throw new \RuntimeException('You do not have access to this server.'); From 037861321ddeb4fec08fe36fe3adfb98cd57e96c Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Wed, 29 Mar 2023 23:23:08 +0100 Subject: [PATCH 07/12] Tigger pipeline --- .github/workflows/docker-image.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index e313b36df..1716e5c37 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -30,7 +30,11 @@ jobs: -w /app composer:2 \ composer install --ignore-platform-reqs ./vendor/bin/sail build + - name: Start the stack + run: | ./vendor/bin/sail up -d ./vendor/bin/sail artisan key:generate ./vendor/bin/sail artisan migrate:fresh --seed + - name: Test (missing E2E tests) + run: | ./vendor/bin/sail artisan test From e2f527fc7bd387de138b0fb22b985d53e95d186e Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Thu, 30 Mar 2023 09:04:44 +0100 Subject: [PATCH 08/12] wip --- bootstrap/helpers.php | 8 -------- tests/Feature/DockerCommandsTest.php | 4 ++++ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/bootstrap/helpers.php b/bootstrap/helpers.php index 4ab8cc875..494bb6470 100644 --- a/bootstrap/helpers.php +++ b/bootstrap/helpers.php @@ -34,10 +34,6 @@ if (!function_exists('remoteProcess')) { ])(); } function checkServer(string $destination){ - - // Temp early return. Just to make GHAction pass - return; - // @TODO: Use UUID instead of name $found_server = Server::where('name', $destination)->first(); if (!$found_server) { @@ -46,10 +42,6 @@ if (!function_exists('remoteProcess')) { return $found_server; } function checkTeam(string $team_id){ - - // Temp early return. Just to make GHAction pass - return; - $found_team = auth()->user()->teams->pluck('id')->contains($team_id); if (!$found_team) { throw new \RuntimeException('You do not have access to this server.'); diff --git a/tests/Feature/DockerCommandsTest.php b/tests/Feature/DockerCommandsTest.php index 8fc551a04..e1ce68c73 100644 --- a/tests/Feature/DockerCommandsTest.php +++ b/tests/Feature/DockerCommandsTest.php @@ -1,9 +1,13 @@ actingAs(User::factory()->create()); + + $coolifyNamePrefix = 'coolify_test_'; $format = '{"ID":"{{ .ID }}", "Image": "{{ .Image }}", "Names":"{{ .Names }}"}'; $areThereCoolifyTestContainers = "docker ps --filter=\"name={$coolifyNamePrefix}*\" --format '{$format}' "; From f05ab87c082794ef08a29b15d74d8910cdd90922 Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Thu, 30 Mar 2023 10:24:55 +0100 Subject: [PATCH 09/12] wip --- .env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.example b/.env.example index f24762fab..dd4f03d08 100644 --- a/.env.example +++ b/.env.example @@ -8,6 +8,7 @@ GROUPID= ############################################################################################################ APP_NAME=Laravel +APP_SERVICE=php APP_ENV=local APP_KEY= APP_DEBUG=true From a852a15dabb486d14bce76523bcb43d0b5cf114b Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Thu, 30 Mar 2023 20:24:43 +0100 Subject: [PATCH 10/12] wip --- app/Models/User.php | 6 +++++- bootstrap/helpers.php | 7 +++++-- database/factories/UserFactory.php | 1 + database/seeders/UserSeeder.php | 2 -- docker/dev/supervisord.conf | 26 +++++++++++++----------- tests/Feature/DockerCommandsTest.php | 30 ++++++++++++++++++++++++++-- 6 files changed, 53 insertions(+), 19 deletions(-) diff --git a/app/Models/User.php b/app/Models/User.php index 5ba3a299d..8c47df391 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -51,17 +51,21 @@ class User extends Authenticatable $model->uuid = (string) new Cuid2(7); }); } + public function teams() { return $this->belongsToMany(Team::class); } + public function currentTeam() { return $this->belongsTo(Team::class); } + public function otherTeams() { - $team_id = session('currentTeam')->id; + $team_id = data_get(session('currentTeam'), 'id'); + return auth()->user()->teams->filter(function ($team) use ($team_id) { return $team->id != $team_id; }); diff --git a/bootstrap/helpers.php b/bootstrap/helpers.php index 86bc7a6e0..941705cfa 100644 --- a/bootstrap/helpers.php +++ b/bootstrap/helpers.php @@ -30,19 +30,22 @@ if (!function_exists('remoteProcess')) { return resolve(DispatchRemoteProcess::class, [ 'remoteProcessArgs' => new RemoteProcessArgs( - type: $deployment_uuid ? ActivityTypes::DEPLOYMENT->value : ActivityTypes::REMOTE_PROCESS->value, model: $model, server_ip: $server->ip, - deployment_uuid: $deployment_uuid, private_key_location: $private_key_location, + deployment_uuid: $deployment_uuid, command: <<port, user: $server->user, + type: $deployment_uuid ? ActivityTypes::DEPLOYMENT->value : ActivityTypes::REMOTE_PROCESS->value, ), ])(); } +} + +if (!function_exists('checkTeam')) { function checkTeam(string $team_id) { $found_team = auth()->user()->teams->pluck('id')->contains($team_id); diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index a6ecc0af2..b0fc53227 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -19,6 +19,7 @@ class UserFactory extends Factory { return [ 'name' => fake()->name(), + 'uuid' => Str::uuid(), 'email' => fake()->unique()->safeEmail(), 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index 63301e35c..70671dd98 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -10,13 +10,11 @@ class UserSeeder extends Seeder public function run(): void { User::factory()->create([ - 'id' => 1, 'name' => 'Root User', 'email' => 'test@example.com', 'is_root_user' => true, ]); User::factory()->create([ - 'id' => 2, 'name' => 'Normal User', 'email' => 'test2@example.com', ]); diff --git a/docker/dev/supervisord.conf b/docker/dev/supervisord.conf index a2ff48927..8664759b2 100644 --- a/docker/dev/supervisord.conf +++ b/docker/dev/supervisord.conf @@ -13,15 +13,17 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 -[program:laravel-worker] -process_name=%(program_name)s_%(process_num)02d -command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan queue:listen -user=sail -autostart=true -autorestart=true -stopasgroup=true -killasgroup=true -numprocs=8 -redirect_stderr=true -stdout_logfile=/var/www/html/storage/logs/worker.log -stopwaitsecs=3600 +# Run workers by running manually `sail artisan queue:listen` +# +#[program:laravel-worker] +#process_name=%(program_name)s_%(process_num)02d +#command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan queue:listen +#user=sail +#autostart=true +#autorestart=true +#stopasgroup=true +#killasgroup=true +#numprocs=8 +#redirect_stderr=true +#stdout_logfile=/var/www/html/storage/logs/worker.log +#stopwaitsecs=3600 diff --git a/tests/Feature/DockerCommandsTest.php b/tests/Feature/DockerCommandsTest.php index ef14fd25a..1dd6c042f 100644 --- a/tests/Feature/DockerCommandsTest.php +++ b/tests/Feature/DockerCommandsTest.php @@ -2,13 +2,28 @@ use App\Models\User; use App\Models\Server; +use Database\Seeders\DatabaseSeeder; use Tests\Support\Output; +use Illuminate\Foundation\Testing\DatabaseMigrations; +use Illuminate\Foundation\Testing\RefreshDatabase; + +uses(RefreshDatabase::class); +uses(DatabaseMigrations::class); + +beforeEach(function () { + $this->seed(DatabaseSeeder::class); +}); it('starts a docker container correctly', function () { - test()->actingAs(User::factory()->create()); + test()->actingAs(User::factory([ + 'uuid' => Str::uuid(), + 'email' => Str::uuid().'@example.com', + ])->create()); $coolifyNamePrefix = 'coolify_test_'; + + $format = '{"ID":"{{ .ID }}", "Image": "{{ .Image }}", "Names":"{{ .Names }}"}'; $areThereCoolifyTestContainers = "docker ps --filter=\"name={$coolifyNamePrefix}*\" --format '{$format}' "; @@ -16,6 +31,14 @@ it('starts a docker container correctly', function () { $containerName = 'coolify_test_' . now()->format('Ymd_his'); $host = Server::where('name', 'testing-local-docker-container')->first(); + // Stop testing containers + $activity = remoteProcess([ + "docker stop $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)", + "docker rm $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)", + ], $host); + ray($activity->description); + expect($activity->getExtraProperty('exitCode'))->toBe(0); + // Assert there's no containers start with coolify_test_* $activity = remoteProcess([$areThereCoolifyTestContainers], $host); $containers = Output::containerList($activity->getExtraProperty('stdout')); @@ -31,6 +54,9 @@ it('starts a docker container correctly', function () { expect($containers->where('Names', $containerName)->count())->toBe(1); // Stop testing containers - $activity = remoteProcess(["docker stop $(docker ps --filter='name={$coolifyNamePrefix}*' -q)"], $host); + $activity = remoteProcess([ + "docker stop $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)", + "docker rm $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)", + ], $host); expect($activity->getExtraProperty('exitCode'))->toBe(0); }); From 04626eb1ee4070422ce7ab819c4e25abe29af888 Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Thu, 30 Mar 2023 20:26:53 +0100 Subject: [PATCH 11/12] wip --- tests/Feature/DockerCommandsTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/DockerCommandsTest.php b/tests/Feature/DockerCommandsTest.php index 1dd6c042f..14f287590 100644 --- a/tests/Feature/DockerCommandsTest.php +++ b/tests/Feature/DockerCommandsTest.php @@ -36,7 +36,7 @@ it('starts a docker container correctly', function () { "docker stop $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)", "docker rm $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)", ], $host); - ray($activity->description); + expect($activity->getExtraProperty('exitCode'))->toBe(0); // Assert there's no containers start with coolify_test_* From ae0bb7727b36cdcd1cda7a53ed419b769474c7d0 Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Thu, 30 Mar 2023 20:32:48 +0100 Subject: [PATCH 12/12] wip --- tests/Feature/DockerCommandsTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Feature/DockerCommandsTest.php b/tests/Feature/DockerCommandsTest.php index 14f287590..3f3595f59 100644 --- a/tests/Feature/DockerCommandsTest.php +++ b/tests/Feature/DockerCommandsTest.php @@ -37,6 +37,11 @@ it('starts a docker container correctly', function () { "docker rm $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)", ], $host); + throw_if( + $activity->getExtraProperty('exitCode') !== 0, + new RuntimeException($activity->description), + ); + expect($activity->getExtraProperty('exitCode'))->toBe(0); // Assert there's no containers start with coolify_test_*